Verilog中输入数据范围的判断

2023-05-16

0.完整源码获得方式

订阅MATLAB/FPGA教程,免得获得教程案例以及任意2份完整源码

----------------------------------------------------------------------------------------------------

在系统设计的过程中,经常需要根据输入数据的值,对相关信号的值进行改变。如果输入数据的边界值数量比较少,可以用条件操作符、if...else、case等结构实现。但是如果数据边界值的数量很多,使用条件操作符和if...else会导致最差情况下的延时增加,使用case会导致代码量巨大。在这种情况下,使用不同的Verilog代码可以对系统的资源和速度产生很大影响。
比如在某MP3解码系统中,存在如下代码:

always@(Sample_reg_Temp0)
begin
 if(Sample_reg_Temp0==0||Sample_reg_Temp0==1)
   Is_Exp_Temp=5'b0;
 else if(Sample_reg_Temp0==2)
   Is_Exp_Temp=5'b00010;
 else if(Sample_reg_Temp0==3||Sample_reg_Temp0==4)
   Is_Exp_Temp=5'b00011;
 else if((Sample_reg_Temp0>4)&&(Sample_reg_Temp0<9))
   Is_Exp_Temp=5'b00100;
 else if((Sample_reg_Temp0>8)&&(Sample_reg_Temp0<14))
   Is_Exp_Temp=5'b00101;  
 //中间部分省略
 else if((Sample_reg_Temp0>2435)&&(Sample_reg_Temp0<4097))
   Is_Exp_Temp=5'b10000;//save 2^15
 else if((Sample_reg_Temp0>4096)&&(Sample_reg_Temp0<6889))
   Is_Exp_Temp=5'b10001;//save 2^14
 else          
   Is_Exp_Temp=5'b10010;//save 2^13
end

由于if...else结构是按照顺序的方法对每个条件进行一次判断,所以如果采用以上代码,在最差情况下Is_Exp_Temp的数据需要经过17级(中间部分省略)多路选择器的延时才能有效,这样会严重拖慢整个系统的速度。而且按照上述代码的写法,Is_Exp_Temp用到了33个16bit的比较器,也消耗了很多的系统资源。

方法一:二分法
Sample_reg_Temp0是16bit的,所以我们可以通过16级多路选择器,确定Sample_reg_Temp0的值的范围,根据其范围对Is_Exp_Temp进行赋值。这样最终会产生2^16=65536种可能性,代码量巨大。但是由于实际中Sample_reg_Temp0只有17个固定的边界,当Sample_reg_Temp0的值确定在一定范围内时就可以将该范围内的数据进行合并。
举例来说,当Sample_reg_Temp0 >= 6889时Is_Exp_Temp = 5'b10010,而Sample_reg_Temp0[15]==1'b1时,Sample_reg_Temp0的范围是[32768,65535],所以Sample_reg_Temp0[15]==1'b1时Is_Exp_Temp = 5'b10010,无需再对Sample_reg_Temp0[14:0]的值进行判断,可以大大减少代码的编写量。
采用这种方法,数据输出需要经过16级多路选择器的延时,在速度上改进不大,但是这种方法不需要用到比较器,对每一位的判断都需要一个多路选择器,而且每一级对下级一数据进行判断时需要用到2个多路选择器,增加了多路选择器的数量,最终的资源占用和实际的数据边界有很大关系。

