System verilog基础语法——(二)数据类型

目录

一、数据类型

二、 数组

三、数组操作与方法

 四、typedef、struct创建新类型

五、类型转换

 六、枚举类型与转换

七、 常量、字符串、表达式位宽


一、数据类型

1. 二值逻辑

bit、byte、int、shortint、longint(除bit外均有无符号类型)。

特点:性能更好,节省内存,用以模拟计算机验证的环境,X,Z默认为0。

2. 四值逻辑

logic、integer、reg、wire(除integer外均为无符号类型),模拟外部世界。

其中logic为拓展传统reg类型,也可像wire类型一样进行连线,使得在验证过程中不需过多考虑对应逻辑被综合成寄存器还是线网,使用时简单理解成赋值即可。同时需注意logic不能有多个结构性的驱动,多驱动(mutil-drive)时必须使用wire类型。

*使用有符号数据类型时需注意其取值范围,如byte最大值是127,而非255。

二、 数组

1. 基本数组特性参考C。

2. 动态数组:SV提供动态数组,以便仿真时再分配空间,达到节省存储的目的。使用时在动态数组声明时使用空下标[],运行时使用new[]分配空间。

int array1[]                //动态数组
    initial begin
        array = new[5];     //new[]分配空间
        foreach(new[i])
            new[i] = i;
    end

 3. 队列:引入队列可在队列具体位置增加(.insert)、删除元素(.delete),比动态数组性能损失小(动态数组需要分配新的数组并复制元素的值)。队列声明使用[$],表示元素编号从0到$。

int q[$] = {1,2,3};
initial begin
    q.insert(1,5);    //第一个元素后插入5
    q.delete(1);      //删除第一个元素之后的元素
    q.push_front(0);  //在队列首位插入0
    q.push_back(4);   //在队列尾插入4
    end

4. 关联数组

三、数组操作与方法

1. 数组循环(遍历)for & foreach

initial begin
    bit [31:0] array[1:0];
    for(i=0;i<=$size(array);i++)
        array[i] = i;
    foreach (array[i])
        array[i] = array[i] * 2;
    end

补充:foreach循环只会遍历原始声明中的数组范围,例如对于数组array[5:3],foreach(array[5:1])等同于for(int i=5;i>=3,i--)。

2. 数组复制和比较

复制:直接使用“=”进行赋值

比较:determine statements? if true : if false

$display("array1 %s array2", (array1 = array2) ? "==" : "!=");

3.  数组缩减:将一个数组缩减成一个值,常用 .sum, .product, .and, .or, .xor

bit on[10];
int all;
initial begin
foreach(on[i])
    on[i] = i;
all = on[i].sum;
end

4. 数组定位:在非合并数组中查找数据,使用数组定位方法返回一个队列。常用:.min, .max, .unique和.find。

int a[] = '{9,6,4,1,5}, tq[$];
tq = a.find with(item>5);    //{9,6},找出所有大于5的元素
tq = a.find_index with (item>5);    //{0.1}
tq = a.find_first_index with (item==1);    //{3}, a[3] = 1

示例需注意:find_index(返回值为索引的数组定位),返回的队列类型是int,非integer!

5. 数组排序:.reverse .sort .rsort .shuffle

其中reverse与shuffle不能带with条件语句。

 四、typedef、struct创建新类型

1. typedef创建新类型,适应不同位宽操作数的算术逻辑单元编译时可配置的要求。

//自定义数组
typedef int fixed_array5[5];
fixed_array5 f5;
initial begin
    foreach(f5[i])
    f5[i] = i;
end

2. struct结构体是将不同类型数据组合成数据结构的方法(C),在SV中其是一个数据集合,即可综合。

initial begin
    typedef struct{         //创建新类型
        int a;
        byte b;} my_struct_s;           
    my_struct_s st = '{     //结构体初始化
        32'haaad,
        8'hbb};
    $display("str=%x %x %x %x",st.a, st.b, st.c, st.d);
