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