• HDLBits: 在线学习 SystemVerilog(六)-Problem 24-27


    HDLBits: 在线学习 SystemVerilog(六)-Problem 24-27

    493a4e1550b575babfe30993794ddaea.jpeg

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

    网址如下:

    https://hdlbits.01xz.net/

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

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

    缩略词索引:

    • SV:SystemVerilog

    Problem 24-Module_add

    题目说明

    给出了一个可以做16bit加法的模块add16,实例化两个add16以达到32bit加法的。

    e494351546dd58781b066f38457a85be.png图片来自 HDLBits

    这个题目的核心就是上面的图片,将两个16bit加法合成32bit加法即可。

    模块端口声明

    1. module top_module(
    2.     input [31:0] a,
    3.     input [31:0] b,
    4.     output [31:0] sum
    5. );

    题目解析

    这个题目重点是进位的处理,一个add16模块计算结果的低16位,另一个add16模块在接收到第一个的进位后计算结果的高16位。此32bit加法器不需要处理输入进位(假设为0)和输出进位(无需进位),但为了内部模块为了结果的正确仍要处理进位信号。(换句话说,add16模块执行16bit的a+b+cin,而顶层模块执行32bit的a+b)

    1. module top_module(
    2.     input logic [31:0] a,
    3.     input logic [31:0] b,
    4.     output logic [31:0] sum
    5. );
    6.     wire logic [15:0] sum_temp0,sum_temp1;
    7.     var logic cout1;
    8.     add16 d1 (
    9.         .a(a[15:0]),
    10.         .b(b[15:0]),
    11.         .cin(1'd0),
    12.         .sum(sum_temp0),
    13.         .cout(cout1)
    14.     );
    15.     
    16.     add16 d2 (
    17.         .a(a[31:16]),
    18.         .b(b[31:16]),
    19.         .cin(cout1),
    20.         .sum(sum_temp1),
    21.         .cout()
    22.     );
    23.     
    24.     assign sum = {sum_temp1,sum_temp0} ;
    25. endmodule
    b0f1628a3c9635fb0ae0dc91693456ff.png

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

    f6b2b77ee45fa2804e20ba50fe04093a.png

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

    这一题就结束了。

    Problem 25-Module fadd

    题目说明

    在本练习中,将创建具有两个层次结构的电路。top_module将实例化add16(提供)的两个副本,每个副本将实例化add1(必须自己编写)的 16 个副本。因此,必须编写两个模块:top_module和add1。 与Problem 24: Adder 1(Module add)一样,提供给您一个执行16bit的加法的模块。您需要实例化两个16bit加法模块来实现32bit加法器。一个add16计算加法结果的低16位,另一个计算结果的高16位。您的32位加法器同样不需要处理进位输入(假设为0)和进位输出(无需进位)信号。

    如下图所示,将add16模块连接在一起,给出的add16模块如下:

    module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );

    在每个add16中,16 个全加器(模块add1,未提供)被实例化以实际执行加法。必须编写具有以下声明的完整加法器模块:

    module add1 ( input a, input b, input cin, output sum, output cout );

    回想一下,全加器计算 a+b+cin 的和和进位。

    综上所述,本设计共有三个模块:

    • top_module— 顶级模块包含两个add16

    • add16 — 一个 16 位加法器模块,由 16 个add1组成

    • add1 — 1 位全加器模块。

    如果提交缺少add1模块,将收到一条错误消息,内容为:

    Error (12006): Node instance "user_fadd[0].a1" instantiates undefined entity "add1".
    a64bde1b204acd48ea1ee649a404ef9b.png图片来自 HDLBits

    模块端口声明

    1. module top_module (
    2.     input [31:0] a,
    3.     input [31:0] b,
    4.     output [31:0] sum
    5. );

    题目解析

    只比上一题复杂些,核心内容没变。

    1. module top_module (
    2.     input logic [31:0] a,
    3.     input logic [31:0] b,
    4.     output logic [31:0] sum
    5. );//
    6.     
    7.     wire logic cout ;
    8.     
    9.     add16 u1_add16 (
    10.         .a(a[15:0]),
    11.         .b(b[15:0]),
    12.         .cin(1'd0),
    13.         .sum(sum[15:0]),
    14.         .cout(cout)
    15.                   );
    16.     add16 u2_add16 (
    17.         .a(a[31:16]),
    18.         .b(b[31:16]),
    19.         .cin(cout),
    20.         .sum(sum[31:16]),
    21.         .cout()
    22.                   );
    23. endmodule
    24. module add1 ( input logic a, 
    25.               input logic b, 
    26.               input logic cin, 
    27.               output logic sum,
    28.               output logic cout 
    29.             );
    30. // Full adder module here
    31.     assign {cout,sum} = a+b+cin ;
    32. endmodule
    6f0022815010c00f0801bfcd8975a6d1.png

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

    c0823375bda5177caed0b1116740f660.png

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

    这一题就结束了。

    Problem 26-Module_cseladd

    题目说明

    上一个练习中(Problem 25: Adder 2(Module fadd))实现的加法器应该叫做行波进位加法器(RCA: Ripple-Carry Adder)。这种加法器的缺点是计算进位输出的延迟是相当慢的(最坏的情况下,来自于进位输入)。并且如果前一级加法器计算完成之前,后一级加法器不能开始计算。这又使得加法器的计算延迟变大。

    一种改进是进位选择加法器,如下所示。第一级加法器与之前相同,但我们复制第二级加法器,一个假设进位=0,一个假设进位=1,然后使用快速2对1多路复用器选择哪个结果碰巧是正确的。

    在本练习中,将获得与上一个练习相同的模块add16,该模块将两个 16 位数字与进位相加,并产生一个进位和 16 位和。必须实例化其中的三add16来构建进位选择加法器,同时实现16bit的2选1选择器来选择结果。

    如下图所示将模块连接在一起。提供的模块add16具有以下声明:

    module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
    22a49c1a1b23de557becee0f05463b45.png图片来自 HDLBits

    模块端口声明

    1. module top_module(
    2.     input [31:0] a,
    3.     input [31:0] b,
    4.     output [31:0] sum
    5. );

    题目解析

    这题是上一题的改进版本的加法器,其实这也是我们数电上学到的CSA(Carry-Select Adder,选择进位加法器),其相对于行波进位加法器延迟小一半左右,但是其是利用资源换取的,所以相应消耗的资源增加约一倍。

    1. module top_module(
    2.     input logic [31:0] a,
    3.     input logic [31:0] b,
    4.     output logic [31:0] sum
    5. );
    6.     wire logic cout_sel;
    7.     wire logic [15:0] upperbit_sum0,upperbit_sum1 ;
    8.     add16 u0_add16 (
    9.         .a(a[15:0]),
    10.         .b(b[15:0]),
    11.         .cin(1'd0),
    12.         .sum(sum[15:0]),
    13.         .cout(cout_sel)
    14.     );
    15.     
    16.     add16 u1_add16 (
    17.         .a(a[31:16]),
    18.         .b(b[31:16]),
    19.         .cin(1'd0),
    20.         .sum(upperbit_sum0),
    21.         .cout()
    22.     );
    23.     
    24.     add16 u2_add16 (
    25.         .a(a[31:16]),
    26.         .b(b[31:16]),
    27.         .cin(1'd1),
    28.         .sum(upperbit_sum1),
    29.         .cout()
    30.     );
    31.     
    32.     always_comb
    33.         begin
    34.             unique case(cout_sel)
    35.                 
    36.                 1'd0:  sum[31:16] = upperbit_sum0 ;
    37.                 1'd1:  sum[31:16] = upperbit_sum1 ;
    38.                 default: sum[31:16] = upperbit_sum0 ;
    39.             endcase
    40.         end
    41. endmodule
    ae48eb64c65564c25f0c0f35592adfbe.png

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

    94ff44a8c82899864590363d9abd13e3.png

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

    这一题就结束了。

    Problem 27-Module addsub

    题目说明

    减法器可以通过选择性地取反一个输入而从加法器构建,这相当于将输入反相然后加 1。最终结果是一个可以执行两种操作的电路:(a + b + 0) 和 ( a + ~b + 1)。

    题目要求构建下面的加减法器。

    提供了一个 16 位加法器模块,需要对其进行两次实例化:

    module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );

    每当sub为 1 时,使用 32 位宽的 XOR 门来反转b输入。(这也可以被视为b[31:0]与sub复制32次相异或)。同时sub信号连接到加法器的进位。

    c545216b7fbd1a544706a83b5e0fa2e2.png图片来自 HDLBits

    模块端口声明

    1. module top_module(
    2.     input [31:0] a,
    3.     input [31:0] b,
    4.     input sub,
    5.     output [31:0] sum
    6. );

    题目解析

    这个题目考察的是减法器,这里就用到数电小常识:减去一个数等于加上这个数的补码(就是题中的按位取反再加1)。

    1. module top_module(
    2.     input logic [31:0] a,
    3.     input logic [31:0] b,
    4.     input logic sub,
    5.     output logic [31:0] sum
    6. );
    7.     wire logic cout_0 ;
    8.     wire logic [31:0] b_reverse ;
    9.     assign b_reverse = b^{32{sub}} ;
    10.     
    11.     add16 u1_add16 (
    12.         .a(a[15:0]),
    13.         .b(b_reverse[15:0]),
    14.         .cin(sub),
    15.         .sum(sum[15:0]),
    16.         .cout(cout_0)
    17.     );
    18.     
    19.    
    20.     add16 u2_add16 (
    21.         .a(a[31:16]),
    22.         .b(b_reverse[31:16]),
    23.         .cin(cout_0),
    24.         .sum(sum[31:16]),
    25.         .cout()
    26.     );
    27. endmodule
    b5fde0ad6b86d9b4775bb557c2a8433d.png

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

    154f2079bd4ccb4ce35cedabdfc5402f.png

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

    这一题就结束了。

    总结

    今天的几道题就结束了,从代码量上看,是不是感觉难度加大了呢?没事,后面的题目难度会越来越大~

    a3a0f9edd6fae978fa4669eae3a740a8.png

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

    代码链接:

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

    往期推荐

    HDLBits: 在线学习 SystemVerilog(五)-Problem 19-23

  • 相关阅读:
    Linux:进程调度的O(1)算法
    C#自定义配置文件(一)
    需要3D地图做数字孪生?选择这款数字孪生软件,全国各省份多种风格的三维地图任你选用
    HTML5离线储存
    自动驾驶学习笔记(六)——Apollo安装
    浅谈 Hive 数据倾斜原因及解决方案
    zabbix(一)
    抖音获取抖音商品原数据 API 返回值说明
    TIM_CCxChannelCmd函数无法关闭互补通道输出
    Util应用框架基础(四) - 验证
  • 原文地址:https://blog.csdn.net/Pieces_thinking/article/details/126882523