verilog实现FIFO
一、计数器
代码
module sync_fifo_cnt #(
parameter DEPTH = 8,
parameter WIDTH = 8
)(
input wire clk,
input wire rst_n,
input wire i_wen,
input wire [WIDTH-1:0] i_wdata,
input wire i_ren,
output reg [WIDTH-1:0] o_rdata,
output wire o_empty,
output wire o_full,
output reg [$clog2(DEPTH):0] cnt
);
reg [$clog2(DEPTH)-1:0] w_addr;
reg [$clog2(DEPTH)-1:0] r_addr;
reg [WIDTH-1:0] fifo_buffer[DEPTH-1:0]; //鐢ㄤ簩缁存暟缁勫疄鐜癛AM
//counter
//read
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
r_addr <= 0;
end
else if(i_ren && !o_empty)
begin
r_addr <= r_addr+1'b1;
o_rdata <= fifo_buffer[r_addr];
end
end
//write
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
w_addr <= 0;
end
else if(i_wen && !o_full)
begin
w_addr <= w_addr + 1'b1;
fifo_buffer[w_addr] <= i_wdata;
end
end
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
cnt <= 0;
end
else if(i_wen && i_ren)
begin
cnt <= cnt;
end
else if(i_wen && !(cnt == DEPTH))
begin
cnt <= cnt + 1'b1;
end
else if(i_ren && !(cnt == 0))
begin
cnt <= cnt - 1'b1;
end
end
assign o_empty = (cnt == 0)?1'b1:1'b0;
assign o_full = (cnt == DEPTH)?1'b1:1'b0;
endmodule
测试
`timescale 1ns/1ns //时间单位/精度
//------------<模块及端口声明>----------------------------------------
module tb_sync_fifo_cnt();
parameter WIDTH = 8 ; //FIFO位宽
parameter DEPTH = 8 ; //FIFO深度
reg clk ;
reg rst_n ;
reg [WIDTH-1:0] data_in ;
reg rd_en ;
reg wr_en ;
wire [WIDTH-1:0] data_out;
wire empty ;
wire full ;
wire [$clog2(DEPTH) : 0] fifo_cnt;
//------------<例化被测试模块>----------------------------------------
sync_fifo_cnt
#(
.WIDTH (WIDTH), //FIFO位宽
.DEPTH (DEPTH) //FIFO深度
)
sync_fifo_cnt_inst(
.clk (clk ),
.rst_n (rst_n ),
.i_wdata (data_in ),
.i_ren (rd_en ),
.i_wen (wr_en ),
.o_rdata (data_out ),
.o_empty (empty ),
.o_full (full ),
.cnt (fifo_cnt )
);
//------------<设置初始测试条件>----------------------------------------
initial begin
clk = 1'b0; //初始时钟为0
rst_n <= 1'b0; //初始复位
data_in <= 'd0;
wr_en <= 1'b0;
rd_en <= 1'b0;
//重复8次写操作,让FIFO写满
repeat(8) begin
@(negedge clk)begin
rst_n <= 1'b1;
wr_en <= 1'b1;
data_in <= $random; //生成8位随机数
end
end
//重复8次读操作,让FIFO读空
repeat(8) begin
@(negedge clk)begin
wr_en <= 1'b0;
rd_en <= 1'd1;
end
end
//重复4次写操作,写入4个随机数据
repeat(4) begin
@(negedge clk)begin
wr_en <= 1'b1;
data_in <= $random; //生成8位随机数
rd_en <= 1'b0;
end
end
//持续同时对FIFO读写,写入数据为随机数据
forever begin
@(negedge clk)begin
wr_en <= 1'b1;
data_in <= $random; //生成8位随机数
rd_en <= 1'b1;
end
end
end
//------------<设置时钟>----------------------------------------------
always #10 clk = ~clk; //系统时钟周期20ns
endmodule