Verilog初级教程(4)Verilog中的标量与向量

举报
李锐博恩 发表于 2021/07/15 02:31:09 2021/07/15
【摘要】 博文目录 写在前面正文标量与变量位选择常见错误 参考资料交个朋友 写在前面 上一篇博文就说到了Verilog的数据类型,其中就常用的就是reg类型以及wire类型,这两种类型可以定义一位的变量也可以定义多位的变量,其中一位称之为标量,多位称之为向量,类似于数组。本篇博客主要讲述对多位变量的一些操作。 例如: Verilog 2001修订版新增的b...


写在前面

上一篇博文就说到了Verilog的数据类型,其中就常用的就是reg类型以及wire类型,这两种类型可以定义一位的变量也可以定义多位的变量,其中一位称之为标量,多位称之为向量,类似于数组。本篇博客主要讲述对多位变量的一些操作。
例如:
Verilog 2001修订版新增的bit位选择语法:

[<start_bit> +: <width>] // part-select increments from start-bit
[<start_bit> -: <width>] // part-select decrements from start-bit

  
 
  • 1
  • 2
  • 个人微信公众号: FPGA LAB

正文

标量与变量

Verilog需要表示单个位以及多个位的组。例如,一个单bit时序元件是一个触发器。然而一个16位的时序元件是一个可以容纳16位的寄存器。为此,Verilog有标量和矢量网以及变量。
一个没有指定范围的net或reg声明被认为是1位宽,是一个标量。如果指定了范围,那么net或reg就变成了一个多比特的实体,称为向量。

标量与向量

  wire o_nor; // single bit scalar net
  wire [7:0]  o_flop; // 8-bit vector net
  reg parity; // single bit scalar variable
  reg  [31:0] addr; // 32 bit vector variable to store address

  
 
  • 1
  • 2
  • 3
  • 4

范围提供了在一个向量中寻址单个位的能力。向量中最高位应该被指定为范围内的左手值,而向量中最低位应该被指定在右手边。

  wire  [msb:lsb]   name;
  integer my_msb; wire [15:0] priority; // msb = 15, lsb = 0
  wire [my_msb: 2]   prior; // illegal

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

在上面的例子中,将创建一个16位宽的网,称为优先级。注意,msb和Isb应该是一个常量表达式,不能用变量代替。
注:msb以及lsb可以是任何整数值–正负或零,而且Isb的值可以大于、等于或小于msb的值。但为了保持风格统一,也就是左边的值要比右边的值大,所以不建议lsb大于或等于msb.

位选择

向量中的任意位都可以被单独选择,并且可以对其单独赋值。
如:

  reg [7:0] addr; // 8-bit reg variable [7, 6, 5, 4, 3, 2, 1, 0] addr [0] = 1; // assign 1 to bit 0 of addr
  addr [3] = 0; // assign 0 to bit 3 of addr


  
 
  • 1
  • 2
  • 3
  • 4
  • 5

操作后的示意图:

单bit选择

但不能超出向量索引范围:

  addr [8] = 1; // illegal : bit8  does not exist in addr

  
 
  • 1

能单个位选择,当然也能范围选择,也即连续选择相邻的多位进行赋值等操作。
例如:

reg [31:0] addr; addr [23:16] = 8'h23; // bits 23 to 16 will be replaced by the new value 'h23 -> constant part-select
 

  
 
  • 1
  • 2
  • 3
  • 4

多位选择

上面多位选择,采用的是常量作为索引值。
还可以使用如下的方式:

[<start_bit> +: <width>] // part-select increments from start-bit
[<start_bit> -: <width>] // part-select decrements from start-bit

  
 
  • 1
  • 2

拥有一个可变的部分选择,可以在循环中有效地使用它来选择矢量的部分。虽然起始位可以改变,但宽度必须是恒定的。

例如:

module des;
  reg [31:0]  data;
  int i; initial begin data = 32'hFACE_CAFE; for (i = 0; i < 4; i++) begin $display ("data[8*%0d +: 8] = 0x%0h", i, data[8*i +: 8]); end $display ("data[7:0]   = 0x%0h", data[7:0]); $display ("data[15:8]  = 0x%0h", data[15:8]); $display ("data[23:16] = 0x%0h", data[23:16]); $display ("data[31:24] = 0x%0h", data[31:24]);
  end
 
endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

仿真结果:

ncsim> run
data[8*0 +: 8] = 0xfe // ~ data [8*0+8 : 8*0]
data[8*1 +: 8] = 0xca // ~ data [8*1+8 : 8*1]
data[8*2 +: 8] = 0xce // ~ data [8*2+8 : 8*2]
data[8*3 +: 8] = 0xfa // ~ data [8*3+8 : 8*3]

data[7:0]   = 0xfe
data[15:8]  = 0xca
data[23:16] = 0xce
data[31:24] = 0xfa
ncsim: *W,RNQUIE: Simulation is complete.

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

常见错误

举例:

module tb; reg [15:0] data; initial begin $display ("data[0:9] = 0x%0h", data[0:9]);   // Error : Reversed part-select index expression ordering end
endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这个常见的错误,就是混用msb以及lsb的风格导致的,再次强调,统一风格,msb在做,lsb在右!


参考资料


交个朋友

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/106973708

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。