HDLBits刷题——Day3(Arithmetic Circuits)

  • Create a one-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
module top_module( 
    input a, b, sel,
    output out ); 
    
    assign out = sel ? b:a;
    
endmodule
----------------参考示例------------------------
module top_module (
    input a,
    input b,
    input sel,
    output out
);

    assign out = (sel & b) | (~sel & a);    // Mux expressed as AND and OR
    
    // Ternary operator is easier to read, especially if vectors are used:
    // assign out = sel ? b : a;
    
endmodule
  • Create a 100-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
module top_module (
    input [99:0] a,
    input [99:0] b,
    input sel,
    output [99:0] out
);

    assign out = sel ? b : a;
    
    // The following doesn't work. Why?
    // assign out = (sel & b) | (~sel & a);
    
endmodule
  • Create a 16-bit wide, 9-to-1 multiplexer. sel=0 chooses a, sel=1 chooses b, etc. For the unused cases (sel=9 to 15), set all output bits to '1'.
module top_module( 
    input [15:0] a, b, c, d, e, f, g, h, i,
    input [3:0] sel,
    output [15:0] out );
    reg[15:0] out1 ;
    always @(*)
        case(sel)
            0 : out1 = a;
            1 : out1 = b;
            2 : out1 = c;
            3 : out1 = d;
            4 : out1 = e;
            5 : out1 = f;
            6 : out1 = g;
            7 : out1 = h;
            8 : out1 = i;
            default : out1 = 16'b1111_1111_1111_1111;   //   out1 = 16'hffff 
        endcase
    assign out = out1;

endmodule
---------------------------参考其他代码---------------------------------

module top_module( 
    input [15:0] a, b, c, d, e, f, g, h, i,
    input [3:0] sel,
    output reg [15:0] out );
    always @(*)begin
        out=16'hffff;
        case(sel)
            4'd0:out = a;
            4'd1:out = b;
            4'd2:out = c;
            4'd3:out = d;
            4'd4:out = e;
            4'd5:out = f;
            4'd6:out = g;
            4'd7:out = h;
            4'd8:out = i;
            
        endcase
    end
endmodule
————————————————
版权声明:本文为CSDN博主「李锐博恩」的原创文章,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/reborn_lee/article/details/103219418
--------------------------------网站提供的答案------------------------------------
    // Case statements can only be used inside procedural blocks (always block)
    // This is a combinational circuit, so use a combinational always @(*) block.
    always @(*) begin
        out = '1;       // '1 is a special literal syntax for a number with all bits set to 1.
                        // '0, 'x, and 'z are also valid.
                        // I prefer to assign a default value to 'out' instead of using a
                        // default case.
        case (sel)
            4'h0: out = a;
            4'h1: out = b;
            4'h2: out = c;
            4'h3: out = d;
            4'h4: out = e;
            4'h5: out = f;
            4'h6: out = g;
            4'h7: out = h;
            4'h8: out = i;
        endcase
    end
    
endmodule
  • Create a 1-bit wide, 256-to-1 multiplexer. The 256 inputs are all packed into a single 256-bit input vector. sel=0 should select in[0], sel=1 selects bits in[1], sel=2 selects bits in[2], etc
    创建一个1位宽的256:1多路复用器。 256个输入全部打包为单个256位输入向量。sel = 0应该选择in [0]sel = 1选择in [1]中的位,sel = 2选择in [2]中的位,依此类推。
    Expected solution length: Around 1 line.
module top_module (
    input [255:0] in,
    input [7:0] sel,
    output  out
);

    // Select one bit from vector in[]. The bit being selected can be variable.
    assign out = in[sel];    // 这里需要注意的是向量的选址可以是变量
    
endmodule
  • Create a 4-bit wide, 256-to-1 multiplexer. The 256 4-bit inputs are all packed into a single 1024-bit input vector. sel=0 should select bits in[3:0], sel=1 selects bits in[7:4], sel=2 selects bits in[11:8], etc.
    创建一个 4 位宽、256 对 1 的多路复用器。256 个 4 位输入全部打包成一个 1024 位输入向量。sel=0 应该选择[3:0]中的位, sel=1 选择[7:4]中的位, sel=2 选择[11:8]中的位。
