G
N
I
D
A
O
L

HDLBits Verilog(2)——Multiplexer & Arithmetic Circuits

----- 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:

image

("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;.

posted @ 2021-08-05 10:33  漫舞八月(Mount256)  阅读(1053)  评论(0编辑  收藏  举报