ZYNQ初识8(zynq_7010)FIFO_IP核
以下内容基于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)
begin
if(!sys_rst_n)
begin
almost_empty_d0 <= 1'b0;
almost_empty_up <= 1'b0;
end
else
begin
almost_empty_d0 <= almost_empty;
almost_empty_up <= almost_empty_d0;
end
end
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;
delay_cnt <= 4'd0;
end
else
begin
case(state)
2'd0 : begin
if(empty_flag)
state <= 2'd1;
else
state <= state;
end
2'd1 : begin
if(delay_cnt ==4'd10)
begin
delay_cnt <= 4'd0;
state <= 2'd2;
fifo_wr_en <= 1'b1;
end
else
delay_cnt <= delay_cnt + 4'd1;
end
2'd2 : begin
if(almost_full)
begin
fifo_wr_en <= 1'b0;
fifo_wr_data <= 8'd0;
state <= 2'd0;
end
else
begin
fifo_wr_en <= 1'b1;
fifo_wr_data <= fifo_wr_data + 8'd1;
end
end
default : state <= 2'd0;
endcase
end
end
endmodule
`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)
begin
if(!sys_rst_n)
begin
almost_full_d0 <= 1'b0;
almost_full_up <= 1'b0;
end
else
begin
almost_full_d0 <= almost_full;
almost_full_up <= almost_full_d0;
end
end
always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
fifo_rd_en <= 1'b0;
//fifo_rd_data <= 8'd0;
state <= 2'd0;
delay_cnt <= 4'd0;
end
else
begin
case(state)
2'd0 : begin
if(full_flag)
state <= 2'd1;
else
state <= state;
end
2'd1 : begin
if(delay_cnt ==4'd10)
begin
delay_cnt <= 4'd0;
state <= 2'd2;
fifo_rd_en <= 1'b1;
end
else
delay_cnt <= delay_cnt + 4'd1;
end
2'd2 : begin
if(almost_empty)
begin
fifo_rd_en <= 1'b0;
//fifo_rd_data <= 8'd0;
state <= 2'd0;
end
else
begin
fifo_rd_en <= 1'b1;
//fifo_rd_data <= fifo_rd_data + 8'd1;
end
end
default : state <= 2'd0;
endcase
end
end
endmodule
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
begin
sys_clk <= 1'b0;
sys_rst_n <= 1'b0;
#500
sys_rst_n <= 1'b1;
end
always #10
sys_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中编辑器的对程序的自动实时报错提醒的功能。