module top_module (
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out
);

    // We can't part-select multiple bits without an error, but we can select one bit at a time,
    // four times, then concatenate them together.
    assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};

    // Alternatively, "indexed vector part select" works better, but has an unfamiliar syntax:
    // assign out = in[sel*4 +: 4];     // Select starting at index "sel*4", then select a total width of 4 bits with increasing (+:) index number.     
  //  意思是 从 sel*4 开始,选择比特序号大于sel*4 的 4 位比特,相当于[sel*4+3:sel*4];
-------------------------------------------------------------------------------
     assign out = in[sel*4+3 -: 4]; // Select starting at index "sel*4+3", then select a total width of 4 bits with decreasing (-:) index number. 
  // 从索引【sel*4+3】开始,递减4位
    // Note: The width (4 in this case) must be constant. 位宽(4)必须是常量

endmodule
  • Create a half adder. A half adder adds two bits (with no carry-in) and produces a sum and carry-out.
    创建一个半加器,半加器是没有低位向前的进位,产生一个本位和一个向前的进位
module top_module( 
    input a, b,
    output cout, sum );
    
   // assign cout = a & b;       // cout  is  and   , 向前的进位是与运算的结果
   // assign sum = a ^ b;     //  sum  is  XOR,本位的和是异或的结果
    assign {cout,sum} = a + b;
endmodule
  • Create a full adder. A full adder adds three bits (including carry-in) and produces a sum and carry-out
    创建一个全加器:
module top_module( 
    input a, b, cin,
    output cout, sum );
    
    assign {cout,sum} = a + b + cin;
   
endmodule
  • Now that you know how to build a full adder, make 3 instances of it to create a 3-bit binary ripple-carry adder. The adder adds two 3-bit numbers and a carry-in to produce a 3-bit sum and carry out. To encourage you to actually instantiate full adders, also output the carry-out from each full adder in the ripple-carry adder. cout[2] is the final carry-out from the last full adder, and is the carry-out you usually see.
    现在您知道如何构建一个全加器,创建 3 个实例来创建一个 3 位二进制进位加法器。加法器将两个 3 位数字和一个进位相加以产生一个 3 位和并进位。为了鼓励您实际实例化全加器,还要输出每位进位加法器中每个全加器的进位。 cout[2] 是最后一个全加器的最终进位,也是您通常看到的进位。
module top_module( 
    input [2:0] a, b,
    input cin,
    output [2:0] cout,
    output [2:0] sum );

    assign sum[0] = a[0]^b[0]^cin;
    assign cout[0] = (a[0]^b[0])&cin |  (a[0]&b[0]);
    assign sum[1] = a[1] ^ b[1] ^ cout[0];
    assign cout[1] = (a[1]^b[1])& cout[0] |  (a[1]&b[1]);
    assign sum[2] = a[2] ^ b[2] ^ cout[1];
    assign cout[2] = (a[2]^b[2])&cout[1]|  (a[2]&b[2]);

endmodule

------------------------------------------------------------------------------------
/*这里我们自然可以想到有相同的的调用模块*/
module fulladder (
    input a,b,
    input cin,
    output cout,
    output sum );
    
    assign {cout,sum} = a + b + cin;
    
endmodule

module top_module( 
    input [2:0] a, b,
    input cin,
    output [2:0] cout,
    output [2:0] sum );
    
    wire    wire_cout0;
    wire    wire_cout1;
    wire    wire_cout2;
    
    full_adder full0(
        .a      (a[0])       ,
        .b      (b[0])       ,
        .cin    (cin)        ,
        .cout   (wire_cout0) ,
        .sum    (sum[0])
    );
    
    full_adder full1(
        .a      (a[1])       ,
        .b      (b[1])       ,
        .cin    (wire_cout0) ,
        .cout   (wire_cout1) ,
        .sum    (sum[1])
    );
    
     full_adder full2(
        .a      (a[2])       ,
        .b      (b[2])       ,
        .cin    (wire_cout1) ,
        .cout   (wire_cout2) ,
        .sum    (sum[2])
    );
    
    assign cout = {wire_cout2,wire_cout1,wire_cout0} ;

endmodule
————————————————
版权声明:本文为CSDN博主「Troke」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45931009/article/details/113977696
image.png

有了上面的学习流程,自然还会想到会生全加器实例进行运算,结果如下:

