手撕程式碼——同步FIFO
阿新 • • 發佈:2022-03-07
手撕程式碼——同步FIFO
module synfifo( input clk, input rst_n, input rd_en, input wr_en, output reg full, output reg empty, input [7:0] datain, output reg [7:0] dataout ); reg [7:0] RAM_DATA [511:0]; reg [8:0] r_addr; reg [8:0] w_addr; reg [8:0] f_cnt; wire rd_allow; wire wr_allow; assign rd_allow = rd_en && !empty; assign wr_allow = wr_en && !full; //DUALRAM always @(posedge clk) begin if(wr_allow) begin RAM_DATA[w_addr] <=datain; end end always @(posedge clk) begin if(rd_allow) begin dataout<=RAM_DATA[r_addr]; end end //empty和full賦值 always @(posedge clk ) begin if(rst_n) begin empty <=1'b1; end else begin empty <= (!wr_en) && (f_cnt[8:1]==8'b0) &&(f_cnt[0]==0 || rd_en); end end always @(posedge clk ) begin if(rst_n) begin full <=1'b1; end else begin full <= (!rd_en) && (f_cnt[8:1]==8'hff) &&(f_cnt[0]==1 || wr_en); end end //讀寫地址變化 always @(posedge clk) begin if(rst_n) begin r_addr <=9'd0; end else if (rd_allow) begin r_addr <=r_addr+1'b1; end else begin r_addr <=r_addr; end end always @(posedge clk) begin if(rst_n) begin w_addr <=9'd0; end else if (wr_allow) begin w_addr <=w_addr+1'b1; end else begin w_addr <=w_addr; end end //資料指標變化 always @(posedge clk) begin if(rst_n) begin f_cnt <=9'd0; end else if ((rd_allow && !wr_allow ) ||(!rd_allow && wr_allow))begin if (wr_allow) begin f_cnt<=f_cnt+1'b1; end else begin f_cnt <=f_cnt-1'b1; end end else begin f_cnt <=f_cnt; end end endmodule