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