题解 | #同步FIFO#
同步FIFO
https://www.nowcoder.com/practice/e5e86054a0ce4355b9dfc08238f25f5f
`timescale 1ns/1ns /**********************************RAM************************************/ module dual_port_RAM #(parameter DEPTH = 16, parameter WIDTH = 8)( input wclk ,input wenc ,input [$clog2(DEPTH)-1:0] waddr ,input [WIDTH-1:0] wdata ,input rclk ,input renc ,input [$clog2(DEPTH)-1:0] raddr ,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 ); initial begin wfull=0; rempty=0;end reg [$clog2(DEPTH):0] wdata_MSB = 0; //带一位扩展位MSB的写入地址 reg [$clog2(DEPTH):0] rdata_MSB = 0; //带一位扩展位MSB的读出地址 wire [$clog2(DEPTH)-1:0] wdata_pre; wire [$clog2(DEPTH)-1:0] rdata_pre; reg [WIDTH-1:0] mem [DEPTH-1:0]; reg [WIDTH-1:0] dout; assign rdata = dout; assign wdata_pre = wdata_MSB[$clog2(DEPTH)-1:0]; //得到不含MSB的真实写入地址 assign rdata_pre = rdata_MSB[$clog2(DEPTH)-1:0]; //得到不含MSB的真实读出地址 wire full_singal; wire empty_singal; assign full_singal = (wdata_MSB[$clog2(DEPTH)] != rdata_MSB[$clog2(DEPTH)] && wdata_pre==rdata_pre)?1:0; //写满信号为1代表MSB位不同且WIDTH-1位相同 assign empty_singal = (wdata_MSB[$clog2(DEPTH)] == rdata_MSB[$clog2(DEPTH)] && wdata_pre==rdata_pre)?1:0;//读空信号为1代表MSB位相同且WIDTH-1位相同 always@(posedge clk) begin if(!rst_n) begin wdata_MSB <=0; rdata_MSB <=0;end else begin wfull <= full_singal; rempty <= empty_singal; if(!full_singal && winc) begin mem[wdata_pre] <= wdata; wdata_MSB <= wdata_MSB+1; end if(!empty_singal && rinc) begin dout <= mem[rdata_pre]; rdata_MSB <= rdata_MSB+1; end end end endmodule