FIFO读写实验

FIFO一般用于不同时钟域之间的数据传输,也常用来实现不同位宽的接口的数据匹配。(可以避免两个模块时钟不一致,造成的亚稳态状态,也可以进行数据缓存,也可以解决数据发送时两边时钟不一致)

FIFO读写实验_第1张图片

 利用FIFO在不同位宽的接口之间作数据匹配:(可以将fifo输入端设计为8位,输出端设计为16位,就可以解决该问题)

FIFO读写实验_第2张图片

下面是本次实验的系统框图

FIFO读写实验_第3张图片

1.fifo ip核的设计

在ip catalog中搜索fifo,双击fifo

FIFO读写实验_第4张图片

然后在工程文件夹中创建IPcore文件夹,然后再在里面建fifo文件夹,最后将ip核定义为fifo保存

并选择verilog

FIFO读写实验_第5张图片

开始配置

FIFO读写实验_第6张图片

 

FIFO读写实验_第7张图片

FIFO读写实验_第8张图片

 FIFO读写实验_第9张图片

正常模式:

FIFO读写实验_第10张图片

前显模式:

 FIFO读写实验_第11张图片

最下面那个框不勾,不使用逻辑资源去实现fifo功能

FIFO读写实验_第12张图片

 FIFO读写实验_第13张图片

 点击finish,完成设计

2.程序设计

fifo_rd模块

FIFO读写实验_第14张图片

 

module fifo_rd(
    //system clock
    input                    clk    ,        // 时钟信号
    input                    rst_n  ,        // 复位信号(低有效)

    //user interface
    input           [7:0]    data   ,        // 从FIFO输出的数据
    input                    rdfull ,        // 读满信号
    input                    rdempty,        // 读空信号
    output   reg             rdreq           // 读请求
);

//reg define
reg   [7:0]                  data_fifo;      // 读取的FIFO数据
reg   [1:0]                  flow_cnt ;      // 状态流转计数

//*****************************************************
//**                    main code
//*****************************************************

//从FIFO中读取数据
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        rdreq <= 1'b0;
        data_fifo <= 8'd0;
    end
    else begin
        case(flow_cnt)
            2'd0: begin
                if(rdfull) begin
                    rdreq <= 1'b1;
                    flow_cnt <= flow_cnt + 1'b1;
                end
                else
                    flow_cnt <= flow_cnt;
            end 
            2'd1: begin
                if(rdempty) begin
                    rdreq <= 1'b0;
                    data_fifo <= 8'd0;
                    flow_cnt  <= 2'd0;
                end
                else begin
                    rdreq <= 1'b1;
                    data_fifo <= data;
                end 
            end 
            default: flow_cnt <= 2'd0;
        endcase
    end
end

endmodule

 fifo_wr模块

FIFO读写实验_第15张图片

 

module fifo_wr(
    //mudule clock
    input                   clk    ,        // 时钟信号
    input                   rst_n  ,        // 复位信号

    //user interface
    input                   wrempty,        // 写空信号
    input                   wrfull ,        // 写满信号
    output    reg  [7:0]    data   ,        // 写入FIFO的数据
    output    reg           wrreq           // 写请求
);

//reg define
reg   [1:0]         flow_cnt;               // 状态流转计数

//*****************************************************
//**                    main code
//*****************************************************

//向FIFO中写入数据
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        wrreq <= 1'b0;
        data  <= 8'd0;
        flow_cnt <= 2'd0;
    end
    else begin
        case(flow_cnt)
            2'd0: begin 
                if(wrempty) begin     //写空时,写请求拉高,跳到下一个状态
                    wrreq <= 1'b1;
                    flow_cnt <= flow_cnt + 1'b1;
                end 
                else
                    flow_cnt <= flow_cnt;
            end 
            2'd1: begin               //写满时,写请求拉低,跳回上一个状态
                if(wrfull) begin
                    wrreq <= 1'b0;
                    data  <= 8'd0;
                    flow_cnt <= 2'd0;
                end
                else begin            //没有写满的时候,写请求拉高,继续输入数据
                    wrreq <= 1'b1;
                    data  <= data + 1'd1;
                end
            end 
            default: flow_cnt <= 2'd0;
        endcase
    end
end

endmodule

 顶层模块:

FIFO读写实验_第16张图片

 

module ip_fifo(          //顶层文件
    input    sys_clk    ,         // 时钟信号
    input    sys_rst_n            // 复位信号
);

//wire define
wire            wrreq   ;         // 写请求信号
wire    [7:0]   data    ;         // 写入FIFO的数据
wire            wrempty ;         // 写侧空信号
wire            wrfull  ;         // 写侧满信号
wire            wrusedw ;         // 写侧FIFO中的数据量