方法二:优化哈夫曼树
通过对代码的分析,可以得知和Is_Exp_Temp有关的Sample_reg_Temp0边界值x有以下几个:
0
1
2
3
5
9
14
23
39
65
108
182
305
513
862
1449
2436
4097
6889
65536
当x[i] =< Sample_reg_Temp0 < x[i+1] (0<i<17)时,Is_Exp_Temp有一个固定的值。所以以边界值的序号做二分,建立一个哈夫曼树。然后使用if...else对每一个节点的值进行判断,最终确定Sample_reg_Temp0的范围,完成对Is_Exp_Temp的赋值。最终代码如下所示:
//为了减少占用的版面,去除了所有的begin...end关键字,只使用缩进来表示层次关系。
    always @(Sample_reg_Temp0)
        if(Sample_reg_Temp0 < 182)
            if(Sample_reg_Temp0 < 23)    
                if(Sample_reg_Temp0 < 9)
                    case(Sample_reg_Temp0)    //synopsys parallel_case
                        0, 1 : Is_Exp_Temp <= 5'b0;
                        2 : Is_Exp_Temp <= 5'b00010;
                        3, 4 : Is_Exp_Temp <= 5'b00011;
                        5, 6, 7, 8 : Is_Exp_Temp <= 5'b00100;
                        default : Is_Exp_Temp <= 5'b11111;
                    endcase
                else
                    if(Sample_reg_Temp0 < 14)    //9-13
                        Is_Exp_Temp <= 5'b00101;
                    else    //14-22
                        Is_Exp_Temp <= 5'b00110; 
            else
                if(Sample_reg_Temp0 < 65)
                    if(Sample_reg_Temp0 < 39)    //23-38
                        Is_Exp_Temp <= 5'b00111; 
                    else    //39-64
                        Is_Exp_Temp <= 5'b01000;
                else
                    if(Sample_reg_Temp0 < 108)    //65-108
                        Is_Exp_Temp <= 5'b01001;
                    else    //108-181
                        Is_Exp_Temp <= 5'b01010;
        else
            if(Sample_reg_Temp0 < 1449)
                if(Sample_reg_Temp0 < 513)
                    if(Sample_reg_Temp0 < 305)    //182-304
                        Is_Exp_Temp <= 5'b01011;
                    else    //305-512
                        Is_Exp_Temp <= 5'b01100;
                else
                    if(Sample_reg_Temp0 < 862)    //513-861
                        Is_Exp_Temp <= 5'b01101;
                    else    //862-1448
                        Is_Exp_Temp <= 5'b01110;
            else
                if(Sample_reg_Temp0 < 4097)
                    if(Sample_reg_Temp0 < 2436)    //1449-2435
                        Is_Exp_Temp <= 5'b01111;
                    else    //2436-4096
                        Is_Exp_Temp <= 5'b10000;
                else
                    if(Sample_reg_Temp0 < 6889)    //4097-6889
                        Is_Exp_Temp <= 5'b10001;
                    else    //6889+
                        Is_Exp_Temp <= 5'b10010;