module top_module (
    input [3:0] x,
    input [3:0] y, 
    output [4:0] sum);
    
    wire cout_0,cout_1,cout_2,cout_3;
    
    fulladder f0(.a(x[0]),.b(y[0]),.cin(0),.sum(sum[0]),.cout( )) ;    // 没有接任何东西也要写上
    fulladder f1(.a(x[1]),.b(y[1]),.cin(cout_0),.sum(sum[1]),.cout(cout_1));
    fulladder f2(.a(x[2]),.b(y[2]),.cin(cout_1),.sum(sum[2]),.cout(cout_2));
    fulladder f3(.a(x[3]),.b(y[3]),.cin(cout_2),.sum(sum[3]),.cout(cout_3));
    
    assign sum = {cout_3,sum[3],sum[2],sum[1],sum[0]};
    
endmodule
module fulladder (
    input a,b,
    input cin,
    output cout,
    output sum );
    
    assign {cout,sum} = a + b + cin;
    
endmodule
-----------------------------------------------------------------------------------------
========================官网解答===============================================
module top_module (
    input [3:0] x,
    input [3:0] y,
    output [4:0] sum
);

    // This circuit is a 4-bit ripple-carry adder行波进位(ripple carry)加法器 with carry-out.
    assign sum = x+y;   // Verilog addition automatically produces the carry-out bit.

    // Verilog quirk: Even though the value of (x+y) includes the carry-out, (x+y) is still considered to be a 4-bit number (The max width of the two operands).
    // This is correct:
    // assign sum = (x+y);
    // But this is incorrect:
    // assign sum = {x+y};  // Concatenation operator: This discards the carry-out
endmodule

  • Assume that you have two 8-bit 2's complement numbers, a[7:0] and b[7:0]. These numbers are added to produce s[7:0]. Also compute whether a (signed) overflow has occurred.
    假设您有两个 8 位 2 的补码,a[7:0] 和 b[7:0]。这些数字相加产生 s[7:0]。还要计算是否发生了(有符号的)溢出。
module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); //
       
    assign s = a + b;
    assign overflow = (a[7]&b[7]&~s[7])|(~a[7]&~b[7]&s[7]);
    
endmodule
--------------------------------------------------------------------------


  • 关于符号位溢出的判断
  1. 符号位判断
    Xf、Yf分别两个数的符号位,Zf为运算结果符号位。

当Xf =Yf =0(两数同为正),而Zf=1(结果为负)时,负溢出;
当出现Xf =Yf =1(两数同为负),而Zf=0(结果为正),正溢出。

  1. 进位判断
    Cs表示符号位的进位,Cp表示最高数值位进位,⊕表示异或。

若 Cs⊕Cp =0 ,无溢出;
若 Cs⊕Cp =1 ,有溢出。

  1. 变形补码判断
    用变形补码进行双符号位运算(正数符为00,负数符号以11)

若运算结果的符号位为"01",则正溢。
若结果双符号为10,则负溢出。
————————————————
版权声明:本文为CSDN博主「沧海一升」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_21842097/article/details/116258049


  • Create a 100-bit binary adder. The adder adds two 100-bit numbers and a carry-in to produce a 100-bit sum and carry out.
    创建一个 100 位二进制加法器。加法器将两个 100 位数字和一个进位相加,产生一个 100 位和并执行。
------------------------------官网答案参考代码--------------------------------
module top_module (
    input [99:0] a,
    input [99:0] b,
    input cin,
    output cout,
    output [99:0] sum
);

    // The concatenation {cout, sum} is a 101-bit vector.
    assign {cout, sum} = a+b+cin;

endmodule
  • You are provided with a BCD (binary-coded decimal) one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out.
module bcd_fadd (
    input [3:0] a,
    input [3:0] b,
    input     cin,
    output   cout,
    output [3:0] sum );

实例化 4 个bcd_fadd副本以创建一个 4 位 BCD 波纹进位加法器。您的加法器应该将两个 4 位 BCD 数字(打包成 16 位向量)和一个进位相加,以产生一个 4 位和并执行。

module top_module ( 
    input [15:0] a, b,
    input cin,
    output cout,
    output [15:0] sum );
    
    wire c1,c2,c3,c4;

    bcd_fadd bcd1(.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(c1),.sum(sum[3:0]));
    bcd_fadd bcd2(.a(a[7:4]),.b(b[7:4]),.cin(c1),.cout(c2),.sum(sum[7:4]));
    bcd_fadd bcd3(.a(a[11:8]),.b(b[11:8]),.cin(c2),.cout(c3),.sum(sum[11:8]));
    bcd_fadd bcd4(.a(a[15:12]),.b(b[15:12]),.cin(c3),.cout(c4),.sum(sum[15:12]));
    
    assign cout = c4;

endmodule
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容