FPGA project : example_fifo

 

// module example_fifo (
//     input           wire             sys_clk ,
//     input           wire    [7:0]    pi_data ,
//     input           wire             rd_req  ,
//     input           wire             wr_req  ,

//     output          wire             mepty   ,
//     output          wire             full    ,
//     output          wire    [7:0]    po_data ,
//     output          wire    [7:0]    usedw    
// );


// scfifo_8x256 scfifo_8x256_insert(
// 	.clock                          ( sys_clk ) ,
// 	.data                           ( pi_data ) ,
// 	.rdreq                          ( rd_req  ) ,
// 	.wrreq                          ( wr_req  ) ,

// 	.empty                          ( mepty   ) ,
// 	.full                           ( full    ) ,
// 	.q                              ( po_data ) ,
// 	.usedw                          ( usedw   ) 
// );
// endmodule

module example_fifo(
    input           wire                wr_clk   ,
    input           wire                wr_req   ,
    input           wire        [7:0]   wr_data  ,
    input           wire                rd_clk   ,
    input           wire                rd_req   ,

    output          wire        [15:00] rd_data  ,
    output          wire                wr_empty ,    
    output          wire                wr_full  ,    
    output          wire        [8:0]   wr_usedw , 
    output          wire                rd_empty ,    
    output          wire                rd_full  ,    
    output          wire        [7:0]   rd_usedw      
);



dcfifo_8x256_to_16x128	dcfifo_8x256_to_16x128_inst (
	.data       ( wr_data       ),
	.rdclk      ( rd_clk        ),
	.rdreq      ( rd_req        ),
	.wrclk      ( wr_clk        ),
	.wrreq      ( wr_req        ),

	.q          ( rd_data       ),
	.rdempty    ( rd_empty      ),
	.rdfull     ( rd_full       ),
	.rdusedw    ( rd_usedw      ),
	.wrempty    ( wr_empty      ),
	.wrfull     ( wr_full       ),
	.wrusedw    ( wr_usedw      )
);


endmodule
`timescale 1ns/1ns
module test_dcfifo ();
    reg           wr_clk   ; // dcfifo 输入信号定义
    reg           wr_req   ;
    reg   [7:0]   wr_data  ;
    reg           rd_clk   ;
    reg           rd_req   ;

    reg           sys_rst_n; // 复位
    reg   [1:0]   cnt_base ; // 用来产生读请求的计数器
    reg           wr_full_reg0 ;
    reg           wr_full_reg1 ;

    wire  [15:00] rd_data  ;
    wire          wr_empty ; 
    wire          wr_full  ;  
    wire  [8:0]   wr_usedw ;
    wire          rd_empty ; 
    wire          rd_full  ; 
    wire  [7:0]   rd_usedw ;

	 parameter CYCLE = 20 ;
    initial begin
        wr_clk = 1'b1       ; // 读写时钟赋初值
        rd_clk = 1'b1       ; // 复位信号描述
        sys_rst_n <= 1'b0   ;
        #(CYCLE)            ; 
        sys_rst_n <= 1'b1   ;
    end

    always #(CYCLE / 2) wr_clk = ~wr_clk ; // 写时钟频率是读时钟的二倍。
    always #(CYCLE    ) rd_clk = ~rd_clk ;

    // cnt_base 0 ~ 3 循环计数 为了产生写请求,故在写时钟域下。
    always @(posedge wr_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_base <= 1'b0 ;
        end else begin
            if(cnt_base == 2'd3) begin
                cnt_base <= 1'b0 ;
            end else begin
                cnt_base <= cnt_base + 1'b1 ;
            end
        end
    end

    // wr_req 读请求,在写时钟域下 cnt_base == 0 且没有读请求时拉高时,拉高一个wr_clk周期
    always @(posedge wr_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            wr_req <= 1'b0 ;
        end else begin
            if(cnt_base == 2'd0 && rd_req == 1'b0) begin
                wr_req <= 1'b1 ;
            end else begin
                wr_req <= 1'b0 ;
            end
        end
    end

    // wr_data 写数据 在写时钟域下,在写在写请求拉高时,wr_data == 255(因为深度是256) 归零。
    // 没计满 则在写请求拉高时,加一
    always @(posedge wr_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            wr_data <= 8'b0 ;
        end else begin
            if(wr_data == 8'd255 && wr_req == 1'b1) begin
                wr_data <= 8'd0 ;
            end else begin
                if(wr_req == 1'b1) begin
                    wr_data <= wr_data + 1'b1 ;
                end else begin
                    wr_data <= wr_data ;
                end
            end
        end
    end

    // wr_full 跨时钟域同步处理 wr_full_reg1
    always @(posedge rd_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            wr_full_reg0 <= 1'b0 ;
            wr_full_reg1 <= 1'b0 ;
        end else begin
            wr_full_reg0 <= wr_full ;
            wr_full_reg1 <= wr_full_reg0 ;
        end
    end

    // rd_req 写满开读,读空拉低。(读请求)拉低后写请求拉高
    always @(posedge rd_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            rd_req <= 1'b0 ;
        end else begin
            if(wr_full_reg1 == 1'b1) begin
                rd_req <= 1'b1 ;
            end else begin
                if(rd_empty) begin
                    rd_req <= 1'b0 ;
                end else begin
                    rd_req <= rd_req ; 
                end
            end
        end
    end

example_fifo example_fifo_insert(
    .wr_clk                     ( wr_clk   ) ,
    .wr_req                     ( wr_req   ) ,
    .wr_data                    ( wr_data  ) ,
    .rd_clk                     ( rd_clk   ) ,
    .rd_req                     ( rd_req   ) ,

    .rd_data                    ( rd_data  ) ,
    .wr_empty                   ( wr_empty ) ,    
    .wr_full                    ( wr_full  ) ,  // 写满标志信号,在写时钟域下。
    .wr_usedw                   ( wr_usedw ) ,    // 需要同步到读时钟域下  用来拉高读请求。 
    .rd_empty                   ( rd_empty ) ,  // 读空  用来拉低读请求
    .rd_full                    ( rd_full  ) ,    
    .rd_usedw                   ( rd_usedw )      
);

endmodule
`timescale 1ns/1ns
module test_fifo();
    reg                     sys_clk ; // 系统时钟
    reg     [7:0]           pi_data ; // 写数据 输入
    reg                     rd_req  ; // 读请求
    reg                     wr_req  ; // 写请求

    wire                    empty   ; // 空标志 可以用来控制读请求
    wire                    full    ; // 满标志 可以用来控制读请求
    wire    [7:0]           po_data ; // 读数据输出
    wire    [7:0]           usedw   ; // 数据余量

    reg                     sys_rst_n ; // 系统复位(仿真文件用到)
    reg     [1:0]           cnt_base  ; // 0 ~ 3 计数器

