赞
踩
这是vivado中fifo的界面
下面依次介绍每个设置:
fifo实现的方式有Common Clock同步和Independent Clocks异步两种,每种fifo下有四种存储形式:
Block RAM:使用FPGA内部的RAM
Distributed RAM:分布式RAM,使用内部的LUT和逻辑电路组成的fifo,
当深度不大于128时可以使用
shift Register:移位寄存器形式,深度不大于32时可以使用
Built-in:内部自带的fifo,深度大于128可以使用
Read Mode 读模式 Standard FIFO 标准FIFO (选择这个模式,读出的数据会滞后读使能信号一个时间周期) First Word Fall Through 第一个写入数据将被从ram中提前读出到读数据线, 第一个数据有效与empty无效同时,即当empty无效时, 不必读取,数据线上的数据已经有效,读信号有效后, 读数据线将显示下一数据地址(读出的数据与读使能信号同一个时间周期) Data Port Parameters 数据接口参数 write width 写宽度 write depth 写深度 read width 读宽度 read depth 读深度 (后面读的设置通常与写的设置相同) Initialization 初始化 Reset Pin 复位引脚 Enable safety Circuit 启用安全电路 一般都要选上 Reset Type 复位类型,有两种 异步复位和同步复位 Full Flag Reset Value 复位的值,0为低电平复位,1为高电平复位
optional flag 选择的标志
Almost Full Flag 几乎满标志位
Almost Empty Flag 几乎空标志位
Handshaking Options 握手选项 用于设计什么时候读,什么时候写
write port handshaking
write acknowledge 写标志位 分为高有效和低有效
overflow 溢出标志
Read port handshaking
valid flag 有效读
underflow flag 读空标志
Programmable Flags 自定义标志位 用于自定义什么是否写满和什么时候读空的标准
programmable full type
在整个IP文件夹中,.veo文件为模板文件,复制时使用这个
读写FIFO的操作
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2020/07/29 18:49:24 // Design Name: // Module Name: fifo_test // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module fifo_test( input clk, input rst_n ); reg [15:0] w_data ; //FIFO写数据 wire wr_en ; //FIFO写使能 wire rd_en ; //FIFO读使能 wire [15:0] r_data ; //FIFO读数据 wire full ; //FIFO满信号 wire empty ; //FIFO空信号 wire [8:0] rd_data_count ; //可读数据数量 wire [8:0] wr_data_count ; //已写入数据数量 wire clk_100M ; //PLL产生100MHz时钟 wire clk_75M ; //PLL产生100MHz时钟 wire locked ; //PLL lock信号,可作为系统复位信号,高电平表示lock住 wire fifo_rst_n ; //fifo复位信号, 低电平有效 wire wr_clk ; //写FIFO时钟 wire rd_clk ; //读FIFO时钟 reg [7:0] wcnt ; //写FIFO复位后等待计数器 reg [7:0] rcnt ; //读FIFO复位后等待计数器 wire valid; // 指示读数据有效 reg reset_rd; //例化PLL,产生100MHz和75MHz时钟 clk_wiz_0 fifo_pll ( // Clock out ports .clk_out1(clk_100M), // output clk_out1 .clk_out2(clk_75M), // output clk_out2 // Status and control signals .reset(~rst_n), // input reset .locked(locked), // output locked // Clock in ports .clk_in1(clk) // input clk_in1 ); assign fifo_rst_n = locked ; //将PLL的LOCK信号赋值给fifo的复位信号 assign wr_clk = clk_100M ; //将100MHz时钟赋值给写时钟 assign rd_clk = clk_75M ; //将75MHz时钟赋值给读时钟 /* 写FIFO状态机 */ localparam W_IDLE = 1 ; localparam W_FIFO = 2 ; reg[2:0] write_state; reg[2:0] next_write_state; always@(posedge wr_clk or negedge fifo_rst_n) begin if(!fifo_rst_n) write_state <= W_IDLE; else write_state <= next_write_state; end always@(*) begin case(write_state) W_IDLE: begin if(wcnt == 8'd79) //复位后等待一定时间,等待最慢时钟60周期,只针对xilinx来说 next_write_state <= W_FIFO; else next_write_state <= W_IDLE; end W_FIFO: next_write_state <= W_FIFO; //一直在写FIFO状态 default: next_write_state <= W_IDLE; endcase end //在IDLE状态下,也就是复位之后,计数器计数 always@(posedge wr_clk or negedge fifo_rst_n) begin if(!fifo_rst_n) wcnt <= 8'd0; else if (write_state == W_IDLE) wcnt <= wcnt + 1'b1 ; else wcnt <= 8'd0; end reg [7:0] wr_timer; always@(posedge wr_clk or negedge fifo_rst_n) begin if(!fifo_rst_n ) wr_timer <= 0; else if (next_write_state == W_FIFO) wr_timer <= wr_timer + 1'b1; else if (wr_timer == 8'd49) wr_timer <= 8'd0; end //在写FIFO状态下,如果不满就向FIFO中写数据 assign wr_en = (write_state == W_FIFO && wr_timer == 8'd49) ? ~full : 1'b0; //在写使能有效情况下,写数据值加1 always@(posedge wr_clk or negedge fifo_rst_n) begin if(!fifo_rst_n) w_data <= 16'd1; else if (wr_en) w_data <= w_data + 1'b1; end /* 读FIFO状态机 */ localparam R_IDLE = 1 ; localparam R_FIFO = 2 ; reg[2:0] read_state; reg[2:0] next_read_state; ///产生FIFO读的数据 always@(posedge rd_clk or negedge fifo_rst_n) begin if(!fifo_rst_n) read_state <= R_IDLE; else read_state <= next_read_state; end always@(*) begin case(read_state) R_IDLE: begin if (rcnt == 8'd59) //复位后等待一定时间, 等待最慢时钟60周期,只针对xilinx来说 next_read_state <= R_FIFO; else next_read_state <= R_IDLE; end R_FIFO: next_read_state <= R_FIFO ; //一直在读FIFO状态 default: next_read_state <= R_IDLE; endcase end //在IDLE状态下,也就是复位之后,计数器计数 always@(posedge rd_clk or negedge fifo_rst_n) begin if(!fifo_rst_n) rcnt <= 8'd0; else if (write_state == W_IDLE) rcnt <= rcnt + 1'b1 ; else rcnt <= 8'd0; end reg [7:0] rd_timer; always@(posedge rd_clk or negedge fifo_rst_n) begin if(!fifo_rst_n ) begin rd_timer <= 0; reset_rd <= 1; end else if (next_read_state == R_FIFO) begin reset_rd <= 0; rd_timer <= rd_timer + 1'b1; end else if (rd_timer == 8'd99) begin reset_rd <= 1; rd_timer <= 8'd0; end end //在读FIFO状态下,如果不空就从FIFO中读数据 assign rd_en = (read_state == R_FIFO && rd_timer == 8'd99 ) ? ~empty : 1'b0; wire almost_full, wr_ack, overflow, almost_empty, underflow, wr_rst_busy, rd_rst_busy; //实例化FIFO fifo_generator_0 fifo_ip_inst ( .rst (~fifo_rst_n || reset_rd ), // input rst .wr_clk (wr_clk ), // input wr_clk .rd_clk (rd_clk ), // input rd_clk .din (w_data ), // input [15 : 0] din .wr_en (wr_en ), // input wr_en .rd_en (rd_en ), // input rd_en .dout (r_data ), // output [15 : 0] dout .full (full ), // output full .almost_full(almost_full), // output wire almost_full .wr_ack(wr_ack), // output wire wr_ack .overflow(overflow), // output wire overflow .empty (empty ), // output empty .almost_empty(almost_empty), // output wire almost_empty .valid(valid), // output wire valid .underflow(underflow), // output wire underflow .rd_data_count (rd_data_count), // output [8 : 0] rd_data_count .wr_data_count (wr_data_count), // output [8 : 0] wr_data_count .wr_rst_busy(wr_rst_busy), // output wire wr_rst_busy 为0是才能开始读写 .rd_rst_busy(rd_rst_busy) // output wire rd_rst_busy ); endmodule
标准的读操作
FWFT的标准的读操作
对于复位来说
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。