1.目标
准备使用FPGA的FIFO功能读取AD9629的12位采样数据,再发送到ARM里面进行处理。
ADC的采样率为20MHz,一共采集1ms时间的数据,共200k数据。
2.方案设计
ADC的输出接FIFO,然后通过 DMA传输到ARM里面,再通过串口显示。数据是存在ARM的256 KB on-chip RAM (OCM)里面?
3.先练习使用FIFO GENERATOR核
选择一个FIFO核,将端口引出,生成warpper文件,添加一段代码,封装一个.v文件.
fifo_ctrl fifo_ctrl
(.FIFO_READ_0_empty(FIFO_READ_0_empty),
.FIFO_READ_0_rd_data(FIFO_READ_0_rd_data),
.FIFO_READ_0_rd_en(FIFO_READ_0_rd_en),
.FIFO_WRITE_0_full(FIFO_WRITE_0_full),
.FIFO_WRITE_0_wr_data(FIFO_WRITE_0_wr_data),
.FIFO_WRITE_0_wr_en(FIFO_WRITE_0_wr_en),
.clk_0(clk_0),
.data_count_0(data_count_0),
.srst_0(srst_0));
然后在ctrl.v文件里面编写控制代码,并编译。
仿真结果如下所示。
4.练习使用异步时钟
将FIFO的核设置成异步时钟,并修改源代码为读写时钟分开控制,代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/02/03 17:49:14
// Design Name:
// Module Name: fifo_ctrl
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fifo_ctrl(
input wr_clk_0,
input rd_clk_0,
input rst_0,
input rd_rst_busy_0,
input wr_rst_busy_0,
input FIFO_WRITE_0_full,
input [11:0]FIFO_READ_0_rd_data,
input FIFO_READ_0_empty,
input [9:0]rd_data_count_0,
input [9:0]wr_data_count_0,
output reg FIFO_WRITE_0_wr_en,
output reg FIFO_READ_0_rd_en,
output [11:0]FIFO_WRITE_0_wr_data
);
// ----------reg and wire ------------------//
reg [11:0] data_source;
reg [11:0] data_in;
assign FIFO_WRITE_0_wr_data=data_source;
//---------------------------------------------//
always@(posedge wr_clk_0 or negedge rst_0)
begin
if(rst_0)
data_source<='b0;
else begin
if((FIFO_WRITE_0_full=='b0)&&(data_source<'d255))
FIFO_WRITE_0_wr_en <= 'b1;
else
FIFO_WRITE_0_wr_en <= 'b0;
if(FIFO_WRITE_0_wr_en=='b1)begin
if(data_source < 10'd255)
data_source<=data_source+1'b1;
else
data_source<= data_source;end
else
data_source<= 'b0;
end
end
//-----------读FIFO----------------------------------//
always@(posedge rd_clk_0 or negedge rst_0)
begin
if(rst_0)
FIFO_READ_0_rd_en<= 'b0;
else begin
if(FIFO_READ_0_empty=='b0)
FIFO_READ_0_rd_en <= 'b1;
else
FIFO_READ_0_rd_en <= 'b0;
end
if(FIFO_READ_0_rd_en=='b1)
data_in <= FIFO_READ_0_rd_data;
else
data_in<=data_in;
end
endmodule
仿真结果如下,可以看到因为写数据时钟是读数据时钟的5倍,在写满后未处理,导致数据出错。
6.单独使用AXIS-FIFO核
使用同步时钟,代码如下,注意READY和VAILD信号同时为高时才有效
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/02/05 14:12:06
// Design Name:
// Module Name: fifo
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fifo(
input s_axis_aclk_0,
input s_axis_aresetn_0,
input M_AXIS_0_tvalid,
input [7:0]M_AXIS_0_tdata,
input S_AXIS_0_tready,
input [31:0]axis_rd_data_count_0,
input [31:0]axis_wr_data_count_0,
input [31:0]axis_data_count_0,
output reg M_AXIS_0_tready,
output reg S_AXIS_0_tvalid,
output [7:0]S_AXIS_0_tdata
);
// ----------reg and wire ------------------//
reg [7:0] data_source;
reg [7:0] data_in;
assign S_AXIS_0_tdata=data_source;
//---------------------------------------------//
always@(posedge s_axis_aclk_0 or negedge s_axis_aresetn_0)
begin
if(!s_axis_aresetn_0)
data_source<='b0;
else begin
if((S_AXIS_0_tready=='b1)&&(data_source<'d55))
S_AXIS_0_tvalid <= 'b1;
else
S_AXIS_0_tvalid <= 'b0;
end
if(S_AXIS_0_tvalid=='b1)begin
if(data_source < 7'd55)
data_source<=data_source+1'b1;
else
data_source<= data_source;end
else
data_source<= 'b0;
end
//-----------读FIFO----------------------------------//
always@(posedge s_axis_aclk_0 or negedge s_axis_aresetn_0)
begin
if(!s_axis_aresetn_0)
M_AXIS_0_tready<= 'b0;
else begin
if(M_AXIS_0_tvalid=='b1)
M_AXIS_0_tready <= 'b1;
else
M_AXIS_0_tready <= 'b0;
end
if(M_AXIS_0_tready=='b1)
data_in <= M_AXIS_0_tdata;
else
data_in<=data_in;
end
endmodule
7.使用ZYNQ读数
添加一个ZYNQ核,将AXIS-FIFO的输出通过HP0连接到ZYNQ,会自动生成DMA等模块
AXIS-FIFO核需要添加TLAST和TKEEP信号。
S-AXIS信号连接到ZYNQ开发板的CN2连接器,使用BANK35的1-16共32个IO口。
生成BITSTREAM后在SDK打开,建立FSBL和HELLOWORD工程,可通过串口打印出HELLOWORD。