1 、同步FIFO设计代码如下:
- 功能描述
(1) 具有深度和宽度均为16的读写memory逻辑;
(2) 具有写满读空标志,防止FIFO溢出和FIFO读空;
// ** syfifo **//
`timescale 1ns/1ps
module syfifo(
// IO 定义
input clk,
input rst_n,
input wr_en,
input rd_en,
input [15:0] data_in,
output reg [15:0] data_out, // 在always模块内被赋值的信号,reg类型
output wire full,
output wire empty
);
// 内部信号定义
reg [3:0] wr_addr; // reg类型数据的默认初始值为不定值x
reg [3:0] rd_addr;
reg [15:0] mem [16-1 :0]; // 宽度和深度均为16的regs
reg [0:0] wr_flag;
reg [0:0] rd_flag;
// ·reg [4:0] i; // 初始化mem时使用,命名注意要有实际含义。不用i
// 空满标志
assign full = ({~wr_flag,wr_addr} == {rd_flag,rd_addr})? 1’b1:1’b0;
assign empty = ({wr_flag,wr_addr} == {rd_flag,rd_addr})? 1’b1:1’b0;
// 写地址控制, 控制写地址产生和写入数据
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1’b0)
begin
wr_addr <= 4’b0;
wr_flag <= 1’b0;
rd_flag <= 1’b0;
// for(i=0;i<16;i=i+1)
// begin
// mem[i] <= 16’b0;//mem可以不复位。数据通路可以不需要,但是控制通路需要
// end
end
else if((wr_en == 1’b1) && (full == 1’b0))
begin
mem[wr_addr] <= data_in;
{wr_flag,wr_addr} <= {wr_flag,wr_addr} + 1’b1;
end
else
begin
{wr_flag,wr_addr} <= {wr_flag,wr_addr}; // wr_addr <= 1’b0, 给0会导致信号跳变 翻转增加功耗;
mem[wr_addr] <= mem[wr_addr];
end
end
//读地址控制, 控制读地址产生和读取数据
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1’b0)
begin
rd_addr <= 4’b0;
rd_flag <= 1’b0;
data_out <= 16’b0;
end
else if((rd_en == 1’b1) && (empty == 1’b0))
begin
data_out <= mem[rd_addr];
{rd_flag,rd_addr} <= {rd_flag,rd_addr} + 1’b1;
end
else
begin
{rd_flag,rd_addr} <= {rd_flag,rd_addr};
data_out <= data_out;
end
end
endmodule
2、 testbench文件如下:
`timescale 1ns/1ps
module tb_syfifo;
//定义内部连线及寄存器
reg [0:0] clk;
reg [0:0] rst_n;
reg [15:0] data_in;
reg [0:0] rd_en;
reg [0:0] wr_en;
wire [0:0] empty;
wire [0:0] full;
wire [15:0] data_out;
reg [31:0] cnt;
initial
begin
clk = 1’b0;
rst_n = 1’b0;
rd_en = 1’b0;
wr_en = 1’b0;
data_in = 16’b0;
cnt = 32’d0;
#20
rst_n = 1’b1;
data_in = 16’d8;//输入随机激励
wr_en = 1’b1;
#300
wr_en = 1’b0;
rd_en = 1’b1;
#500
rd_en = 1’b0;
wr_en = 1’b1;
#300
while(1)
begin
@(posedge clk);
wr_en = $random;
rd_en = $random;
cnt = cnt + 1’b1;
if(cnt == 8’d100)
begin
cnt = 8’h0;
break;
end
end
#300;
$display(“----------Simulate finish!!!---------” );
$finish;
end
always #5 clk = ~clk;
// 生成SyFIFO.fsdb波形文件
initial begin
$fsdbDumpfile(“SyFIFO.fsdb”);
$fsdbDumpvars(0, “tb_syfifo”, “+mda”, “+functions”);
end
// // 生成SyFIFO.vcd波形文件
// initial begin
// $dumpfile(“SyFIFO.vcd”);
// $dumpvars(0, tb_syfifo);
// end
syfifo u_syfifo(
.clk (clk),
.rst_n (rst_n),
.data_in (data_in),
.rd_en (rd_en),
.wr_en (wr_en),
.empty (empty),
.full (full),
.data_out(data_out)
);
endmodule