end

3. 联合:将不同类型变量存放在同一位置,与C相同

typedef union{int i;real f;} num_u;
num_u un;
un.f = 0.0;

五、类型转换

1. 静态转换:转换时指定目标类型,并需在要转换的表达式前加上单引号,操作时不对转换值进行检查。

2. 动态转换:函数$cast,允许对转换值进行检查。

3. 流操作符:<<与>>,放在表达式、结构或数组的右边,将其后的数据打包成一个比特流。<<将数据从右至左变成流,>>将数据从左至右打包成流。不能将比特流结果直接赋值给非合并数据,而应该在复制表达式的左边使用流操作符把比特流拆分到合并数组中。

initial begin
    int h;
    bit [7:0] b,g[4],j[4] = '{8'ha, 8'hb, 8'hc, 8'hd};
    bit [7:0] q,r,s,t;
    h = {>> {j} };                //0a0b0c0d 把数组打包成整形
    h = {<< {j} };                //b030d050 位倒序
    h = {<<byte {j} };            //0d0c0b0a 字节倒序
    h = {>>byte {j} };            //0d,0c,0b,0a 拆分成数组
    h = {<< {8'b0011_0101} };     //1010_1100 位倒序
    h = {<<4 {8'b0011_0101} };    //0101_0011 半字节倒序
    {>> {q,r,s,t} } = j;          //把j分散到四个字节变量里
    h = {>> {t,s,r,q} };          //把字节集中到h里
end

 六、枚举类型与转换

1.枚举类型:创建强大的变量类型,仅限于特定名称的集合,例如指令中的操作码或状态机中的状态名。使用枚举定义常量能自动为列表中的每个名称分配不同的数值。枚举类型子程序:

.first()/.last()

返回第一个枚举常量
.next()/.next(N)返回下一个/N个枚举常量
.prev()/.prev(N)返回前一个/N个枚举常量

2. 枚举类型转换:SV要求整型变量赋值给枚举变量时需显示类型转换 ,目的在于使开发者使用时能意识到可能存在的数值越界情况。

typedef enum {RED,BLUE,GREEN} COLOR_E;
COLOR_E color, c2;
int c;
initial begin
    color = BLUE;            //赋一个合法的值
    c = color;               //枚举类型转换成整数型 1
    c++;                     //整型递增 2
    if(!$cast(color,c))      //整型转换为枚举类型
        $display("cast failed for c= %0d", c);
    $display("color is %0d /%s",color,color.name);
    c++;                     //c = 3 对于枚举类型以越界
    c2 = COLOR_E'(c);        //不做类型检查
    $display("c2 is %0d/%s",c2,c2.name);
end

七、 常量、字符串、表达式位宽

1. 常量:SV支持const修饰符,允许变量在声明时对其进行初始化,但不能在过程代码中改变其值。

2. 字符串:SV中string类型可用来保存长度可变的字符串。单个字符串为byte类型,长度为N的字符串元素编号从0到N-1。与C不同的是结尾不带null符,所有“\0”的操作都会被忽略。其使用动态存储方式,存储空间可变。常用操作见下表:

.getc(N)返回第N位的字符
.tolower()/.upper()返回小写/大写字符串
.putc(N,"s")第N位用"s"代替
{s,"-"}{}将字符串s与“-”拼接
.substr(start,end)返回位置start到end的字符串
$psprintf()新建字符串

 3. 表达式的位宽:表达式位宽常常造成不可预知情况,避免由位宽溢出造成的情况常采取方法

使用临时变量
加入其他值强制获取最小精度
变量强制转换达到期望的精度
bit[7:0] b8;
bit one = 1'b1;
$displayb(one + one);            //1+1=0,两单比特相加,宽度溢出

b8 = one + one;                  //1+1=2 ,b8宽度为8 bit
$displayb(b8);

$displayb(one + one + 2'b0);     //1+1=2,增加亚元参数,强制SV转换2 bit精度

$displayb(2'(one) + one);        //1+1=2,操作数强制转换为2 bit值

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: FPGA是一种可编程逻辑器件,可以通过编程实现各种功能。而Verilog是一种硬件描述语言,用于描述FPGA中的电路。Verilog基础语法包括模块定义、端口定义、信号定义、赋值语句、条件语句、循环语句等。模块定义是Verilog中最基本的语法,用于定义一个电路模块。端口定义用于定义模块的输入输出端口。信号定义用于定义模块内部的信号。赋值语句用于给信号赋值。条件语句用于根据条件执行不同的代码。循环语句用于重复执行一段代码。掌握Verilog基础语法是学习FPGA编程的基础。 ### 回答2: FPGA是一种可编程逻辑器件,它可以通过硬件描述语言来编写自定义的逻辑电路来实现各种功能。其中,Verilog是一种常用的硬件描述语言,有助于实现FPGA的功能。 Verilog语言主要由模块、端口、信号、语句和运算符五个基本部分组成。模块是Verilog中的最基本的语法单元,类似于传统程序语言中的函数,模块之间可以通过实例化进行连接。端口则是与外部世界进行通信的接口,可以分为输入端口(input)和输出端口(output)两种类型。信号是Verilog中表示数字信号的基本单元,可以是位向量、整数或实数。语句则是Verilog中描述操作和行为的语言,常用的语句包括赋值语句、分支语句和循环语句。运算符则是Verilog中用于进行操作的符号,包括算数运算符、逻辑运算符和位运算符。 在Verilog语言中,还有一些常用的结构体和命令可以帮助我们更方便地实现FPGA的功能。其中,常用的结构体包括always语句、case语句和module归档,常用的命令包括initial语句、wire语句和reg语句。always语句可以在指定的触发条件下执行某一段代码,case语句可以根据不同的条件执行不同的代码段,module归档则可以将多个模块合并为一个模块。initial语句可用于在仿真开始前初始化某些信号,wire语句则用于声明并连接信号,reg语句则用于声明并存储信号。 总体而言,了解FPGA和Verilog基础语法可以帮助我们更好地理解FPGA技术的应用和实现。然而,理论知识只有结合实际操作和实验才能更好地掌握。所以,我们还需要结合实际项目来进行练习和实践,从而更好地掌握FPGA和Verilog基础语法。 ### 回答3: FPGA(可编程门阵列)是一种可编程逻辑器件,可以用来创建定制的数字电路。Verilog是一种硬件描述语言,用于描述数字电路的结构和行为。 Verilog基础语法有以下几个部分: 1.模块定义:Verilog代码以模块的形式进行组织,每个模块都有一个名称和端口列表。模块定义以module关键字开始,以endmodule关键字结束。 2.端口声明:模块的端口是输入和输出连接到其他模块或FPGA芯片的引脚。端口可以是输入(input)、输出(output)或双向(inout)。端口声明在模块定义中。 3.信号声明:信号是描述数字电路中状态的变量。可以是单个位(wire)或多位(reg),在模块中声明。 4.赋值语句:用来为信号赋值,包括非阻塞赋值(<=)、阻塞赋值(=)和连续赋值(assign)。 5.条件分支语句:if, else if和else语句是用来控制程序流程,实现条件判断。 6.循环语句:Verilog支持for、while、do while和forever等类型的循环语句,可以在程序中实现迭代操作。 7.模块实例化:用来将其他模块作为子模块嵌入到当前模块中,从而实现复杂的数字电路。 除上述基本语法外,Verilog还有其他常用语法,如always块、initial块和function定义等。需要深入了解和使用Verilog,可以参考相关资料和教程。掌握了Verilog语法,可以使用FPGA搭建各种个性化的数字电路,用于嵌入式系统、数字信号处理、计算机网络等各种应用领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值