0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Verilog设计中如何匹配变量的位宽

C29F_xilinx_inc 来源:赛灵思 作者:赛灵思 2022-02-16 16:21 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1、位宽太小

FPGA设计中,我们经常需要用寄存器来寄存某些“数量类”的变量,比如FIFO的深度啦、或者计数器的最大值啦;又或者输入输出信号也需要将位宽用parameter参数化以便更好的调用等。

举个简单的小例子:系统频率100M(周期10ns),假设需要要求设计一个计时器计时100ns,那么需要计数次数为:100ns/10ns - 1 = 9,9这个数需要用多大位宽的寄存器表示呢?很简单,以2为底取对数就行,答案是最少4位宽。为了方便地复用这个模块,我们把计时时间参数化并放到模块外,如下:

module counter #(
parameter TIME = 'd10 //计时时间,单位10ns
)(
input clk_100M ,
input rst
);
reg [3:0] cnt; //计数器

//计时器
always@(posedge clk_100M)begin
if(rst)
cnt else if(cnt == TIME - 1)
cnt else
cnt end

endmodule

假设我们下次设计需要一个计时器的话,直接调用上面的counter模块并把TIME这个参数改成自己需要的参数就可以,这样做理论上是可以的,只是会有一个致命的隐患。不妨再假设:我现在调用了counter模块,并将TIME设置为20,以实现计时200ns的功能。当TIME = 20这个参数传递到被例化模块后,可以发现由于cnt寄存器的位宽仅为4位,其能表示的最大值为4'b1111(即十进制下的数字15),每次其到达15后就溢出为0重新开始了,也就是说这个200ns的计时器实际上根本就计数不到200ns。

这个隐患发生的原因就是在设计寄存器cnt时的位宽只有4位,无法满足“大量时间的计时任务”。

2、自己写一个Function

现在来想一下如何解决上述的位宽不匹配的问题。将寄存器的位宽设计为一个较大的数值(如固定为32bit)不失为一个不错的方法,但是如果将这条规则适用到每一个寄存器,则势必造成大量的资源浪费(你资源多你随便玩)。而且该方法指标不治本,我们需要做的是,这个寄存器应该有多大就设计多大的位宽(有多大的脚就穿多大的鞋,鞋子太大一定能穿,但你脚不一定舒服)。

前面说过寄存器的位宽的计算方法:以2为底取对数。所以我们只需要设计一个Function(可综合),来实现此项功能即可。刚好在Xilinx的许多源码都出现了这个简单的Function,我们直接拿过来用就是的:

// function 实现
function integer clogb2 (input integer bit_depth);
begin
for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
bit_depth = bit_depth >> 1;
end
endfunction

// 使用案例
localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1);
reg [C_TRANSACTIONS_NUM : 0] write_index;
reg [C_TRANSACTIONS_NUM : 0] read_index;

上面的代码就是定义了一个求位宽的function,用其求得某类寄存器的位宽,然后再对寄存器赋值时就直接使用求得的位宽来赋值,这样复用起来就比较方便了。

我们将这个代码放到上面的计数器模块中后,不管需要计数多大时间,都能计算出相匹配的寄存器位宽了。

3、无法在输入输出端口使用

自己写Function实现对2取对数的功能也有一定的局限性:无法对输入输出端口信号使用该Function。Function是定义在模块内部,所以若输入输出端口也需要根据输入的parameter参数来以2为底取对数的话此种方法就无能为力了。比如:设计一个同步FIFO,输出信号fifo_cnt(计数器)是对写入FIFO的数据进行计数的寄存器,其最大值即为FIFO的深度DATA_DEPTH ,所以fifo_cnt的位宽就需要在定义模块输入输出端口时确定,显然这无法使用自己构造的 cblogb2 Function。那该当如何?
//计数器法实现同步FIFO

module sync_fifo_cnt
#(
parameter DATA_WIDTH = 'd8 , //FIFO位宽
parameter DATA_DEPTH = 'd16 //FIFO深度
)
(
input clk , //系统时钟
input rst_n , //低电平有效的复位信号
input [DATA_WIDTH-1:0] data_in , //写入的数据
input rd_en , //读使能信号,高电平有效
input wr_en , //写使能信号,高电平有效

output reg [DATA_WIDTH-1:0] data_out, //输出的数据
output empty , //空标志,高电平表示当前FIFO已被写满
output full , //满标志,高电平表示当前FIFO已被读空
output reg [$clog2(DATA_DEPTH) : 0] fifo_cnt //$clog2是以2为底取对数
);

//省略部分代码

endmodule

4、$clog2系统函数

其实办法也有,在上面的代码中也展示出来了,就是使用 $clog2 这个Verilog的系统函数。$clog2是Verilog--2005标准新增的一个系统函数,功能就是对输入整数实现以2为底取对数,其结果向上取整(如5.5取6)。有一点需要说明的是,目前Vivado2017以上的版本都是支持这个系统函数的(Quartus II不清楚 )。但是百度搜索这条结果的时候有两条结论是错误的:

1、Vivado不支持$clog2系统函数

2、$clog2系统函数在Vivado实现的是以e为底取对数,而不是2

接下来写个简单的模块验证下Vivado对$clog2系统函数的支持如何