// Instantiation
example_fifo example_fifo_insert (
    .sys_clk                ( sys_clk ) ,
    .pi_data                ( pi_data ) ,
    .rd_req                 ( rd_req  ) ,
    .wr_req                 ( wr_req  ) ,

    .mepty                  ( empty   ) ,
    .full                   ( full    ) ,
    .po_data                ( po_data ) ,
    .usedw                  ( usedw   )    
);
    parameter CYCLE = 20 ;
    // cnt_base 4个时钟周期 用来产生读写使能
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_base <= 2'd0 ;
        end else begin
            if(cnt_base == 2'd3) begin
                cnt_base <= 2'd0 ;
            end else begin
                cnt_base <= cnt_base + 1'b1 ;
            end
        end
    end
    // wr_req 写请求,再没有读请求时,cnt_base == 0 拉高一个sys_clk 时钟周期写请求
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            wr_req <= 1'b0 ;
        end else begin
            if(cnt_base == 2'd0 && rd_req == 1'b0 ) begin // 读请求拉低后,即开始写数据
                wr_req <= 1'b1 ;
            end else begin
                wr_req <= 1'b0 ;
            end
        end
    end
    // pi_data  写入的数据 在读请求拉高的情况下,每过一个时钟周期数据加一.
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            pi_data <= 8'd0 ;
        end else begin
            if(pi_data == 8'd255 && wr_req == 1'b1) begin 
                pi_data <= 8'd0 ;
            end else begin
                if(wr_req == 1'b1) begin
                    pi_data <= pi_data + 1'b1 ;
                end else begin
                    pi_data <= pi_data ;
                end
            end
        end
    end
    // rd_req 写满开读,读空停止
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            rd_req <= 1'b0 ;
        end else begin
            if(full == 1'b1) begin
                rd_req <= 1'b1 ;
            end else begin
                if(empty == 1'b1) begin
                    rd_req <= 1'b0 ;
                end else begin
                    rd_req <= rd_req ;
                end
            end
        end
    end

    initial begin // 初始化
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        #( CYCLE * 100)   ;
        sys_rst_n <= 1'b1 ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;

endmodule

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值