深入浅出学Verilog--数据类型

1、数值类型

        在Verilog可以用4种数值来描述其构建的电路的电平逻辑,除了event类型real类型外,几乎所有的数据类型都可以用这4种数值来表示

  • 0:代表逻辑0,或者条件“
  • 1:代表逻辑1,或者条件“
  • x或X:代表未知值。意味着不确定,可能是逻辑0,也可能是逻辑1。
  • z或Z:代表高阻态,一般用于3态缓冲电路(tri-state buffer)。高阻态常见于该端口没有驱动的情况,其电平值与其所接的上拉或下拉电路有关。若连接到上拉电路,则电平值为逻辑1;反之则为逻辑0。

        不同的仿真软件对这些数值的显示可能各不相同,在xilinx的vivado软件这4种数值的显示是这样的:1是全覆盖的绿色横框;0 是绿色横条;x 是半覆盖的红色横框;z 是半覆盖的蓝色横框。

深入浅出学Verilog--数据类型_第1张图片

2、数据类型

        Verilog中主要有两大类数据类型:

  • Net(网类):Net用来表示电路中的物理链接,例如不同门级电路间的连接就需要使用nets,类似实际电路中的电线。
  • Variable(变量类):变量用来存储电路中的数据,它会一直保存数据直到下一次改写。

2.1、Net类型

        Net用来构建电路中不同元素的物理连接,自身不存储任何数据,它的值只取决于所连接的驱动电路的值(默认值为z,即高阻态)。Net类数据下有很多子类型的数据,比如wire、tri、wand、wor、tri1等等,其中wire类型是最常用的,其他类型数据在实践中几乎不会被用到。

2.1.1、wire类型

        下图中的net_11就是一个net型数据(确切的说应该是wire数据),它左边连接着与门的输出端、右边连接着触发器的输入端。它自身不能存储任何数据,它的值取决于它左侧所连接的与门的输出端,然后它又将这个值赋给它右侧所连接的触发器。

深入浅出学Verilog--数据类型_第2张图片

        下面是几种wire类型的声明方式:

wire        flag;                    //声明一个wire

wire        flag1,flag2;         //声明多个wire

wier        flag = 1'b0;         //声明wire的同时并赋值

      

2.1.2、其他net类型

        除了wire类型外,还有一些其他的net类型。由于verilog语言的灵活性,这些net类型几乎都可以使用wire类型 + 门级电路来构建,所以在实践中,这些类型一般都不会被使用。这里稍微了解一下就可以:

深入浅出学Verilog--数据类型_第3张图片

2.2、Variable类型 

        Variable(变量)类型用来存储电路中的数据,它会一直保存数据直到下一次改写。Variable类型有reg、time、integer、real和realtime5个子类型,其中最为常用的是reg(寄存器)类型。

2.2.1、reg变量 

        reg和wire是verilog中最为常用的两种数据类型,它俩可以分别用来构建组合逻辑电路和时序逻辑电路。

        reg以时钟信号为基准,用来在电路中存储数据,触发器(flip-flop)就是一种典型的存储数据的电路。下面是几种reg变量的声明方式:

reg       flag;                    //声明一个reg

reg       flag1,flag2;         //声明多个reg

reg       flag = 1'b0;         //声明reg的同时并赋值

     

2.2.1、其他变量

integer整数

        整数变量用关键字 integer 来声明,声明时不用指明位宽--位宽和编译器有关(一般为32 bit)。在实践中,integer变量一般用作辅助使用(integer的引入并不会生成硬件电路),例如指定某个reg/wire的位宽(方便更改),或在循环语句中充当循环参数等。例如:

integer i;
always@(*) begin
    for (i=0;i<=5;i=i+1) begin
        ······
    end
end

real(实数)

        实数用关键字 real 来声明,可用十进制或科学计数法来表示。real 声明不能带有范围,默认值为 0。real 可以用来存储浮点数。例如:

real        data1 =1e3;
real        data2 = 3.14;

time、realtime(时间)

        time/realtime变量可以用保存仿真时间,位宽多为64bit,调用系统函数$time/$realtime可以获取当前仿真时间,time和realtime的区别在于,一个是存储整数变量(time),另一个存储实数变量(realtime)。例如:

time         t1  = 25;

realtime   rt1 = 2.5;

3、向量

        在声明wire或reg变量时,如果不指定范围,那么此时的wire/reg就是一个标量(scalar);反之,如果指定了范围,那么此时的wire/reg就是一个向量(Vector)。

        wire类型的向量与标量形式:

