创建IP核
本次实验创建了一个8位输入 4位输出的IP核心,并将IP核心所有信号都进行添加
先进行前仿真,写入时钟为读取时钟的两倍
写入开始
- 第1个 wclk 上升沿,wrreq <= 1;
- 第2个 wclk 上升沿,当 wrreq 置 1,此时写入送入到 data 端口的数据,此时写入值为 8’h12 ,写入过程发生在上升沿
- 第3个 wclk 上升沿, wrempty 置 0,同时 wrusedw 输出 0;此时写入值为 8’h13
- 第4个 wclk 上升沿,同时 wrusedw 输出 1;此时写入值为 8’h14
- 第6至17个 wclk 上升沿,此时写入值为 8’h15至8‘h21, 同时 wrusedw 输出 2-14;
- 第18个 wclk 上升沿,wrusedw 输出 1,wrfull 置为 1;此时无法检测出wrfull 为1
- 第19个 wclk 上升沿,可以检测wrfull ,
所以一个完整写入fifo,并检测FIFO是否写入满需要经过4个周期,
// 写入
0:begin
wrreq <= 1;
data <= DIN;
end
1:wrreq <= 0//写入中
2:;//等待wrfull置为1
3:;//判断是狗写入满
写入结束
对于写入时的 rdempty和 rdusedw变化情况
本实验创建fifo的深度为16,所以对图 wrusedw 范围为0~15 ,而对于rdusedw是0~31。
当wrusedw 输出 1时rdusedw输出为0,此时rdempty还为高,下个写入时钟rdusedw输出为2,根据写入时钟变化
当超额写入时写入信号时rdusedw wrusedw 为 0,但是实际并没写入 当rdusedw == 31 时 rdfull = 1
读取开始
.
- 第1个 rclk 上升沿,rdreq <= 1;
- 第2个 rclk 上升沿,当 rdreq 置 1;
- 第3个 rclk 上升沿,输出数据低位 4’h2;
- 第4个 rclk 上升沿,输出数据高位 4’h1;此时rdusedw 输出31
- 第5个 rclk 上升沿,输出数据高位 4’h3;此时rdusedw 输出30
- 顺序读出.
读取结束
当输出完成后rdempty同步变化,但是rdusedw 为检测到读空后的下个周期变化
欢迎自行测试
`timescale 1ns/1ns
`define clk_period 20
module fifo_test();
reg clk;
reg rst_n;
reg [7:0] data ;
reg rdclk ;
// reg rdreq ;
wire wrclk ;
reg wrreq ;
wire [3:0] q ;
wire rdempty ;
wire rdfull ;
wire [4:0] rdusedw ;
wire wrempty ;
wire wrfull ;
wire [3:0] wrusedw ;
// reg [3:0] data_out;
fifotest fifotest(
.data (data ),
.rdclk (rdclk ),
.rdreq ( ),
.wrclk (wrclk ),
.wrreq (wrreq ),
.q (q ),
.rdempty (rdempty ),
.rdfull (rdfull ),
.rdusedw (rdusedw ),
.wrempty (wrempty ),
.wrfull (wrfull ),
.wrusedw (wrusedw )
);
assign wrclk = clk;
initial clk = 1;
always#(`clk_period/2) clk = ~clk;
initial rdclk = 1;
always#(`clk_period/5) rdclk = ~rdclk;
always@(posedge wrclk or negedge rst_n)
if(!rst_n)begin
data <= 8'h11;
wrreq <= 0;
end
else if(!wrfull)begin
if(data <= 8'h19)begin
wrreq <= 1;
data <= data + 1'b1;
end
else begin
wrreq <= 0;
data <= data;
end
end
else begin
wrreq <= 0;
data <= 8'h11;
end
// always@(posedge rdclk or negedge rst_n)
// if(!rst_n)begin
// rdreq <= 0;
// data_out <= 4'hf;
// end
// else if(!rdempty & !wrreq)begin
// rdreq <= 1;
// data_out <= q;
// end
// else begin
// rdreq <= 0;
// data_out <= 4'hf;
// end
initial begin
rst_n = 0;
#(`clk_period*20);
rst_n = 1;
#(`clk_period*500);
$stop;
end
endmodule