• 深入浅出学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 是半覆盖的蓝色横框。

    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数据),它左边连接着与门的输出端、右边连接着触发器的输入端。它自身不能存储任何数据,它的值取决于它左侧所连接的与门的输出端,然后它又将这个值赋给它右侧所连接的触发器。

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

    wire        flag;                    //声明一个wire

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

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

          

    2.1.2、其他net类型

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

    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

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

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

    位操作(bit-selsct)

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

    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。例如:

    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:7]   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(仅可读)。

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


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

  • 相关阅读:
    《安富莱嵌入式周报》第283期:全开源逆向“爆破”硬件工具,Linux内核6.1将正式引入RUST语言,I3C培训教程,80款市场成熟的电感式位置传感器设计
    前端相关免查整合-vue、es、工具类等
    Matlab杂项记录
    丁鹿学堂:重学js的设计模式,彻底掌握(一)
    Keras计算机视觉(二)
    什么是Ribbon,怎么实现负载均衡?
    本地Git项目同时推送至GitHub和Gitee
    面试题-React(十九):React Hook
    R语言实践——rWCVP:世界维管植物名录的R包
    Nginx重写功能
  • 原文地址:https://blog.csdn.net/wuzhikaidetb/article/details/132820014