题解 | 同步FIFO
同步FIFO
https://www.nowcoder.com/practice/3ece2bed6f044ceebd172a7bf5cfb416
`timescale 1ns/1ns // 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]; //定义一个二维数组RAM_MEM模拟RAM储存单元,每个储存单元位宽为WIDTH,共有DEPTH个存储单元 //二维数组读入读出 always@(posedge wclk)begin if(wenc) RAM_MEM[waddr] <= wdata; end always@(posedge rclk)begin if(renc) rdata <= RAM_MEM[raddr]; end endmodule /****************************************************************/ 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] waddr, raddr;//clog2即取2的对数位,向上进位 reg[$clog2(DEPTH):0] cnt; //0也要包括进去,比如DEPTH是8位,取2为底的对数后值为3,0还需要再要一个。因此不需要减去一,避免计数溢出 always@(posedge clk or negedge rst_n)begin if(!rst_n) waddr <= 0; else waddr <= winc&~wfull ? waddr + 1 : waddr;//写使能且写未满,则写地址加一,否则不变 end always@(posedge clk or negedge rst_n)begin if(!rst_n) raddr <= 0; else raddr <= rinc&~rempty ? raddr + 1: raddr;//读使能且读不为空则读地址加一,否则不变 end always@(posedge clk or negedge rst_n)begin if(!rst_n) cnt <= 0; else if(rinc&~rempty&winc&~wfull) cnt <= cnt; else if(rinc&~rempty) cnt <= cnt - 1; else if(winc&~wfull) cnt <= cnt + 1; else cnt <= cnt; end always@(posedge clk or negedge rst_n)begin if(!rst_n)begin wfull <= 0; rempty <= 0; end else begin wfull <= cnt == DEPTH;//计数等于DEPTH时赋给wfull高电平 rempty <= cnt == 0;//计数等于0时赋给rempty高电平 end end dual_port_ram#( .DEPTH(DEPTH), .WIDTH(WIDTH) )my_RAM( .wclk(clk), .rclk(clk), .wenc(winc&~wfull),//写使能且写未满 .renc(rinc&~rempty),//读使能且读未满 .raddr(raddr), .waddr(waddr), .rdata(rdata), .wdata(wdata) ); endmodule
verilog刷题记录 文章被收录于专栏
记录自己最近刷题掌握的点滴