wire  [3:0]  n0;        //4位宽的向量wire

wire           n1;        //单位宽的标量wire

        reg类型的向量与标量形式:

reg  [3:0]  d0;        //4位宽的向量reg

reg           d1;        //单位宽的标量reg

深入浅出学Verilog--数据类型_第4张图片

        向量最左端的值被称为最高有效位MSB(Most Significant Bit),最右端的值被称为最低有效位 LSB(Least Significant Bit)。MSB和LSB的值可以是任意整数(正整数、负整数和零),而且MSB即可以大于LSB,也可以小于LSB,但两者不能相等(相等就是标量了)

        对于向量,可以根据其地址,来对某一位或某几位进行操作。

位操作(bit-selsct)

        可以通过地址索引的方式,对向量中的某一位进行选取和操作,这就是位操作bit-selsct。例如:

深入浅出学Verilog--数据类型_第5张图片

reg  [7:0] addr;         //声明一个8位宽的reg型变量(向量)addr

addr [0] = 1'b1;        //直接对addr的第0位进行操作,将其赋值为1

addr [3] = 1'b0;        //直接对addr的第3位进行操作,将其赋值为0

部分操作(part-selsct) 

        既然可以通过地址作为索引,来对向量的某一位进行操作,那么必然也可以通过多位地址来对向量的多位进行操作,这就是部分操作part-selsct。例如:

深入浅出学Verilog--数据类型_第6张图片

reg  [31:0] addr;                //声明一个32位宽的reg型变量(向量)addr

addr[23:16] = 8'h23;         //直接对addr的第16~23位进行操作,将其赋值为8'h23,即8'b0010_0011

        Verillog 还支持指定 bit 位后固定位宽的向量域选择访问。开始位可以是变化的,但是位宽必须固定为常数,这个语法在循环等语句中非常实用。

  • [start_bit+:width]    //从start_bit开始向上递增width位
  • [start_bit-:width]    //从start_bit开始向下递减width位

 reg  [31-:8]  addr1;        //等价于 reg  [31:24] addr1。实践中起始位31可以变化,位宽固定为8,等于选取该变量的某个8位

 reg  [0+:8]   addr2;        //等价于 reg  [0:8]   addr2。实践中起始位0可以变化,位宽固定为8,等于选取该变量的某个8位

4、数组和存储器

4.1、数组

        在 Verilog 中可以声明 reg, wire, integer, time, real类型的数组(Array)。数组维数没有限制,其中的每个元素可以是标量或者向量。

reg         y1[3:0];                //1维数组,共有4个元素,每个元素位宽为1(即标量)

reg [3:0] y2[3:0];                //1维数组,共有4个元素,每个元素位宽为4

reg [3:0] y3[3:0][15:0];       //2维数组,共有4*16 = 64个元素,每个元素位宽为4

         数组与向量一样,也可以通过地址索引的方式进行访问。

y1 = 0;                        //非法赋值--不能同时对4个元素赋值

y1[0] = 1'b0;               //对y1的第0个元素赋值为1'b0

y2[2] = 4'b1111;          //对y2的第2个元素赋值为4'b1010

y3[2] [1] = 4'b1100;    //对y3的第2行、第1个元素赋值为4'b1100

        需要注意的是,向量是一个单独的元件,其位宽为 n;而数组则由多个元件组成,其每个元件的位宽为 n 或 1。尽管他们的访问方式类似,但它们在定义上就有所区别。

reg [n-1:0]   rega;           // rega是一个reg向量,它只有一个元件,位宽为n

reg  mema [n-1:0];         // mema 是一个数组,它有n个元件,每个元件的位宽为1

4.2、存储器

        存储器(Memory)就是一种一维寄存器数组,它可以用来构建 RAM(可读写) 或 ROM(仅可读)。

深入浅出学Verilog--数据类型_第7张图片

reg [7:0] mem [255:0];        //可以理解为构建了一个256个格子的存储器,每个格子都可以存储8个bit的数据


  • 您有任何问题,都可以在评论区和我交流!
  • 本文由 孤独的单刀 原创,首发于CSDN平台,博客主页:wuzhikai.blog.csdn.net
  • 您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞、评论和收藏⭐!

你可能感兴趣的:(Verilog语法,fpga开发,Verilog,Xilinx,IC,FPGA,altera,数据类型)