草庐IT

FPGA设计——verilog实现乒乓操作并modelsim仿真

Fighting_XH 2023-04-14 原文

乒乓操作是FPGA设计中常用的一种技巧,它通过数据流控制实现按节拍相互配合的切换,来提高数据处理效率,达到无缝缓冲和处理的效果。本文针对乒乓操作进行学习总结。
完整工程

乒乓操作的原理

一、原理图如下

1、二选一控制器来对缓冲模块1和2进行选择。
2、数据缓冲模块一般就是SDRAM,FIFO等。
3、每一时刻如何工作:
clk1 时刻,输入数据data存入到mux1选择的缓冲1中。
clk2时刻,将data数据存在mux1 选择的缓冲2中,同时mux2选择缓冲1,将缓冲1中的数据送到后续处理中。
clk3时刻,mux1选通了缓冲1,将输入data存在缓冲1,同时mux2选择缓冲2,将其中的数据送到后续处理中
4、依次切换循环,从而实现乒乓操作。


二、波形表示
通过乒乓操作,我们即可通过节拍相互配合,最终实现数据的无缝缓冲与发送。
简单来看就是缓冲1写,则缓冲2读;缓冲2写,缓冲1读。

优点

1、 实现数据的无缝缓冲和处理;——按节拍相互配合进行切换

2、 可节约缓冲区空间;

3、 可实现低速模块处理高速模块。

乒乓操作的verilog实现

1、采用case语句来进行选择。
2、确定该模块的输入输出端口:

3、由于乒乓操作就是缓冲1写,缓冲2读;缓冲2写,缓冲1读,共这两种情况,采用state的高低电平进行选择。
其中高电平1表示写1读2,低电平0表示写2读1
4、verilog代码

module pingpong(
    input clk,
    input rst,
    input [7:0] data_in,
    output reg [7:0] data_out
);
	 
reg [7:0] buffer_1;
reg [7:0] buffer_2;
reg wr_flag1;                            //写标志,wr_flag1=0,buffer_2写;wr_flag1=1,buffer_1写
reg rd_flag2;                            //读标志,rd_flag2=0,buffer_1读;rd_flag2=1,buffer_2读
reg state;             // 1:写1读2,   0:写2读1
 
 
// 状态每一个clk,翻转一次(二分频)
always@(posedge clk or negedge rst) begin
    if (!rst)
        state<= 0;
    else
        state<= ~state;

end

//二选一多路器,原理图中的选择控制模块
always@(*)
begin
    case(state) 
        1'b0:   //buffer2写,buffer1读
        begin
            wr_flag1<=0;
            rd_flag2<=0;
        end
        1'b1://buffer1写,buffer2读
        begin
            wr_flag1<=1;
            rd_flag2<=1;
        end
        default:
        begin
            wr_flag1<=0;
            rd_flag2<=0;
        end
    endcase
end
 
//写缓存buffer数据
always@(posedge clk or negedge rst)
begin
    if(!rst)begin
        buffer_1<=8'b0;
        buffer_2<=8'b0;
    end
	 
    else begin
        case(wr_flag1) //根据写标志,判断往哪个缓冲中写数据
            0: buffer_2<=data_in;//此时,写buffer1保持上一时刻的数据
				
            1: buffer_1<=data_in;//此时,写buffer2保持上一时刻的数据
				
            default:begin
                buffer_1<=0;
                buffer_2<=0;
            end
        endcase
    end
end
//读缓存buffer数据
always@(posedge clk or negedge rst)
begin
    if(!rst)
        data_out<=8'b0;
    else
        case(rd_flag2)//根据读标志,判断读哪个缓冲中的数据
            0:data_out<=buffer_1; //读buffer_1的数据
				
            1:data_out<=buffer_2;
				
            default:data_out<=0;
        endcase
end
endmodule

tb测试:

`timescale 1ns / 1ps
module pingpong_operation_tb;
	reg clk;
	reg rst_n;
	reg [7:0] data_in;
	wire [7:0] data_out;
	
	pingpong_operation u_pingpong(
    .clk(clk),
    .rst_n(rst_n),
    .data_in(data_in),
    .data_out(data_out)
    );
	
	
initial begin
    clk = 0;
    rst_n = 0;
    #40 rst_n =1;
	 #100000;
	 $stop;
end
 
always #10 clk = ~clk; //一个ck为20ns

//产生输入激励
 
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        data_in<=0;
     else
        data_in<=data_in+1;
end
 	 
endmodule

波形如下:
state = 1 :buffer1写,读buffer2;
state = 0 :buffer2写,读buffer1;

读写标志:
state = 1 :wr_flag1 = 1;rd_flag2= 1;
state = 0 :wr_flag1 = 0;rd_flag2= 0;

写进哪个缓冲?
wr_flag1 = 1 : buffer_1<=data_in;此时,buffer_2保持上一时刻数据不变。
wr_flag1 = 0 : buffer_2<=data_in;此时,buffer_1保持上一时刻数据不变。

读哪个缓冲中的数据?
rd_flag2 = 0 : data_out<=buffer_1;
rd_flag2 = 1 : data_out<=buffer_2;

可看到与我们前面根据原理分析出的波形相同。

有关FPGA设计——verilog实现乒乓操作并modelsim仿真的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  7. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  8. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

随机推荐