以下内容基于bi站正点原子对fifoIP核的视频讲解。
以下是在vivado中创建fifo IP核的几个步骤:
另附上视频讲解过程中的程序,注意设置顶层文件:
主要包含三个文件,分别是顶层,数据读模块和数据写模块:
`timescale 1ns / 1ps
// Create Date: 2025/01/03 09:58:34
// Design Name:
// Module Name: test_027_FIFO_IP
module test_027_FIFO_IP(input sys_clk , input sys_rst_n );wire almost_full ; wire almost_empt ;wire fifo_wr_en ;wire [7:0] fifo_wr_data ;wire fifo_rd_en ; wire [7:0] fifo_rd_data ;wire full;wire empty;wire [7:0] rd_data_count;wire [7:0] wr_data_count;//fifo数据写模块的例化调用fifo_wr fifo_wr_u(.sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .almost_full (almost_full), .almost_empty (almost_empt), .fifo_wr_en (fifo_wr_en ),.fifo_wr_data (fifo_wr_data));//fifo数据读模块的例化调用fifo_rd fifo_rd_u(.sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .almost_full (almost_full), .almost_empty (almost_empty), .fifo_rd_en (fifo_rd_en)// .fifo_rd_data (fifo_rd_data));//fifo模块例化调用 fifo_test fifo_test_u ( .wr_clk(sys_clk), // input wire wr_clk .rd_clk(sys_clk), // input wire rd_clk .din(fifo_wr_data), // input wire [7 : 0] din .wr_en(fifo_wr_en), // input wire wr_en .rd_en(fifo_rd_en), // input wire rd_en .dout(fifo_rd_data), // output wire [7 : 0] dout .full(full), // output wire full .almost_full(almost_full), // output wire almost_full .empty(empty), // output wire empty .almost_empty(almost_empty), // output wire almost_empty .rd_data_count(rd_data_count), // output wire [7 : 0] rd_data_count.wr_data_count(wr_data_count) // output wire [7 : 0] wr_data_count ); //ILA例化调用ila_fifo ila_fifo_u (.clk(sys_clk), // input wire clk.probe0(fifo_wr_en), // input wire [0:0] probe0 .probe1(fifo_rd_en), // input wire [0:0] probe1 .probe2(full), // input wire [0:0] probe2 .probe3(empty), // input wire [0:0] probe3 .probe4(fifo_wr_data), // input wire [7:0] probe4 .probe5(wr_data_count), // input wire [7:0] probe5 .probe6(fifo_rd_data), // input wire [7:0] probe6 .probe7(rd_data_count), // input wire [7:0] probe7 .probe8(almost_full), // input wire [0:0] probe8 .probe9(almost_empty) // input wire [0:0] probe9
);endmodule
`timescale 1ns / 1ps
// Create Date: 2025/01/03 10:53:04
// Design Name:
// Module Name: fifo_wr
module fifo_wr(input sys_clk ,input sys_rst_n ,input almost_full ,input almost_empty ,output reg fifo_wr_en ,output reg [7:0] fifo_wr_data);//如何抓取信号的上升沿(下降沿)reg almost_empty_d0;reg almost_empty_up;wire empty_flag; //标志位->高电平抓取reg [1:0] state; //state3个状态切换reg [3:0] delay_cnt;assign empty_flag = ~almost_empty_up & almost_empty_d0;always @ (posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n) beginalmost_empty_d0 <= 1'b0;almost_empty_up <= 1'b0;end elsebeginalmost_empty_d0 <= almost_empty;almost_empty_up <= almost_empty_d0;end end always @ (posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n) beginfifo_wr_en <= 1'b0;fifo_wr_data <= 8'd0;state <= 2'd0; delay_cnt <= 4'd0;end elsebegincase(state)2'd0 : beginif(empty_flag) state <= 2'd1;elsestate <= state;end2'd1 : beginif(delay_cnt ==4'd10)begindelay_cnt <= 4'd0;state <= 2'd2;fifo_wr_en <= 1'b1;endelsedelay_cnt <= delay_cnt + 4'd1;end2'd2 : beginif(almost_full)beginfifo_wr_en <= 1'b0; fifo_wr_data <= 8'd0;state <= 2'd0;endelsebeginfifo_wr_en <= 1'b1;fifo_wr_data <= fifo_wr_data + 8'd1; endenddefault : state <= 2'd0;endcaseend endendmodule
`timescale 1ns / 1ps
// Create Date: 2025/01/04 9:05:04
// Design Name:
// Module Name: fifo_rd
module fifo_rd(input sys_clk ,input sys_rst_n ,input almost_full ,input almost_empty ,output reg fifo_rd_en ,input [7:0] fifo_rd_data);//如何抓取信号的上升沿(下降沿)reg almost_full_d0;reg almost_full_up;wire full_flag; //标志位->高电平抓取reg [1:0] state; //state3个状态切换reg [3:0] delay_cnt;assign full_flag = ~almost_full_up & almost_full_d0;always @ (posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n) beginalmost_full_d0 <= 1'b0;almost_full_up <= 1'b0;end elsebeginalmost_full_d0 <= almost_full;almost_full_up <= almost_full_d0;end end always @ (posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n) beginfifo_rd_en <= 1'b0;//fifo_rd_data <= 8'd0;state <= 2'd0; delay_cnt <= 4'd0;end elsebegincase(state)2'd0 : beginif(full_flag) state <= 2'd1;elsestate <= state;end2'd1 : beginif(delay_cnt ==4'd10)begindelay_cnt <= 4'd0;state <= 2'd2;fifo_rd_en <= 1'b1;endelsedelay_cnt <= delay_cnt + 4'd1;end2'd2 : beginif(almost_empty)beginfifo_rd_en <= 1'b0; //fifo_rd_data <= 8'd0;state <= 2'd0;endelsebeginfifo_rd_en <= 1'b1;//fifo_rd_data <= fifo_rd_data + 8'd1; endenddefault : state <= 2'd0;endcaseend endendmodule
tb激励文件(自己写的,没有实际测试过)
`timescale 1ns / 1ps
// Create Date: 2025/01/04 10:31:57
// Design Name:
// Module Name: tb_fifo
module tb_fifo();reg sys_clk;reg sys_rst_n;
initial beginsys_clk <= 1'b0;sys_rst_n <= 1'b0;#500sys_rst_n <= 1'b1;end
always #10sys_clk <= ~sys_clk;test_027_FIFO_IP test_027_FIFO_IP_u(.almost_full (almost_full ),.almost_empt (almost_empt ),.fifo_wr_en (fifo_wr_en ),.fifo_wr_data (fifo_wr_data ),.fifo_rd_en (fifo_rd_en ),.fifo_rd_data (fifo_rd_data ),.full (full ), .empty (empty ), .rd_data_count (rd_data_count ),.wr_data_count (wr_data_count )
);endmodule
最后在放上vivado中对应fifoIP核程序对应的仿真电路 图解(Schematic):
另附注:
1、板子的PL端时钟需要从PS端调用,此时调用时钟的文件应为顶层文件,所以仿真受限。
2、涉及的状态机的写法的简单回顾。
3、在程序的编写过程中出现了一些问题如begin--end的无法自动对齐,就类似‘{}’,有时容易造成混乱,目前是tab手动控制,还没有更好的解决办法,和notepad++关联就无法使用vivado中编辑器的对程序的自动实时报错提醒的功能。