一、创建IP核
二、FIFO实例化
在工程中找到fifo IP核自动生成的.VEO后缀的文件,这里就是fifo使用时需要实例化的接口列表。
- wr_clk : 写时钟
- wr_en : fifo写请求
- din : 写入FIFO的数据
- rd_clk : 读时钟
- rd_en : fifo读请求
- dout : 从FIFO输出的数据
- empty: 读空信号
- almost_empty 将要空信号
- full 写满信号
- almost_full 将要满信号
三、fifo写
- 检测到写空,并且有数据要写入fifo
- 进入延时状态,延时10拍 原因是FIFO IP核内部状态信号的更新存在延时 延迟10拍以等待状态信号更新完毕
- 拉高写使能,并且想fifo写入数据
- 检测到fifo被写满,则停止写入,并等待fifo被读空(回到第一步)
reg [1:0] state; // 状态流转计数
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
fifo_wr_en <= 1'b0;
fifo_wr_data <= 8'd0;
state <= 2'd0;
dly_cnt <= 4'd0;
wr_fifo_cnt <=0;
end
else begin
case(state)
2'd0: begin
if(empty && /*数据有效标志*/) begin //如果检测到FIFO将被读空
state <= 2'd1; //就进入延时状态
end
else
state <= state;
end
2'd1: begin
if(dly_cnt == 4'd10) begin //延时10拍 原因是FIFO IP核内部状态信号的更新存在延时 延迟10拍以等待状态信号更新完毕
dly_cnt <= 4'd0;
state <= 2'd2; //开始写操作
fifo_wr_en <= 1'b1; //打开写使能
end
else
dly_cnt <= dly_cnt + 4'd1;
end
2'd2: begin
if(full) begin //等待FIFO将被写满
fifo_wr_en <= 1'b0; //关闭写使能
fifo_wr_data <= 8'd0;
state <= 2'd0; //回到第一个状态
end
else begin //如果FIFO没有被写满
fifo_wr_data <= /*要写的数据*/ ;
fifo_wr_en <= 1'b1; //则持续打开写使能
end
end
default : state <= 2'd0;
endcase
end
end
endmodule
四、fifo读
- 检测到fifo已满,
- 进入延时状态,延时10拍 原因是FIFO IP核内部状态信号的更新存在延时 延迟10拍以等待状态信号更新完毕
- 拉高读使能
- 检测到fifo被读空,则停止读取,并等待fifo被写满(回到第一步)
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
fifo_rd_en <= 1'b0;
state <= 2'd0;
dly_cnt <= 4'd0;
data_fifo_en<= 1'b0;
end
else begin
data_fifo_en<=1'b0;
case(state)
2'd0: begin
if(full) //如果检测到FIFO将被写满
state <= 2'd1; //就进入延时状态
else
state <= state;
end
2'd1: begin
if(dly_cnt == 4'd10) begin //延时10拍, 原因是FIFO IP核内部状态信号的更新存在延时, 延迟10拍以等待状态信号更新完毕
dly_cnt <= 4'd0;
state <= 2'd2; //开始读操作
end
else
dly_cnt <= dly_cnt + 4'd1;
end
2'd2: begin
data_fifo_en<=1'b0;
if(empty) begin //等待FIFO将被读空
fifo_rd_en <= 1'b0; //关闭读使能
state <= 2'd0; //回到第一个状态
end
else begin //如果FIFO没有被读空
fifo_rd_en <= 1'b1; //则持续打开读使能
data_fifo_en<=1'b1;
end
end
default : state <= 2'd0;
endcase
end
end