在对小于9的值进行判断时,为了减少使用的if...else级数,使用了并行case对有限的几个值进行进行多路选择,这样就可以把if...else的层数控制在4层。
采用以上方法,使用14个16bit比较器、14个双路选择器、一个9选择的多路选择器,就实现了Is_Exp_Temp的改变,相对于最初的33个比较器,17个双路选择器,大大减少了所用的资源,同时将Is_Exp_Temp的有效延时从17级多路选择器减少到4级,提升了系统的运行速度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Verilog中输入数据范围的判断 的相关文章

  • Quartus Prime 中的“多个常量驱动程序”Verilog 错误

    我正在致力于用 Verilog 设计一个有限状态机来表示堆栈 该模块如下 module state machine s Enable Clock Resetn c OF Err UF Err input 2 0 s input Enable
  • 带有always_comb结构的Systemverilog问题

    我对这个 SystemVerilog 代码有疑问 这是代码 module mult multiplicand multiplier Product clk clear Startm endm input 31 0 multiplicand
  • Verilog 奇怪的仿真结果综合后

    我面临一个奇怪的问题 该代码适用于简单的 ALU 仅将感兴趣的代码粘贴到此处 always posedge clk or posedge rst begin if rst 1 begin mul valid shr 3 b000 end e
  • 模加法器输出显示没有变化

    输出波形显示无变化sum dif burrow and out 即使增加延迟时间后 输出仍然没有变化 这应该像 mod 加法器一样工作 如加 10 和 2 并且 mod 3 给出输出零 CODE module Mod adder a b p
  • 使用数据流模型的T触发器

    我正在尝试模拟 t flipflop 的工作 timescale 1ns 1ps module t flipflop input t input clk input clear output q output qbar wire sbar
  • 使用forever和always语句

    以下两个代码都会生成一个时钟 我需要知道除了时钟生成之外 永远循环是否还有其他用途 我只在时钟一代中遇到过永远 如果只是为了这个目的 那岂不是毫无用处 initial begin clk 0 forever begin 5 clk clk
  • 如何生成异步复位verilog总是阻塞凿子

    Chisel 始终生成敏感度列表中仅包含时钟的块 always posedge clk begin end 是否可以将模块配置为使用异步重置并生成这样的始终块 always posedge clk or posedge reset begi
  • 如何在verilog中逐行读取文本文件?

    我有一个 SREC 文件 它是一个简单的文本文件 我想在 verilog 中逐行读取它 我怎样才能做到这一点 以下读取文件 每个时钟周期 1 行 预期的数据格式是每行一个十进制数 integer data file file handler
  • 如何在RTL中使用时钟门控?

    我正在对一些时钟进行门控latch以及我设计中的逻辑 我在综合和布局布线方面没有太多经验 在 RTL 中实现时钟门控的正确方法是什么 示例1 always comb begin gated clk clk latch update en e
  • 修改后的 baugh-wooley 算法乘法 verilog 代码不能正确乘法

    以下 verilog 源代码和 或测试平台可以很好地工作商业模拟器 iverilog https www edaplayground com x 3TuQ也形式化验证工具 yosys smtbmc https gist github com
  • 在逻辑中使用单端端口期待差异对?

    我使用的逻辑被设置为需要一个差分对时钟端口 然而 对于一个特定的应用程序 我只能输入一个单端时钟 由于硬件限制 修改逻辑以接受单端时钟不是一种选择 因为涉及许多文件和代码行 有没有办法可以输入单端端口并以某种方式将其馈送到模块的差异对端口
  • verilog 中的“<<”运算符

    我有一个verilog代码 其中有一行如下 parameter ADDR WIDTH 8 parameter RAM DEPTH 1 lt lt ADDR WIDTH 这里将存储什么RAM DEPTH以及什么是 lt lt 操作员在这里做
  • verilog $readmemh 对于 50x50 像素 RGB 图像花费太多时间

    我正在尝试编译用于 FPGA 编程的 verilog 代码 我将在其中实现 VGA 应用程序 我使用 QuartusII 和 Altera 我正在尝试正确使用 readmemh 来逐像素获取图片 现在 我已经使用 matlab 将图片转换为
  • 我们可以在 C 或 SystemVerilog 中使用 ifdef MACROS 中的条件吗?

    我想要那样的东西 ifdef N O gt N I define GREATER 1 else define LESSER 1 endif 但做不到 有什么解决方案或阅读吗 我很努力地想要做到这一点 但是却做不到 Verilog 不提供这样
  • 对象 <名称> 未声明

    这是我的代码 据我所知 LEDs被定义为 module sevenseg LEDs in output reg 6 0 LEDs input 3 0 in always in begin case in 0 LEDs 7 b1000000
  • 开始后跟冒号和变量是什么意思?

    什么是data mux意思是这里 它只是块的名称吗 if PORT CONFIG 32 P0 1 b1 begin data mux end 这些是块名称 它们特别适用于generate块 例如 您可以定义一个generate块如 genv
  • 在 Verilog 中判断总线是否包含单个 x 的最佳方法是什么?

    我有一个监控总线的测试台 总线内的一些信号 位 可以是 1 bx 由于多种原因 我需要知道总线内是否有任何信号是 1 bx 如果总线包含任何 x 测试 不用于综合 仅用于模拟目的 的最佳方法是什么 我曾希望我可以使用减少或然后使用 但这似乎
  • 如何在Verilog中将二维数组中的所有位设置为0?

    我构建了一个 8 2bits 数组来表示 Verilog 中的一块内存 reg 1 0 m 0 7 该存储器有一个复位信号 如果复位为1 则该存储器中的所有位都应重置为0 但是我不知道如何以简洁的方式设置m的所有位 因为如果有数百个内存中有
  • Verilog 中的 If 语句和分配连线

    我试图弄清楚基于组合逻辑分配电线的基础知识 I have wire val wire x wire a wire b always begin if val 00 I want to assign x a if val 01 I want
  • 如何修复实例上的错误:未定义的变量 B?

    我想编译此 Verilog 代码 但在实例中出现错误B模块中的MultiP module error 1 Undefined variable B error 2 near Adder1 syntax error unexpected ID