wire            rdreq   ;         // 读请求信号
wire    [7:0]   q       ;         // 从FIFO输出的数据
wire            rdempty ;         // 读侧空信号
wire            rdfull  ;         // 读侧满信号
wire            rdusedw ;         // 读侧FIFO中的数据量
//*****************************************************
//**                    main code
//*****************************************************

//例化FIFO模块
fifo u_fifo(
    .wrclk   ( sys_clk ),         // 写时钟
    .wrreq   ( wrreq   ),         // 写请求
    .data    ( data    ),         // 写入FIFO的数据
    .wrempty ( wrempty ),         // 写空信号
    .wrfull  ( wrfull  ),         // 写满信号
    .wrusedw ( wrusedw ),         // 写侧数据量
    
    .rdclk   ( sys_clk ),         // 读时钟
    .rdreq   ( rdreq   ),         // 读请求
    .q       ( q       ),         // 从FIFO输出的数据
    .rdempty ( rdempty ),         // 读空信号
    .rdfull  ( rdfull  ),         // 读满信号
    .rdusedw ( rdusedw )          // 读侧数据量
);

//例化写FIFO模块
fifo_wr u_fifo_wr(
    .clk     (sys_clk ),          // 写时钟
    .rst_n   (sys_rst_n),         // 复位信号

    .wrreq   (wrreq   ),          // 写请求
    .data    (data    ),          // 写入FIFO的数据
    .wrempty (wrempty ),          // 写空信号
    .wrfull  (wrfull  )           // 写满信号
);

//例化读FIFO模块
fifo_rd u_fifo_rd(
    .clk     (sys_clk ),          // 读时钟
    .rst_n   (sys_rst_n),         // 复位信号

    .rdreq   (rdreq   ),          // 读请求
    .data    (q       ),          // 从FIFO输出的数据
    .rdempty (rdempty ),          // 读空信号
    .rdfull  (rdfull  )           // 读满信号
);

endmodule

 系统rtl图FIFO读写实验_第17张图片

 仿真文件

`timescale 1 ns/ 1 ns
module ip_fifo_tb();

parameter T = 20;
reg sys_clk;
reg sys_rst_n;

                                          
wire            wrreq   ;         // 写请求信号
wire    [7:0]   data    ;         // 写入FIFO的数据
wire            wrempty ;         // 写侧空信号
wire            wrfull  ;         // 写侧满信号
wire            wrusedw ;         // 写侧FIFO中的数据量

wire            rdreq   ;         // 读请求信号
wire    [7:0]   q       ;         // 从FIFO输出的数据
wire            rdempty ;         // 读侧空信号
wire            rdfull  ;         // 读侧满信号
wire            rdusedw ;         // 读侧FIFO中的数据量

                     

initial                                                
begin                                                  

	sys_clk = 1'b0;
	sys_rst_n = 1'b0;
   
	#200 
	sys_rst_n = 1'b1;
    //模拟发送一帧数据
   
    #1500000  $stop;
	
                   
end                                                    
always #(T/2)  sys_clk = ~sys_clk;                                              
    
fifo u_fifo(
    .wrclk   ( sys_clk ),         // 写时钟
    .wrreq   ( wrreq   ),         // 写请求
    .data    ( data    ),         // 写入FIFO的数据
    .wrempty ( wrempty ),         // 写空信号
    .wrfull  ( wrfull  ),         // 写满信号
    .wrusedw ( wrusedw ),         // 写侧数据量
    
    .rdclk   ( sys_clk ),         // 读时钟
    .rdreq   ( rdreq   ),         // 读请求
    .q       ( q       ),         // 从FIFO输出的数据
    .rdempty ( rdempty ),         // 读空信号
    .rdfull  ( rdfull  ),         // 读满信号
    .rdusedw ( rdusedw )          // 读侧数据量
);

//例化写FIFO模块
fifo_wr u_fifo_wr(
    .clk     (sys_clk ),          // 写时钟
    .rst_n   (sys_rst_n),         // 复位信号

    .wrreq   (wrreq   ),          // 写请求
    .data    (data    ),          // 写入FIFO的数据
    .wrempty (wrempty ),          // 写空信号
    .wrfull  (wrfull  )           // 写满信号
);

//例化读FIFO模块
fifo_rd u_fifo_rd(
    .clk     (sys_clk ),          // 读时钟
    .rst_n   (sys_rst_n),         // 复位信号

    .rdreq   (rdreq   ),          // 读请求
    .data    (q       ),          // 从FIFO输出的数据
    .rdempty (rdempty ),          // 读空信号
    .rdfull  (rdfull  )           // 读满信号
);                  
endmodule

 

 

 

 

你可能感兴趣的:(fpga,verilog,fifo)