配置异步FIFO IP核
- 新建文件夹,新建工程(略)
- 配置FIFO IP核
调用代码
module fifo(
input wire wrclk ,
input wire [7:0] pi_data ,//输入顶层模块的数据 wrclk
input wire pi_flag ,//写请求 wrclk
input wire rdclk ,
input wire rdreq ,//读请求 rdclk
output wire wrempty ,//写端口空标志,高电平有效 wrclk
output wire wrfull ,//写端口满标志,高电平有效 wrclk
output wire [7:0] wrusedw ,//写端口中的数据个数 wrclk
output wire [15:0] po_data ,//读出的数据 rdclk
output wire rdempty ,//读端口空标志,高电平有效 rdclk
output wire rdfull ,//读端口满标志,高电平有效 rdclk
output wire [6:0] rdusedw ,//读端口中存在的数据个数 rdclk
dcfifo_256x8to128x16 dcfifo_256x8to128x16_inst
(
//input
.data (pi_data),
.rdclk (rdclk ),
.rdreq (rdreq ),
.wrclk (wrclk ),
.wrreq (wrreq ),
//output
.q (po_data),
.rdempty(rdempty),
.rdfull (rdfull ),
.rdusedw(rdusedw),
.wrempty(wrempty),
.wrfull (wrfull ),
.wrusedw(wrusedw),
);
endmodule
- 分析综合后的RTL视图
仿真代码
'timescale 1ns/1ns
module tb_fifo();
//定义端口,连接
reg wrclk ;
reg [7:0] pi_data ;
reg pi_flag ;
reg rdclk ;
reg rdreq ;
reg sys_rst_n ;
reg [1:0] cnt_baud ;
reg wrfull_reg0 ;
reg wrfull_reg1 ;
wire wrempty ;
wire wrfull ;
wire [7:0] wrusedw ;
wire [15:0] po_data ;
wire rdempty ;
wire rdfull ;
wire [6:0] rdusedw ;
//时钟,复位初始化
initial begin
wrclk = 1'b1;
rdclk = 1'b1;
sys_rst_n <= 1'b0;
#100;
sys_rst_n <= 1'b1;
end
//写时钟wrclk:50Mhz 周期20ns,每10ns电平翻转一次
always #10 wrclk = ~wrclk;
//读时钟rdclk:25Mhz 周期40ns,每20ns电平翻转一次
always #20 rdclk = ~rdclk;
//计数器cnt_baud:从0到3计数 产生输入数据间的间隔
always@(posedge wrclk or negedge sys_rst_n) //写时钟高电平,复位时钟低电平
if(sys_rst_n == 1'b0)
cnt_baud <= 2'b0;
else if(&cnt_baud == 1'b1) //位与
cnt_baud <= 2'b0;
else
cnt_baud <= cnt_baud +1'b1;
//输入数据有效标志信号,写请求信号:pi_flag
always@(posedge wrclk or negedge sys_rst_n) //写时钟高电平,复位时钟低电平
if(sys_rst_n == 1'b0)
pi_flag <= 1'b0
else if((cnt_baud == 2'd0) && (rdreq == 1'b0)) //每4个时钟周期且没有读信号时产生一个数据有效标志信号
pi_flag <= 1'b1;
else
pi_flag <= 1'b0;
//写入FIFO的数据:pi_data 0~255的依次循环
always@(posedge wrclk or negedge sys_rst_n) //写时钟高电平,复位时钟低电平
if(sys_rst_n == 1'b0)
pi_data <= 8'b0;
else if((pi_data == 8'd255) && (pi_flag ==1'b1))
pi_data <= 8'b0;
else if(pi_flag == 1'b1)
pi_data <= pi_data +1'b1;
//将写满标志信号wrfull在rdclk时钟下 延迟两拍
always@(posedge rdclk or negedge sys_rst_n) //读时钟高电平,复位时钟低电平
if(sys_rst_n == 1'b0)
begin
wrfull_rag0 <= 1'b0;
wrfull_reg1 <= 1'b0;
end
else
begin
wrfull_reg0 <= wrfull;
wrfull_reg1 <= wrfull_reg0;
end
//读请求信号同步与rdclk时钟
always@(posedge rdclk or negedge sys_rst_n) //读时钟高电平,复位时钟低电平
if(sys_rst_n = 1'b0)
rdreq <= 1'b0;
else if(wrfull_reg1 == 1'b1)
rdreq <= 1'b1;
else if(rdempty == 1'b1)
rdreq <= 1'b0;
//例化
fifo fifo_inst(
//写
.wrclk (wrclk ),
.pi_data (pi_data),
.pi_flag (pi_flag),
//读
.rdclk (rdclk ),
.rdreq (rdreq ),
//写
.wrempty (wrempty),
.wrfull (wrfull ),
.wrusedw (wrusedw),
//读
.po_data (po_data),
.rdempty (rdempty),
.rdfull (rdfull ),
.rdusedw (reusedw)
);
endmodule
仿真结果
- 整体结果
1、pi_data与po_data交替出现
2、pi_flag信号与pi_data一一对应
3、读请求信号rdreq为高时po_data输出
- wrfull与rdfull信号
pi_data为11111111(255)时且pi_flag为高时,wrfull(写满信号)拉高,一段时间后,rdfull(读端口满信号)拉高:FIFO的存储空间已满。两个信号同步的时钟分别是wrclk和rdclk。
- wrusedw和rdusedw信号
wrusedw信号计数到1111_1111(255),rdusedw计数到1111_111(127),从8位256个数据变成16位128个数据。之后都变为0,即数据存满,计数器溢出。
- rdempty和wrempty信号
16位数据全部读出后,rdempty信号立即拉高,即数据全部读完,因为同步时钟的不同,一段时间后,wrempty信号也被拉高。
小结
逻辑思维拷打!