题解 | 同步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 [$clog2(DEPTH):0] w_ptr; reg [$clog2(DEPTH):0] r_ptr; dual_port_RAM #( .DEPTH (DEPTH), .WIDTH (WIDTH) ) U_dual_port_RAM( .wclk (clk ), .wenc (winc ), .waddr (w_ptr[$clog2(DEPTH)-1:0]), .wdata (wdata), .rclk (clk), .renc (rinc), .raddr (r_ptr[$clog2(DEPTH)-1:0]), .rdata (rdata) ); always @(posedge clk or negedge rst_n)begin if(!rst_n)begin w_ptr <= 'd0; end else if(winc && !wfull)begin w_ptr <= w_ptr + 1; end end always @(posedge clk or negedge rst_n)begin if(!rst_n)begin r_ptr <= 'd0; end else if(rinc && !rempty)begin r_ptr <= r_ptr +1 ; end end always @(posedge clk or negedge rst_n)begin if(!rst_n)begin wfull <= 'd0; end else if(w_ptr[$clog2(DEPTH)] != r_ptr[$clog2(DEPTH)] && w_ptr[$clog2(DEPTH)-1:0] == r_ptr[$clog2(DEPTH)-1:0])begin wfull <= 1 ; end else begin wfull <= 'd0; end end always @(posedge clk or negedge rst_n)begin if(!rst_n)begin rempty <= 'd0; end else if(w_ptr == r_ptr)begin rempty <= 1 ; end else begin rempty <= 'd0; end end endmodule