`timescale 1ns / 1ps

module clog2_test#(
parameter integer num = 325
)
(
input clk,
input rst,
output reg [$clog2(num) - 1:0] result
);

always @(posedge clk)begin
if(rst)
result else
result end

endmodule

我们直接看reg result的位宽综合出来到底是多少。如果以e为底向上取整,则位宽应是6;如果以2为底向上取整,则位宽应是9。Vivado综合的原理图局部如下:

Verilog设计中如何匹配变量的位宽

可以看到最后编译出的结果是9位的,也就说明Vivado是支持这个系统函数的(版本:2019.2)。

其他变量的位宽设计同理。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5588

    浏览量

    129035
  • 计数器
    +关注

    关注

    32

    文章

    2306

    浏览量

    97554
  • 参数
    +关注

    关注

    11

    文章

    1868

    浏览量

    33752
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    操作的常见错误与应对策略

    溢出或数据丢失。在进行位移操作时,必须确保位移量在数据类型的有效范围内。例如,对于一个 8 的无符号字符型变量unsigned char,其为 8
    发表于 11-24 07:50

    NucleiStudio如何生成.verilog文件和.dasm文件,以及对.dasm文件自定义指令反汇编结果分析

    文件,以及对.dasm文件自定义指令反汇编结果分析。 一、如何生成.verilog和.dasm文件文件 项目右键选择Properties 选择C/C++ Build下面的Setting 更改
    发表于 10-24 06:33

    PLCStatic和Temp变量的区别

    大家好,收到粉丝投稿,让博主讲下Static变量和Temp变量的区别,新入行的兄弟可能会对这两个概念不太能理解。
    的头像 发表于 09-24 14:51 905次阅读
    PLC<b class='flag-5'>中</b>Static和Temp<b class='flag-5'>变量</b>的区别

    为什么铜块尺寸和板槽公差匹配很关键

    为什么公差设计如此重要? 埋嵌铜块看似只是把铜块“放进”PCB槽里,但实际却涉及机械加工、树脂填充、压合、焊接等多个环节。任何尺寸不匹配都会带来严重后果,例如:铜块松动、界面空隙、热阻增大、甚至
    的头像 发表于 09-15 15:36 4345次阅读

    Ansible Playbook变量使用技巧

    在inventory定义的连接变量(比如ansible_ssh_user);优先级第二。
    的头像 发表于 04-15 10:26 671次阅读

    寻找verilog高手,有报酬

    我采集了一块电路板正常工作时的数据,基于这些数据我想用EPM7128slc84-15(sys_clk:50Mhz)测试电路板,寻求一verilog高手,有偿
    发表于 03-08 16:31

    Verilogsigned和$signed()的用法

    吗?其实不是的,因为有符号数和无符号数据的加法强结果和乘法器结构是一样的,signed的真正作用是决定如何对操作数扩的问题。 2、verilog的加法和乘法操作前,会先对操作数据扩
    的头像 发表于 02-17 17:47 1184次阅读
    <b class='flag-5'>Verilog</b><b class='flag-5'>中</b>signed和$signed()的用法

    浅谈Verilog和VHDL的区别

    Verilog和VHDL是两种广泛使用的硬件描述语言(HDL),它们用于描述和模拟数字电路系统的行为和结构。这两种语言的主要作用是帮助工程师设计、仿真和验证集成电路(IC)和系统级芯片(SoC)的硬件模块。
    的头像 发表于 02-17 14:20 2622次阅读
    浅谈<b class='flag-5'>Verilog</b>和VHDL的区别

    EE-88:使用21xx编译器在C初始化变量

    电子发烧友网站提供《EE-88:使用21xx编译器在C初始化变量.pdf》资料免费下载
    发表于 01-13 15:54 0次下载
    EE-88:使用21xx编译器在C<b class='flag-5'>中</b>初始化<b class='flag-5'>变量</b>

    ADC芯片的采样率为100MSPS,16,那么吞吐量是多少?

    例如ADC芯片的采样率为100MSPS,16,那么吞吐量是多少? 用差分LVDS和FPGA相连,FPGA的时钟速率多少能够满足要求/?
    发表于 12-18 08:49

    Verilog例化说明

    的例化(或说是调用)。在一个FPGA项目工程,其输入、输出端口命名通常在设计前期就已确定下来,但会存在一些中间变量,一个工程可能会让不同的工程师在不同的时间段内共同完成,不同的人对于这些变量的命名会有所不同,故例化很有必要。
    的头像 发表于 12-17 11:29 3118次阅读
    <b class='flag-5'>Verilog</b>例化说明

    Verilog 电路仿真常见问题 Verilog 在芯片设计的应用

    。然而,在实际应用,设计师可能会遇到各种问题,这些问题可能会影响仿真的准确性和设计的可靠性。 Verilog电路仿真常见问题 仿真环境的搭建问题 仿真环境的搭建是进行Verilog仿真的第一步。设计师需要选择合适的仿真工具,并
    的头像 发表于 12-17 09:53 1600次阅读

    Verilog 与 ASIC 设计的关系 Verilog 代码优化技巧

    Verilog与ASIC设计的关系 Verilog作为一种硬件描述语言(HDL),在ASIC设计扮演着至关重要的角色。ASIC(Application Specific Integrated
    的头像 发表于 12-17 09:52 1435次阅读

    Verilog 测试平台设计方法 Verilog FPGA开发指南

    Verilog测试平台设计方法是Verilog FPGA开发的重要环节,它用于验证Verilog设计的正确性和性能。以下是一个详细的Verilog
    的头像 发表于 12-17 09:50 1558次阅读

    Verilog与VHDL的比较 Verilog HDL编程技巧

    Verilog 与 VHDL 比较 1. 语法和风格 VerilogVerilog 的语法更接近于 C 语言,对于有 C 语言背景的工程师来说,学习曲线较平缓。它支持结构化编程,代码更直观,易于
    的头像 发表于 12-17 09:44 2679次阅读