题解 | #同步FIFO#
同步FIFO
https://www.nowcoder.com/practice/3ece2bed6f044ceebd172a7bf5cfb416
/**********************************SFIFO************************************/ module sfifo#( parameter WIDTH = 8, parameter DEPTH = 16 )( input clk , input rst_n , input winc , input rinc , input [WIDTH-1:0] wdata , output reg wfull , output reg rempty , output reg [WIDTH-1:0] rdata ); localparam ADDR_WIDTH = $clog2(DEPTH); // 读写计数 -扩展1位 reg [ADDR_WIDTH:0] wr_cnt; reg [ADDR_WIDTH:0] rd_cnt; // 读写扩展位 wire wr_msb; wire rd_msb; // 读写ram地址 wire[ADDR_WIDTH-1:0] wr_addr; wire[ADDR_WIDTH-1:0] rd_addr; // 读写使能 wire wr_en; wire rd_en; assign wr_msb = wr_cnt[ADDR_WIDTH]; assign rd_msb = rd_cnt[ADDR_WIDTH]; assign wr_addr = wr_cnt[ADDR_WIDTH-1:0]; assign rd_addr = rd_cnt[ADDR_WIDTH-1:0]; assign wr_en = winc && (~wfull); assign rd_en = rinc && (~rempty); /************************* 读写计数 ****************************/ // write always@(posedge clk or negedge rst_n)begin if(!rst_n) wr_cnt <= 'd0; else if(wr_en) wr_cnt <= wr_cnt + 'd1; else wr_cnt <= wr_cnt; end // read always@(posedge clk or negedge rst_n)begin if(!rst_n) rd_cnt <= 'd0; else if(rd_en) rd_cnt <= rd_cnt + 'd1; else rd_cnt <= rd_cnt; end /************************* RAM ****************************/ // memory reg [WIDTH-1:0] mem[DEPTH-1:0]; // write always@(posedge clk)begin if(wr_en) mem[wr_addr] <= wdata; else mem[wr_addr] <= mem[wr_addr]; end // read always@(posedge clk)begin if(rd_en) rdata <= mem[rd_addr]; // 下面这样写还不行了 //else // rdata <= 'd0; end /************************* rempty and wfull ****************************/ // 按这题意思 复位置0 时钟上升沿开始变化 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin rempty <= 1'b0; wfull <= 1'b0; end else begin rempty <= (wr_msb == rd_msb) && (wr_addr == rd_addr); wfull <= (wr_msb != rd_msb) && (wr_addr == rd_addr); end end endmodule