手把手 Veriolg HDL的 4位单信号的乒乓Buffer操作

一级目录

二级目录

三级目录

1 乒乓简介

乒乓操作是FPGA设计中常用的一种技巧,两组或者多组相同或者类似的结构,通过并行工作,轮流输出的形式,提高处理性能的一种结构,此处以2组为例。

此处的乒乓都是不带存储的,即Buffer都是1个数据深度。先实现简单的,然后在基础上将Buffer换成两个FIFO,每个FIFO也可以各自加上握手·····等等。

有关FIFO、Valid—Ready握手相关请转至上一篇文章:同步Vaild-Ready握手FIFO机制链接:
链接: link

在这里插入图片描述

2 乒乓原理

如上图所示,有以下4点:
1、数据输入进来,2选1进Buffer;数据输出出去,2选1出Buffer。
2、写1时2读,写2时1读。
3、对Buffer的写与读都通过读写使能控制。
4、读写使能通过**状态机**控制。

3 状态机设置

电路只有两种状态,即**写1读2**,**写2读1**,故使用**一位信号不断取反**即可实现状态切换。

4 代码

模块代码:

module PingPang #(parameter WIDTH = 4) (
    input                   clk,
    input                   rst_n,
    input      [WIDTH-1:0]  data_in,
    output reg [WIDTH-1:0]  data_out
);

//reg define
reg [WIDTH-1:0]  buffer1;                   //ping
reg [WIDTH-1:0]  buffer2;                   //pang
reg wr_buffer1;                             //buffer1写使能
reg wr_buffer2;                             //buffer2写使能
reg rd_buffer1;                             //buffer1读使能
reg rd_buffer2;                             //buffer2读使能

//state define
reg state;
parameter s0 = 1'b0,s1 = 1'b1;

always@(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        state <= s0;
    else
        state <= ~state;

end

always@(*)
begin
    case(state)
        s0:                                   //写1读2
        begin
           wr_buffer1 <= 1'b1; 
           rd_buffer2 <= 1'b1;               
           wr_buffer2 <= 1'b0;                    
           rd_buffer1 <= 1'b0;                   
        end
        s1:                                   //写2读1
        begin
           wr_buffer1 <= 1'b0; 
           rd_buffer2 <= 1'b0;               
           wr_buffer2 <= 1'b1;                    
           rd_buffer1 <= 1'b1;                   
        end
        default:                              //写1读2
        begin
           wr_buffer1 <= 1'b1; 
           rd_buffer2 <= 1'b1;               
           wr_buffer2 <= 1'b0;                    
           rd_buffer1 <= 1'b0;                   
        end
    endcase
end

//根据标志位写数据
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n) begin
        buffer1 <= 4'b0;
        buffer2 <= 4'b0;
    end
    else begin
        if(wr_buffer1 && (!wr_buffer2))
        buffer1 <= data_in;
        else if (wr_buffer2 && (!wr_buffer1))
        buffer2 <= data_in;
        else begin
        buffer1 <= 4'b0;
        buffer2 <= 4'b0;
        end
    end
end
//根据标志位读数据
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n) begin
       data_out <= 4'b0;
    end
    else begin
        if(rd_buffer1 && (!rd_buffer2))
        data_out <= buffer1;
        else if (rd_buffer2 && (!rd_buffer1))
        data_out <= buffer2;
        else
        data_out <= 4'b0;
    end
end
endmodule

testbench代码:

`timescale 1ns/1ns

module tb_PingPang#(parameter WIDTH = 4);
reg                   clk;
reg                   rst_n;
reg      [WIDTH-1:0]  data_in;
wire     [WIDTH-1:0]  data_out;

PingPang PingPang_u0 (
                .clk(clk),
                .rst_n(rst_n),
                .data_in(data_in),
                .data_out(data_out));


initial begin
        rst_n    = 1'b0;
        clk      = 1'b0;

#20     rst_n    = 1'b1;
#20 repeat(8) begin
		@(posedge clk)begin		
			data_in <= $random;
		end
	end
end

always begin
#10    clk = ~clk;
end
endmodule

5 波形

输入的波形在Buffer1和Buffer2中来回切换,并且输出。
在这里插入图片描述至此完结!!!
下面来考虑,如何把Buffer1和2都换成两个可以存储的FIFO呢?具体解决思路我过几天再更新。
最后一样,贴上邮箱:boyue8817505@163.com

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值