• HDLBits: 在线学习 SystemVerilog(一)-Problem 2-6


    HDLBits: 在线学习 SystemVerilog(一)-Problem 2-6

    842f0d28e73e7bc39262af20b3fb5479.jpeg

    HDLBits 是一组小型电路设计习题集,使用 Verilog/SystemVerilog 硬件描述语言 (HDL) 练习数字硬件设计~

    网址如下:

    https://hdlbits.01xz.net/

    关于HDLBits的Verilog实现可以查看下面专栏:

    https://www.zhihu.com/column/c_1131528588117385216

    缩略词索引:

    • SV:SystemVerilog

    Problem 2-Wire

    wire介绍

    关于Verilog中的wire变量介绍,HDLBits有详细的介绍,这里不再赘述。介绍一下SV中关于wire变量介绍:

    网络类型

    网络用于将设计元素连接在一起,例如将一个模块的输出端口连接到另一个模块的输入端口。网络在三个重要方面不同于变量:

    • 网络没有像变量一样的临时存储,相反,网络反映了网络驱动器的当前值(电容性trireg网络似乎存储了一个值,但实际上代表了驱动网络的电容器的行为),

    • 网络可以计算多个驱动因素的结果值,其中变量只能有一个来源(如果对一个变量进行了多个程序赋值,则最后一个赋值是结果值,而不是解析所有赋值的结果)。

    • 网络反映驱动器值(0、l、Z或X)和驱动器强度。

    驱动器的强度级别以0~7的步长表示。每个级别由一个关键字表示。大多数建模构件的默认强度级别为“强”,即级别6。强度级别对于晶体管级建模很重要,但不用于RTL建模。强度的表示和使用超出了本文关于RTL建模的范围。

    可综合网络类型

    通过同时指定类型和数据类型来声明网络。类型可以是表3-3和3-4中列出的任何关键字。数据类型必须是关键字logic,可以显式指定或隐式推断。

    每个SystemVerilog网络类型都有特定的语义规则,这些规则会影响多个驱动程序的解析方式。虽然所有网络类型都表示硅行为,但并非所有网络类型都可以用标准ASIC和FPGA技术表示。表3-3列出了ASIC和FPGA综合编译器支持的网络类型。

    表3-3:可综合网络类型
    类型代表
    wire使用CMOS行为解析多个驱动器的互连网络
    triwire的同义词在所有方面都相同,可用于强调预期具有三态值的网络
    Supply0在电源强度级别具有恒定逻辑0的互连网络。可用于表示接地轨(GND、VSS)
    Supply1在电源强度级别具有恒定逻辑1的互连网络。可用于表示供电轨(VCC、VDD)

    不可综合的网络类型。

    SystemVeriIog有几种网络类型,综合编译器并不普遍支持这些类型,如表3-4(第77页)所示。

    表3-4:一般不可综合的网络类型
    类型代表
    uwire不允许或不解析多个驱动程序的互连网络
    pull0一种互连网络,具有将下拉电阻器连接到网络的特性
    Pull1一种互连网络,具有将上拉电阻器连接到该网络的特性
    wand一种互连网络,通过对驱动值进行AND运算来解析多个驱动程序
    triandwand的同义词,在所有方面都相同;可用于强调预期具有三态值的网络
    wor一种互连网络,通过对驱动值进行OR来解析多个驱动程序
    triorwor的同义词,在所有方面都相同;可用于强调预期具有三态值的网络
    trireg具有电容性的互连网络;如果所有驱动器均为高阻抗,则电容反映最后解析的驱动值
    笔记

    某些RTL综合编译器可能支持一种或多种网络类型。最佳实践编码风格是不使用这些类型,以确保RTL模型与任何综合编译器兼容。如果使用其中一种类型,设计工程师应检查项目中使用的所有工具是否支持该类型。

    题目说明

    创建一个具有一个输入一个输出的模块,其行为类似于wire(网络)。

    37a361982c5ad8f884b275bc09606cb3.png图片来自 HDLBits

    这个题目的核心就是上面的图片,模块和端口已经被定义好了,黑色的框图以及箭头代表模块和端口。我们需要做的工作是完成图中绿色的部分,即完成这条连线

    图中已经给出了实现这条线的关键语句:assign。关于assign语句SV中的关键点如下:

    assign语句SV中的关键点

    给wire赋值。wire可以从两种类型的源接收值:作为output or inout port端口的连接,以及作为连续赋值(assign语句)的左侧。不能在程序赋值的左侧使用wire。

    在整个仿真过程中对连续赋值进行求值,赋值右侧的任何更改都会导致对右侧表达式进行求值,并更新左侧表达式。左侧可以是变量或wire。wire的连续赋值可以是显式的,也可以是隐式的。显式连续赋值以关键字assign开始。

    cf702012489a2dd2adc6dab4755627a2.png

    隐式连续赋值结合了网络声明和对该网络的赋值。组合中未使用assign关键字。

    31990728760ae3980d32c14c0b0fe3fb.png

    注意不要混淆内嵌变量初始化和隐式连续赋值。

    66540d5a0f105d665099dd531162dc67.png

    这两个构造的语法可能看起来很相似,但行为却截然不同。在线变量初始化是一次评估和赋值,在前面的示例中,如果a或b的值在以后的仿真中发生变化,则不会更新变量。隐式连续赋值,顾名思义,是在整个仿真过程中不断求值的表达式。在前面的示例中,每次仿真期间a或b的值发生变化时,n1都会更新。

    连接大小不匹配。wire用于将设计块连接在一起,例如将一个模块的输出端口连接到一个或多个其他模块的输入端口。通常,端口和互连网络的向量宽度相同,但SystemVerilog允许向量大小不同。例如16位标量网络可以将32位宽的输出端口连接到8位宽的输入端口。这种尺寸不匹配可能是设计错误,但在SystemVerilog中,只会生成警告。

    SystemVerilog语言具有解决端口/连接不匹配的规则:

    • port的比特数少于连接到的网络或变量-值的最左边的比特被截断,导致值的最重要比特丢失。

    • 一个端口的比特数大于连接到它的网络或变量的比特数-网络或变量的值保持扩展状态,如果端口、网络/变量中有一个无符号,则该值为零扩展。如果端口和网络/变量都有符号,则该值为有符号。

    • 仿真器和综合编译器将生成连接大小不匹配的警告消息。这些警告不容忽视!连接不匹配通常是需要纠正的设计错误。    |

    模块端口声明

    module top_module( input in, output out );

    题目解析

    这个没什么说的,一句话就可以了“assign out = in;”。难度不大,对于SV/Verilog来说,重点关注assign实现组合逻辑的一些注意点。

    1. module top_module( input logic in, 
    2.                    output logic out 
    3.                  );
    4.     assign out = in ;
    5.     
    6. endmodule
    3393f2e392211619e591200ef5eaae40.png

    点击Submit,等待一会就能看到下图结果:

    3561fe6c6b34125967acc9bf4d351ab3.png

    注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红(后面会展示)。

    这一题就结束了。

    Problem 3-Wire4

    题目说明

    创建一个具有 3 个输入和 4 个输出的模块,其行为类似于下面演示的这些连线:

    1. a -> w
    2. b -> x
    3. b -> y
    4. c -> z
    49cae7d9f4c7d6c9205e0fcbe254cdbc.png图片来自 HDLBits

    这个题目的核心就是上面的图片,模块和端口已经被定义好了,黑色的框图以及箭头代表模块和端口。我们需要做的工作是完成图中绿色的部分,即完成这条连线

    模块端口声明

    1. module top_module( 
    2.     input a,b,c,
    3.     output w,x,y,z );

    题目解析

    主要使用assign语句实现上面的连线,难度较低。

    1. module top_module( 
    2.     input logic a,b,c,
    3.     output logic w,x,y,z
    4. );
    5.     assign w = a;
    6.     assign x = b;
    7.     assign y = b;
    8.     assign z = c;
    9.     
    10. endmodule
    d637b1e7d6d43ed67769e0f10d3d6ea3.png

    点击Submit,等待一会就能看到下图结果:

    b16e55eb808799fe8e02727a0751ec69.png

    注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红(后面会展示)。

    这一题就结束了。

    Problem 4-Notgate

    题目说明

    创建一个实现非门(Notgate)的模块。

    af5bc0909c34fecfd1023677853cd441.png图片来自 HDLBits

    从这个题目开始实现几个经典组合电路,非门的的核心就是上面的图片,模块和端口已经被定义好了,黑色的框图以及箭头代表模块和端口。我们需要做的工作是完成图中绿色的部分,实现一个非门。

    模块端口声明

    module top_module( input in, output out );

    题目解析

    主要使用assign语句实现非门,也很简单就一个语句“assign out = ~in;”。这里注意一个逻辑取反和逐位取反的区别。

    1. module top_module( input  logic in, 
    2.                    output logic out 
    3.                  );
    4.     assign out = ~in ;
    5.     
    6. endmodule

    上面使用“assign out = ~in ;”和“assign out = !in ;”无区别,因为只有一位变量。

    8ea327c09efef5a35e3485dacc969813.png

    点击Submit,等待一会就能看到下图结果:

    4e148ecdebb65dd8a89c10a649b34b95.png

    注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红(后面会展示)。

    这一题就结束了。

    Problem 5-Andgate

    题目说明

    创建一个与门(Andgate)模块。。

    1e70f3aa39d1c5be4e91442e0c37731f.png图片来自 HDLBits

    与门的的核心就是上面的图片,模块和端口已经被定义好了,黑色的框图以及箭头代表模块和端口。我们需要做的工作是完成图中绿色的部分,实现一个与门。

    模块端口声明

    1. module top_module( 
    2.     input a, 
    3.     input b, 
    4.     output out );

    题目解析

    主要使用assign语句实现与门,也很简单就一个语句“assign out = a & b;”。值得注意的是 & 和 && 的区别。

    1. module top_module( 
    2.     input logic a, 
    3.     input logic b, 
    4.     output logic out );
    5.  
    6.     assign out = a & b;
    7.     
    8. endmodule
    512c8aed55f9a8d6de0f0d129550d072.png

    点击Submit,等待一会就能看到下图结果:

    916090c7da62e1a05ab15c324d54a297.png

    注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红(后面会展示)。

    这一题就结束了。

    Problem 6-Norgate

    题目说明

    创建一个实现 NOR 门的模块。或非门(Norgate)是一个输出反相的或门。用 Verilog 编写的 NOR 门需要两个运算符。

    8d361655a520713da53e03ac913a92ac.png图片来自 HDLBits

    或非门的的核心就是上面的图片,模块和端口已经被定义好了,黑色的框图以及箭头代表模块和端口。我们需要做的工作是完成图中绿色的部分,实现一个或非门。从图中可以看出就是一个或门输出取反,核心就是先实现一个或门,之后再输出端取反即可,可以使用两个assign语句或者一个assign语句实现。

    模块端口声明

    1. module top_module( 
    2.     input a, 
    3.     input b, 
    4.     output out );

    题目解析

    这一题的关键是看懂题目给的符号,给大家一个常用的门电路示意图:

    089518fceb922fcafe92f981e9c6e871.png

    HDLbits网站上的使用的是国外流行图形符号一栏,从题目给定的符号,对比上一图就是典型的或非门,由或门和非门组合实现。

    1. module top_module( 
    2.     input logic a, 
    3.     input logic b, 
    4.     output logic out );
    5.     
    6.     assign out = ~(a | b);
    7. endmodule

    代码中(a|b)实现一个或门,然后取反即可~(a | b)。

    ba2ce1e6e4e4f6dc4ca03761bb2aeb50.png

    点击Submit,等待一会就能看到下图结果:

    d75f57c34f178caed1e5984a378ef041.png

    注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

    错误示范

    一开始代码写错了,写成:

    1. module top_module( 
    2.     input logic a, 
    3.     input logic b, 
    4.     output logic out );
    5.     
    6.     assign out = ~a | b;
    7. endmodule

    仿真结果如下:

    889ee89fe9576807035e503ca28f17d5.png

    造成上面结果的主要原因还是因为Verilog/SV中逻辑操作,运算符等有优先级(和数学里的加减乘除乘除一样),具体优先级如下:

    0ac1c3aed4a823f0d6f9d32a2717d7e0.png

    所以上面的代码会优先做~a然后在和b或,加上括号解决。

    总结

    今天的5道题就结束了,整体难度不大,后面的题目难度会越来越大~

    最后我这边做题的代码也是个人理解使用,有错误欢迎大家批评指正,祝大家学习愉快~

    代码链接:

    https://github.com/suisuisi/SystemVerilog/tree/main/SystemVerilogHDLBits

    往期推荐

    HDLBits: 在线学习 SystemVerilog(零)-在线“巡礼” HDLBits

  • 相关阅读:
    Docker安装Elasticsearch并启动密码xpack功能
    【Matlab】状态空间模型的最小化实现 minreal() 函数
    测试用例的设计方法及测试分类
    c# xml 参数配置表的使用
    (附源码)计算机毕业设计SSM基于的宿舍楼跳蚤市场管理系统
    el-cascader三级联动懒加载回显问题
    python代码小tips-从HTML字符串中提取文本内容并去掉标签
    【操作系统】内存管理(一)—— 内存管理的概述与总结
    持续集成如何进行Jenkins管理?
    【ESP32】10.PCF8591数模转换器实验(IIC总线/wire库)
  • 原文地址:https://blog.csdn.net/Pieces_thinking/article/details/126277356