随机推荐

  • 51单片机串口奇偶校验

    有的单片机串口奇偶校验都是硬件自动完成的 xff0c 但是就我目前用到的很多51核的单片机 xff0c 需要软件做一些简单的处理来完成奇偶校验 可以自己写一个简单的小程序来实现 xff1a 一位一位的判断1的个数 xff0c 这个当然好实现
  • C语言printf()输出格式大全

    这里写自定义目录标题 1 xff0e 转换说明符 a A 浮点数 十六进制数字和p P 记数法 C99 c 字符 d 有符号十进制整数 f 浮点数 包括float和doulbe e E 浮点数指数输出 e E 记数法 g G 浮点数不显无意
  • 2019年 电赛C题 全国大学生电子设计竞赛试题解析与总结

    2019年全国大学生电子设计竞赛试题 电赛C题 分析与总结 线路负载及故障检测装置 本科组 一 题目任务 设计并制作线路负载及故障检测装置 xff0c 示意图如图1所示 检测装置只通过两个连接端子与两根导线连接 导线上A B两点距离各自连接
  • 用moment获取一年内指定周的起始时间和结束时间、用户所选时间和前端传参时间不一致问题

    问题1 xff1a 原代码 xff1a 所选周 selectedWeek handler let selectedWeek 61 parseInt this selectedWeek substring 1 计算所选周的周开始时间和周结束时
  • HTML知识(一)

    1 HTML元素 HTML元素指的是从开始标签 start tag 到结束标签 xff08 end tag xff09 的所有代码 元素内容是开始标签与结束标签之间的内容 某些HTML元素具有空内容 xff0c 空元素在开始标签中进行关闭
  • CSS隐藏元素、BFC、元素居中、布局

    1 css中有哪些方式可以隐藏页面元素 xff1f 区别是什么 xff1f 1 1 display none 元素在页面上将彻底消失 xff0c 元素本身占有的空间会被其他元素占有 xff0c 导致浏览器的重排和重绘 特点 xff1a 元素
  • 响应式设计和CSS提高性能的方法

    一 响应式设计 1 是什么 xff1f 是一种网络页面设计布局 xff0c 页面的设计与开发应当根据用户行为以及设备环境 xff08 系统平台 屏幕尺寸 屏幕定向等 xff09 进行相应的响应和调整 2 常见特点 xff08 1 xff09
  • js事件循环机制

    一 同步任务与异步任务 JavaScript是一门单线程 语言 xff0c 但是单线程并不意味着阻塞 实现单线程非阻塞的方式就是事件循环机制 在JavaScript中 xff0c 所有的事件都可以分为同步任务和异步任务 同步任务 xff1a
  • 简易MIMO-OFDM系统的设计

    0 完整源码获得方式 订阅MATLAB FPGA教程 xff0c 免得获得教程案例以及任意2份完整源码 MIMO OFDM系统的接收信号是多个发射天线发送信号的衰落与加性噪声的线性叠加 xff0c 若采用通常SISO OFDM系统或MIMO
  • 栈的定义和操作

    一 栈的定义 栈是一种操作受限制的线性表 xff0c 将允许进行插入 删除的一端称为栈顶 xff0c 另一端称为栈底 二 栈的分类 栈主要分为静态栈和动态栈 xff0c 静态栈类似于数组 xff0c 而动态栈类似于链表 xff0c 但只能对
  • 用C语言和前序遍历创建一棵二叉树

    一 二叉树的介绍 二叉树的特点是二叉树的每个结点的度都不大于2 xff0c 可以视为每个结点都有左孩子和右孩子 故二叉树结点的数据结构为 typedef int BDataType typedef struct BTNode BDataTy
  • 超市购物程序设计

    一 任务介绍 1 任务描述 去超市购物说人们日常生活的重要事情之一 在超市中有很多日常生活的用法 xff0c 如水果 蔬菜 洗衣机 电冰箱等 人们只能买到超市中的已有商品 xff0c 如果所需要的商品在超市中没有或已经卖完了 xff0c 那
  • 如何在IDEA中配置XML、添加XML文件样板以及设置项目编码方式

    一 如何在IDEA中配置XML 1 首先保证本地电脑上有apache maven包 xff0c 打开IDEA 2 点击File下拉菜单中的Settings xff0c 弹出Settings菜单框 3 在弹出的菜单框中选择Build Exec
  • Java之String类与StringBuffer类

    一 String类 1 实例化方式 1 xff09 直接赋值法 String str 61 34 abc 34 String类的设计采用了共享设计模式 在JVM底层实际上会自动维护一个对象池 xff08 字符串对象池 xff09 xff0c
  • 人脸识别项目的测试用例

  • 球机和枪机的区别

    球机 和 枪机 的区别最明显的应该就是外形的区别 xff0c 那么 xff0c 球机和枪机还有什么深层次的区别呢 xff1f 枪机即 枪式摄像机 xff0c 其监控位置固定 xff0c 只能正对某监控位置 xff0c 所以监控方位有限 枪机
  • STM32的USART注意

    在USART的发送端有2个寄存器 xff0c 一个是程序可以看到的USART DR寄存器 另一个是程序看不到的移位寄存器 对应USART数据发送有两个标志 xff0c 一个是TXE 61 发送数据寄存器空 xff0c 另一个是TC 61 发
  • 数据传输中断和查询的区别

    中断方式就是在接受数据时 xff0c 微控制器转入中断服务程序对接受到的数据进行处理 xff0c 而查询方式就是通过查询状态寄存器中接受状态位对接收到的数据进行处理 xff0c 两者在工作上的区别主要在于 xff0c 中断方式微控制器可以执
  • C语言 HTTP发送post和get请求

    安装curl环境 xff1a apt install curl apt get install libcurl4 openssl dev 使用C语言来做HTTP协议 xff0c 然后发送post和get请求 xff0c 这里为post请求的
  • Verilog中输入数据范围的判断

    0 完整源码获得方式 订阅MATLAB FPGA教程 xff0c 免得获得教程案例以及任意2份完整源码 在系统设计的过程中 xff0c 经常需要根据输入数据的值 xff0c 对相关信号的值进行改变 如果输入数据的边界值数量比较少 xff0c