ZYNQ学习之FIFO使用

本文详细介绍了FIFO的基本原理及其在Vivado中的应用,包括使用FIFO IP核进行数据缓存,通过状态机控制写入与读取操作,并利用PLL产生不同频率的时钟信号。此外,还提供了具体的Verilog代码实现和ILA探针配置用于监控FIFO的工作状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.FIFO原理介绍

2.FIFO IP 在vivado中使用。

3.建立顶层文件

module fifo_test(
    input clk_sys,
    input rst_n

    );
reg [15:0]  w_data;
wire        wr_en;
wire        rd_en;
wire   [15:0] r_data;
wire         full;
wire         empty;
wire  [8:0]  rd_data_count;
wire  [8:0]  wr_data_count;

wire         clk_50M;
wire         clk_25M;
wire         locked;

wire     fifo_rst_n;
wire     wr_clk;
wire     rd_clk;
reg [7:0]  wcnt;
reg [7:0]  rcnt;

//例化pll,产生写入时钟50MHz和输出时钟25Mhz,输出给FIFO
  clk_wiz_0 pll_clk
   (
    // Clock out ports
    .clk_out1(clk_50M),     // output clk_out1
    .clk_out2(clk_25M),     // output clk_out2
    // Status and control signals
    .reset(rst_n), // input reset
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(clk_sys)
    );      // input clk_in1
  //PLL产生时钟赋值给FIFO
 assign fifo_rst_n=locked;
 assign wr_clk=clk_50M;
 assign rd_clk=clk_25M;   
    
  //写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'd120)
                next_write_state<=W_FIFO;
            else
                next_write_state<=W_IDLE;
            end
         W_FIFO:
             next_write_state<=W_FIFO;
          default:
            next_write_state<=W_IDLE;
     endcase
end

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

//在写FIFO状态下,如果不满就继续向FIFO中写数据,写满就停止写入
assign wr_en=(write_state==W_FIFO)? ~full:1'b0;
//在写使能的情况下,写入数据值如何变化
always@(posedge wr_clk or negedge fifo_rst_n)
begin   
    if(!fifo_rst_n)
    w_data<=16'd0;
    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;
 
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'd60)
                 next_read_state<=R_FIFO;
             else
                 next_read_state<=R_IDLE;
             end
          R_FIFO:
              next_read_state<=R_FIFO;
           default:
             next_read_state<=R_IDLE;
      endcase
 end       
 always@(posedge rd_clk or negedge fifo_rst_n)
 begin
     if(!fifo_rst_n)
         rcnt<=8'd0;
     else if (read_state==R_IDLE)
         rcnt<=rcnt+1'b1;
     else
       rcnt<=8'd0;
 end   
 //在读FIFO状态下,如果不空就从FIFO中读数据
 assign rd_en=(read_state==R_FIFO)? ~empty:1'b0;
 
 
 //例化FIFO IP核
 fifo_ip FIFO_init (
   .wr_clk(wr_clk),                // input wire wr_clk
   .rd_clk(rd_clk),                // input wire rd_clk
   .din(w_data),                      // input wire [15 : 0] din
   .wr_en(wr_en),                  // input wire wr_en
   .rd_en(rd_en),                  // input wire rd_en
   .dout(r_data),                    // output wire [15 : 0] dout
   .full(full),                    // output wire full
   .empty(empty),                  // output wire empty
   .rd_data_count(rd_data_count),  // output wire [8 : 0] rd_data_count
   .wr_data_count(wr_data_count)  // output wire [8 : 0] wr_data_count
 );
 ila_0 ila_wr (
     .clk(clk_sys), // input wire clk 
     .probe0(w_data), // input wire [15:0]  probe0  
     .probe1(wr_en), // input wire [0:0]  probe1 
     .probe2(full), // input wire [0:0]  probe2 
     .probe3(wr_data_count) // input wire [8:0]  probe3
 );
 ila_0 ila_rd (
     .clk(clk_sys), // input wire clk
     .probe0(r_data), // input wire [15:0]  probe0  
     .probe1(rd_en), // input wire [0:0]  probe1 
     .probe2(empty), // input wire [0:0]  probe2 
     .probe3(rd_data_count) // input wire [8:0]  probe3
 );            
              
    
endmodule

4.读写测试

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA&SDR探索者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值