HDLBits Verilog(2)——Multiplexer & Arithmetic Circuits
- ----- 61. 2-to-1 multiplexer -----
- ----- 62. 2-to-1 bus multiplexer -----
- ----- 63. 9-to-1 multiplexer -----
- ----- 64. 256-to-1 multiplexer -----
- ----- 65. 256-to-1 4-bit multiplexer -----
- ----- 66. Half adder -----
- ----- 67. Full adder -----
- ----- 68. 3-bit binary adder -----
- ----- 69. Adder -----
- ----- 70. Signed addition overflow -----
- ----- 71. 100-bit binary adder -----
- ----- 72. 4-digit BCD adder -----
----- 61. 2-to-1 multiplexer -----
Problem Statement
Create a one-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
Expected solution length: Around 1 line.
Answer
module top_module(
input a, b, sel,
output out );
assign out = (~sel & a) | (sel & b);
//other way: assign out = sel ? b : a;
endmodule
----- 62. 2-to-1 bus multiplexer -----
Problem Statement
Create a 100-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
Expected solution length: Around 1 line.
Answer
module top_module(
input [99:0] a, b,
input sel,
output [99:0] out );
assign out = ( ~{100{sel}} & a) | ( {100{sel}} & b);
//other way: assign out = sel ? b : a;
endmodule
----- 63. 9-to-1 multiplexer -----
Problem Statement
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'.
Expected solution length: Around 15 lines.
Answer
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
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;
default: out = {16{1'b1}};
endcase
end
endmodule
----- 64. 256-to-1 multiplexer -----
Problem Statement
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.
Expected solution length: Around 1 line.
Answer
module top_module(
input [255:0] in,
input [7:0] sel,
output out );
assign out = in[sel];
endmodule
----- 65. 256-to-1 4-bit multiplexer -----
Problem Statement
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.
Expected solution length: Around 1–5 lines.
Answer
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out = {in[4*sel+3], in[4*sel+2], in[4*sel+1], in[4*sel]};
endmodule
Note: An unfamiliar syntax
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.
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.
- Note: The width (4 in this case) must be constant. So
assign out = in[4*sel+3 : 4*sel]
is the wrong way.
----- 66. Half adder -----
Problem Statement
Create a half adder. A half adder adds two bits (with no carry-in) and produces a sum and carry-out.
Expected solution length: Around 2 lines.
Answer1
module top_module(
input a, b,
output cout, sum );
assign sum = a ^ b;
assign cout = a & b;
endmodule
Answer2
module top_module(
input a, b,
output cout, sum );
assign {cout, sum} = a + b;
endmodule
----- 67. Full adder -----
Problem Statement
Create a full adder. A full adder adds three bits (including carry-in) and produces a sum and carry-out.
Expected solution length: Around 2 lines.
Answer1
module top_module(
input a, b, cin,
output cout, sum );
wire s, co1, co2;
assign s = a ^ b;
assign co1 = a & b;
assign sum = cin ^ s;
assign co2 = cin & s;
assign cout = co1 | co2;
endmodule
Answer2
module top_module(
input a, b, cin,
output cout, sum );
assign {cout, sum} = a + b + cin;
endmodule
----- 68. 3-bit binary adder -----
Problem Statement
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.
Answer
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
adder adder1(.a(a[0]), .b(b[0]), .cin(cin), .cout(cout[0]), .sum(sum[0])); // low-bit
adder adder2(.a(a[1]), .b(b[1]), .cin(cout[0]), .cout(cout[1]), .sum(sum[1]));
adder adder3(.a(a[2]), .b(b[2]), .cin(cout[1]), .cout(cout[2]), .sum(sum[2])); // high-bit
endmodule
module adder(
input a, b, cin,
output cout, sum );
assign {cout, sum} = a + b + cin;
endmodule
----- 69. Adder -----
Problem Statement
Implement the following circuit:
("FA" is a full adder)
Answer
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum);
wire [2:0] io;
adder adder1(.a(x[0]), .b(y[0]), .cin(0), .cout(io[0]), .sum(sum[0])); // low-bit
adder adder2(.a(x[1]), .b(y[1]), .cin(io[0]), .cout(io[1]), .sum(sum[1]));
adder adder3(.a(x[2]), .b(y[2]), .cin(io[1]), .cout(io[2]), .sum(sum[2]));
adder adder4(.a(x[3]), .b(y[3]), .cin(io[2]), .cout(sum[4]), .sum(sum[3])); // high-bit
endmodule
module adder(
input a, b, cin,
output cout, sum );
assign {cout, sum} = a + b + cin;
endmodule
----- 70. Signed addition overflow -----
Problem Statement
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.
Answer1
检测补码加法中的溢出(深入理解计算机系统,CS:APP,P65):令s = x + y
,当 x > 0, y > 0, s < 0
时,s
发生正溢出(即 x 和 y的最高位为 0,s 最高位为 1 时发生正溢出);当 x < 0, y < 0, s > 0
时,s
发生负溢出(即 x 和 y的最高位为 1,s 最高位为 0 时发生负溢出)。
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
);
wire [7:0] io;
adder adder0(.a(a[0]), .b(b[0]), .cin(0), .cout(io[0]), .sum(s[0])); // low-bit
adder adder1(.a(a[1]), .b(b[1]), .cin(io[0]), .cout(io[1]), .sum(s[1]));
adder adder2(.a(a[2]), .b(b[2]), .cin(io[1]), .cout(io[2]), .sum(s[2]));
adder adder3(.a(a[3]), .b(b[3]), .cin(io[2]), .cout(io[3]), .sum(s[3]));
adder adder4(.a(a[4]), .b(b[4]), .cin(io[3]), .cout(io[4]), .sum(s[4]));
adder adder5(.a(a[5]), .b(b[5]), .cin(io[4]), .cout(io[5]), .sum(s[5]));
adder adder6(.a(a[6]), .b(b[6]), .cin(io[5]), .cout(io[6]), .sum(s[6]));
adder adder7(.a(a[7]), .b(b[7]), .cin(io[6]), .cout(io[7]), .sum(s[7])); // high-bit
assign overflow = (a[7] & b[7] & ~s[7]) | (~a[7] & ~b[7] & s[7]); // 检测补码加法中的溢出(CS:APP,P65)
endmodule
module adder(
input a, b, cin,
output cout, sum );
assign {cout, sum} = a + b + cin;
endmodule
Answer2
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
----- 71. 100-bit binary adder -----
Problem Statement
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.
Expected solution length: Around 1 line.
Answer1
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
genvar i;
wire [99:0] io;
generate
for(i = 0; i <= 99; i = i + 1)begin: add100
if(i == 0)
assign {io[i], sum[i]} = a[i] + b[i] + cin;
else
assign {io[i], sum[i]} = a[i] + b[i] + io[i-1];
end
assign cout = io[99];
endgenerate
endmodule
Answer2
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
----- 72. 4-digit BCD adder -----
Problem Statement
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 );
Instantiate 4 copies of bcd_fadd to create a 4-digit BCD ripple-carry adder. Your adder should add two 4-digit BCD numbers (packed into 16-bit vectors) and a carry-in to produce a 4-digit sum and carry out.
Answer
module bcd_fadd (
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );
//...
endmodule
module top_module(
input [15:0] a, b,
input cin,
output cout,
output [15:0] sum );
wire io0, io1, io2, io3;
bcd_fadd bcd_fadd0(.a(a[3:0]), .b(b[3:0]), .cin(cin), .cout(io0), .sum(sum[3:0]));
bcd_fadd bcd_fadd1(.a(a[7:4]), .b(b[7:4]), .cin(io0), .cout(io1), .sum(sum[7:4]));
bcd_fadd bcd_fadd2(.a(a[11:8]), .b(b[11:8]), .cin(io1), .cout(io2), .sum(sum[11:8]));
bcd_fadd bcd_fadd3(.a(a[15:12]), .b(b[15:12]), .cin(io2), .cout(io3), .sum(sum[15:12]));
assign cout = io3;
endmodule
Warning
- Warning (10230): Verilog HDL assignment warning at tb_modules.sv(8): truncated value with size 32 to match size of target (4) File
Truncating values occur when the right side of an assignment is wider than the left side and the upper bits are cut off. This can indicate a bug if there is a truncation you didn't expect, so check these carefully. The most common case where this isn't a bug is when you're using literals without a width (32 bits is implied), e.g., using assign a[1:0] = 1;
instead of assign a[1:0] = 2'd1;
.