作者:MiS603开发团队
日期:20150911
公司:南京米联电子科技有限公司
论坛:www.osrc.cn
EAT博客:http://blog.chinaaet.com/whilebreak
博客园:http://www.cnblogs.com/milinker/
MiS603开发板 第八章 IP-CORE FIFO
FIFO是FPGA在数据流处理方面非常重要的一种资源。FIFO可以用数据的缓存,数据先入先出。本章讲简单介绍FIFO的使用,通过UART经过PC将数据发送给FIFO,FIFO缓存后再通过UART返回给电脑,让读者有一个全局的认识。当具体项目的时候,可以根据项目要求灵活运用。
8.1 添加FIFO IP CORE
Step1:新建工程FIFO_TEST
Step2:添加FIFO IP CORE
Step3:如下图选择后单击Next
Step3:时钟选择-Independent Clocks(读和写各用一个时钟),内存类型选用:Blcok RAM
Step4:设置读模式为First-Word Fall Through,此模式下数据和读请求同步出现,如果选择Standard FIFO数据在读请求后输出。数据的宽度选择8bit 深度选择32
Step6:
Almost full flag:接近满标志,提前判断FIFO即将满标志位
Almost full empty:接近空标志可以用来提前判断FIFO即将空标志位
Write Acknowledge:写成功回应标志位
Overflow flag:写溢出标志位
Valid flag:读有效标志位
Underflow flag:读溢出标志
Step7:采用同步复位方式,另外可以编程满,和可编程空标志不选
Step8:勾选计数器,这些读写计数器可以用来评估FIFO数据的大概数量
Step9:单击Generate 产品FIFO的IP
Step11:添加FIFO IP到工程中,并且添加UART串口驱动,利用串口传输功能验证工程的正确性。
8.2 程序分析
读者注意,本章UART串口驱动使用了精简版,和前面的学习版本功能一样。精简版使用起来更加简单。
module FIFO_TEST(
input CLK_50MHZ_i,
input rst_n_i,
input uart_rx_i,
output uart_tx_o
);
parameter WRITE_FIFO=0;
parameter READ_FIFO=1;
wire IsRxdDone,UartIsFull;
wire fifo_full;
wire fifo_empty;
wire [7:0] fifo_din;
wire [7:0] fifo_dout;
wire fifo_wr_en;
wire fifo_rd_en;
reg UartIsSta;
(*KEEP = "TRUE" *) wire [4:0]fifo_rd_cnt;
(*KEEP = "TRUE" *) wire [4:0]fifo_wr_cnt;
//读写FIFO状态机,每次数据读入大于15个就开始输出
reg f_s;
always @(posedge CLK_50MHZ_i)begin
if(~rst_n_i)begin
f_s <= 1‘b0;
end
else begin
case(f_s)
WRITE_FIFO:begin
if(fifo_wr_cnt>=5‘d15)begin //大于15就进入发送状态
f_s <= READ_FIFO;
end
end
READ_FIFO:begin
if(fifo_empty)begin//当FIFO被读空,进入FIFO写状态
f_s <= WRITE_FIFO;
end
end
endcase
end
end
assign fifo_wr_en = (~fifo_full)&IsRxdDone;//使能写
assign fifo_rd_en = UartIsSta; //使能读
FIFO FIFO_0 (
.rst(~rst_n_i), // input rst
.wr_clk(CLK_50MHZ_i), // input wr_clk
.rd_clk(CLK_50MHZ_i), // input rd_clk
.din(fifo_din), // input [7 : 0] din
.wr_en(fifo_wr_en), // input wr_en
.rd_en(fifo_rd_en), // input rd_en
.dout(fifo_dout), // output [7 : 0] dout
.full(fifo_full), // output full
// .almost_empty(fifo_empty),
.empty(fifo_empty), // output empty
.rd_data_count(fifo_rd_cnt), // output [4 : 0] rd_data_count
.wr_data_count(fifo_wr_cnt) // output [4 : 0] wr_data_count
);
//控制串口发送,以及从FIFO读取数据
always @(posedge CLK_50MHZ_i)begin
if(~rst_n_i)begin
UartIsSta <= 1‘b0;
end
else begin
if((f_s==READ_FIFO)&(~fifo_empty)&(~UartIsFull))
UartIsSta <= ~UartIsSta;
else UartIsSta <= 1‘b0;
end
end
UartRxd U1 (.Clk_i(CLK_50MHZ_i),.RevD(fifo_din),.IsDone(IsRxdDone),.Rxd_i(uart_rx_i));//recieve
UartTxd U2 (.Clk_i(CLK_50MHZ_i),.IsSta(UartIsSta),.IsFull(UartIsFull),.SendD(fifo_dout),.Txd_o(uart_tx_o)); //send
endmodule
以上程序状态机,当FIFO中的数据大于15个就开始进入发送状态,在发送状态,只要FIFO还有数据,就一直发送在,直到FIFO数据全部被发送出去。这种用法适用于数据量传输,比如视频流传输。
8.3 测试结果
由上图可以看出,每发送32个自己数据,就实现一次回传,一次性将32字节数据全部回传。
8.4 小结
本章通过一个FIFO回传实验,实现了数据从PC端进入Mis603板卡,然后保存到FIFO中,当FIFO数据大于一定数据后,就进入发模块。