题解 | #同步FIFO#
同步FIFO
https://www.nowcoder.com/practice/3ece2bed6f044ceebd172a7bf5cfb416
`timescale 1ns/1ns /**********************************RAM************************************/ module dual_port_RAM #(parameter DEPTH = 16, parameter WIDTH = 8)( input wclk ,input wenc ,input [$clog2(DEPTH)-1:0] waddr //深度对2取对数,得到地址的位宽。 ,input [WIDTH-1:0] wdata //数据写入 ,input rclk ,input renc ,input [$clog2(DEPTH)-1:0] raddr //深度对2取对数,得到地址的位宽。 ,output reg [WIDTH-1:0] rdata //数据输出 ); reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1]; always @(posedge wclk) begin if(wenc) RAM_MEM[waddr] <= wdata; end always @(posedge rclk) begin if(renc) rdata <= RAM_MEM[raddr]; end endmodule /**********************************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 wire [WIDTH-1:0] rdata ); reg [WIDTH-1:0] fifo_buffer [DEPTH-1:0]; reg [$clog2(DEPTH)-1:0] wr_addr; reg [$clog2(DEPTH)-1:0] rd_addr; reg [$clog2(DEPTH):0] fifo_cnt; reg [WIDTH-1:0] read_data; //读操作 always @(posedge clk or negedge rst_n) begin if(~rst_n) rd_addr <= 0; else if(~rempty & rinc) begin read_data <= fifo_buffer[rd_addr]; rd_addr <= rd_addr + 1'b1; end end //写操作 always @(posedge clk or negedge rst_n) begin if(~rst_n) wr_addr <= 0; else if(~wfull & winc) begin fifo_buffer[wr_addr] <= wdata; wr_addr <= wr_addr + 1'b1; end end //计数器 always @(posedge clk or negedge rst_n) begin if(~rst_n) fifo_cnt <= 0; else begin case({winc,rinc}) 2'b00: fifo_cnt <= fifo_cnt; 2'b01: begin if(~fifo_cnt) fifo_cnt <= fifo_cnt - 1'b1; end 2'b10: begin if(~(fifo_cnt == DEPTH)) fifo_cnt <= fifo_cnt + 1'b1; end 2'b11: fifo_cnt <= fifo_cnt; default: ; endcase end end always @(posedge clk or negedge rst_n) begin if(~rst_n) begin wfull <= 0; rempty <= 0; end else begin wfull = (fifo_cnt == DEPTH)? 1'b1 : 0; rempty = (fifo_cnt == 0)? 1'b1 : 0; end end assign rdata = read_data; endmodule