题解 | #同步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 ); //地址位宽 parameter addr_lengt=$clog2(DEPTH); //读地址与写地址 reg[addr_lengt:0]raddr_fifo; reg[addr_lengt:0]waddr_fifo; //读写地址变化 always@(posedge clk or negedge rst_n)begin if(~rst_n) waddr_fifo<=0; else if(winc&&!wfull) waddr_fifo<=waddr_fifo+1; end always@(posedge clk or negedge rst_n)begin if(~rst_n) raddr_fifo<=0; else if(rinc&&!rempty) raddr_fifo<=raddr_fifo+1; end //读写地址指针point reg[addr_lengt:0]read_point; reg[addr_lengt:0]write_point; always@(*)begin write_point=waddr_fifo; read_point=raddr_fifo; end /*用格雷码后不知道原因输出会延后DEPTH个时钟周期,在寻找原因中 //读写地址指针格雷码 wire [addr_lengt:0]read_point_gray; wire [addr_lengt:0]write_point_gray; */ assign write_point_gray=(write_point>>1)^write_point; assign read_point_gray=(read_point>>1)^read_point; //读空写满判断 always@(posedge clk or negedge rst_n)begin if(~rst_n) wfull<=0; else wfull<=(write_point=={~read_point[addr_lengt],read_point[addr_lengt-1:0]}); end always@(posedge clk or negedge rst_n)begin if(~rst_n) rempty<=0; else rempty<=(read_point==write_point); end wire wen; wire ren; assign wen=winc&!wfull; assign ren=rinc&!rempty; dual_port_RAM #(.DEPTH(DEPTH), .WIDTH(WIDTH) )dual_port_RAM( .wclk(clk), .waddr(waddr_fifo[addr_lengt-1:0]), .wenc(wen), .wdata(wdata), .rclk(clk), .raddr(raddr_fifo[addr_lengt-1:0]), .renc(ren), .rdata(rdata) ); endmodule