目录
一、设计代码
//sync_fifo
`timescale 1ns/1ns
module sync_fifo #(
parameter DATA_WIDTH = 8,
parameter DATA_DEPTH = 16
)
(
input clk,
input rst_n,
input wr_en,
input signed [DATA_WIDTH - 1:0] data_in,
input rd_en,
output reg signed [DATA_WIDTH - 1:0] data_out,
output empty,
output full,
output reg [$clog2(DATA_DEPTH) : 0] fifo_cnt
);
reg [DATA_WIDTH - 1:0] fifo_buffer [DATA_DEPTH - 1:0];
reg [$clog2(DATA_DEPTH) - 1:0] wr_addr;
reg [$clog2(DATA_DEPTH) - 1:0] rd_addr;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n)
wr_addr <= 0;
else if (!full && wr_en) begin
wr_addr <= wr_addr + 1;
fifo_buffer[wr_addr] <= data_in;
end
end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rd_addr <= 0;
data_out <= 0;
end
else if (!empty && rd_en) begin
rd_addr <= rd_addr + 1;
data_out <= fifo_buffer[rd_addr];
end
end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n)
fifo_cnt <= 0;
else if (wr_en && !rd_en && !full)
fifo_cnt <= fifo_cnt + 1;
else if (rd_en && !wr_en && !empty)
fifo_cnt <= fifo_cnt - 1;
else if (wr_en && rd_en && full)
fifo_cnt <= fifo_cnt - 1;
else if (wr_en && rd_en && empty)
fifo_cnt <= fifo_cnt + 1;
else
fifo_cnt <= fifo_cnt;
end
assign full = (fifo_cnt == DATA_DEPTH) ? 1 : 0;
assign empty = (fifo_cnt == 0) ? 1 : 0;
endmodule
二、testbench代码
使用System Verilog实现testbench,以进行随机验证。SV相关基础可参考:
System Verilog基础_qq_42922513的博客-CSDN博客https://blog.csdn.net/qq_42922513/article/details/130984574
//sync_fifo_tb.sv
`timescale 1ns/1ns
module sync_fifo_tb;
parameter DATA_WIDTH = 8;
parameter DATA_DEPTH = 16;
bit clk;
bit rst_n;
bit wr_en;
bit signed [DATA_WIDTH - 1 : 0] data_in;
bit rd_en;
bit signed [DATA_WIDTH - 1 : 0] data_out;
bit empty;
bit full;
bit [$clog2(DATA_DEPTH) : 0] fifo_cnt;
sync_fifo #(
.DATA_WIDTH(DATA_WIDTH),
.DATA_DEPTH(DATA_DEPTH)
)
u1(
.clk(clk),
.rst_n(rst_n),
.wr_en(wr_en),
.data_in(data_in),
.rd_en(rd_en),
.data_out(data_out),
.empty(empty),
.full(full),
.fifo_cnt(fifo_cnt)
);
class packet;
rand bit signed [DATA_WIDTH - 1 : 0] number;
rand bit wr_en_rand;
rand bit rd_en_rand;
constraint c {number >= - (2 ** (DATA_WIDTH - 1));
number <= 2 ** (DATA_WIDTH - 1) - 1;
}
endclass
packet numb;
initial begin
numb = new();
clk = 0;
rst_n = 1;
wr_en = 0;
rd_en = 0;
#3
rst_n = 0;
#20
rst_n = 1;
repeat (1000) begin
@(negedge clk) begin
assert(numb.randomize());
wr_en = numb.wr_en_rand;
rd_en = numb.rd_en_rand;
data_in <= numb.number;
end
end
#100;
rd_en = 0;
wr_en = 0;
#100;
$stop;
end
always #10 clk = ~clk;
endmodule
三、仿真结果
工具:Vivado2018.3