异步FIFO
1、实验原理
了解掌握AFIFO的工作原理以及其结构,设计AFIFO模块以及其test_bench,最后在Robei可视化仿真软件经行功能实现和仿真验证。
2、实验原理
在两个时钟域之间进行数据传递最常用的的使用方法就是异步FIFO。异步FIFO一般包括两个端口,其中端口A是写入端,端口B是读入端。AFIFO中最常用的控制信号是“空”(empty)和“满”(full),另外,“将空”(almost empty)、“将满”(almost full)也是两个经常使用的控制信号。
din[n-1:0] dout[n-1:0]
wr_en rd_en
wclk rclk
full
rempty
图1 AFIFO外部链接关系
确定AFIFO的空状态或满状态需要一定的数学处理以及读指针和写指针的比较。关键问题是两个指针在不同的时钟域产生,所以指针必须经过同步化才能在另一时钟域中进行比较和用于计算。对于异步FIFO来说,产生准确的“空”和“满”指示信号是比较困难的,但为了保证操作的安全,避免“满”后仍继续写入和“空”后仍继续读出是可以做到的。
3、实验内容
3.1、yibuFIFO模型的设计
1)、新建一个模型命名为 yibuFIFO,类型为 module,同时具备6 输入3输出,每个引脚的属性和名称参照下图2进行修改。
图2 yibuFIFO引脚属性
图3 yibuFIFO界面图
2) 添加代码。点击模型下方的 Code添加代码。
代码:
reg [4:0] wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr;
reg [4:0] rbin, wbin;
reg [7:0] mem[0:(1<<4)-1];
wire[3:0] waddr, raddr;
wire [4:0] rgraynext, rbinnext,wgraynext,wbinnext;
wire rempty_val,wfull_val;
assign rdata=mem[raddr];
always@(posedge wclk)
if (winc && !wfull) mem[waddr] <= wdata;
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) {rbin, rptr} <= 0;
else {rbin, rptr} <= {rbinnext, rgraynext};
assign raddr = rbin[3:0];
assign rbinnext = rbin + (rinc & ~rempty);
assign rgraynext = (rbinnext>>1) ^ rbinnext;
assign rempty_val = (rgraynext == ~rq2_wptr);
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) rempty <= 1'b1;
else rempty <= rempty_val;
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) {wbin, wptr} <= 0;
else {wbin, wptr} <= {wbinnext, wgraynext};
assign waddr = wbin[3:0];
assign wbinnext = wbin + (winc & ~wfull);
assign wgraynext = (wbinnext>>1) ^ wbinnext;
assign wfull_val = (wgraynext=={~wq2_rptr[4:4-1],
wq2_rptr[4-2:0]});
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) wfull <= 1'b0;
else wfull <= wfull_val;
3) 保存模型到一个文件夹(文件夹路径不能有空格和中文)中,运行并检查有无错误输出。
三、yibuFIFO_test测试文件的设计
1) 新建一个 6输入3 输出的yibuFIFO_test测试文件,记得将 Module Type 设置为 “testbench”,各个引脚配置如图4所示。
图4 yibuFIFO_test引脚属性
2)、另存为测试文件。将测试文件保存到上面创建的模型所在的文件夹下。加入模型。 在 Toolbox 工具箱的 Current 栏里,会出现模型,单击该模型并在 yibuFIFO_test上添加,并连接引脚,如下图5所示:
图5 yibuFIFO_test界面图
4) 输入激励,点击测试模块下方的“Code”,输入激励算法。激励代码在结束的时候要用$stop 结束。
激励代码:
integer i;
always begin
#10 wclk=1;
#10 wclk=0;
end
always begin
#15 rclk=1;
#15 rclk=0;
end
initial begin
wclk=0;rclk=0;wdata=0;winc=0;rinc=0;wrst_n=0;rrst_n=0;i=0;
#2 winc=1;
#2 rinc=0;
for(i=0;i<=20;i=i+1)
begin
repeat(1)@(posedge wclk);
wrst_n=1;
wdata=wdata+1;
end
repeat(1)@(posedge wclk);
wrst_n=0;
#100 rinc=1;
#2 winc=0;
for(i=0;i<=20;i=i+1)
begin
repeat(1)@(posedge rclk);
#2;
rrst_n=1;
end
repeat(1)@(posedge rclk);
#2;
rrst_n=0;
#100 rinc=0;
#2 $finish;
end
5) 执行仿真并查看波形。查看输出信息。检查没有错误之后查看波形。点击右侧 Workspace 中的信号,进行添加并查看分析仿真结果。如图6所示
图6 yibuFIFO_test仿真波形
4.问题与思考
1、思考异步FIFO与同步FIFO的优缺点。
|