module top_module ( input a, input b, input c, output w, output x, output y, output z ); assign w = a; assign x = b; assign y = b; assign z = c;
// If we're certain about the width of each signal, using // the concatenation operator is equivalent and shorter: // assign {w,x,y,z} = {a,b,b,c}; endmodule
Inverter
1 2 3 4 5 6 7 8 9
module top_module( input in, output out ); assign out = ~in; endmodule
AND gate
1 2 3 4 5 6 7
module top_module( input a, input b, output out ); assign out = a & b ; endmodule
NOR gate
1 2 3 4 5 6 7
module top_module( input a, input b, output out ); assign out = ! (a | b) ; endmodule
XNOR gate
Declaring wires
7458 chip
Vectors
Vectors
More Verilog Features
*Combinational for-loop : Vector reversal 2
Given a 100-bit input vector [99:0], reverse its bit ordering.
1 2 3 4 5 6 7 8 9
// False Vesion module top_module( input [99:0] in , output [99:0] out ) ; for(int i = 0 ; i < 100 ; i++) begin assign out[i] = in [99 - i] ; end endmodule
1
Error (10170): Verilog HDL syntax error at top_module.v(6) near text: "for"; expecting "endmodule".
module top_module( input [99:0] in , output [99:0] out ) ; genvar i ;//state a variable i generate for(i = 0 ; i < 100 ; i++) begin : generate_name assign out[i] = in [99 - i] ; // type of out is wire end endgenerate endmodule
或者将for-loop写在always中:
1 2 3 4 5 6 7 8 9 10 11 12
module top_module( input [99:0] in , outputreg [99:0] out ) ; always @(*)begin for(int i = 0 ; i < $bits(out) ; i++ ) begin //$bits(signal)获取信号位长 out[i] = in [ $bits(out) - 1 - i ] ; //type of out is reg end end endmodule
Combinational for-loop:255-bit population count
A “population count” circuit counts the number of ‘1’s in an input vector. Build a population count circuit for a 255-bit input vector.
1 2 3 4 5 6 7 8 9 10 11
module top_module( input [254:0] in, outputreg [7:0] out ); always @(*) begin out = 0 ;//寄存器型变量在always块中初始化 for(int i = 0 ; i < 255 ; i++) begin out = out + in[i] ; end end endmodule
Generate for-loop:1000-bit binary adder 2
Create a 100-bit binary ripple-carry adder by instantiating 100 full adders. The adder adds two 100-bit numbers and a carry-in to produce a 100-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[99] is the final carry-out from the last full adder, and is the carry-out you usually see.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
module top_module( input [99:0] a, b, input cin, output [99:0] cout, output [99:0] sum ); generate genvar i ;//好像在for循环内声明genvar i 会报错 assign sum[0] = a[0] ^ b[0] ^ cin ; assign cout[0] = a[0] & b[0] | a[0] & cin | b[0] & cin ; for (i = 1 ; i < 100 ; i++) begin : generate_name assign sum[i] = a[i] ^ b[i] ^ cout[i-1] ; assign cout[i] = a[i] & b[i] | a[i] & cout[i-1] | b[i] & cout[i-1] ; end endgenerate endmodule
*Generate for-loop:100-digit BCD adder
You are provided with a BCD one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out.
1 2 3 4 5 6
module bcd_fadd ( input [3:0] a, input [3:0] b, input cin, output cout, output [3:0] sum );
Instantiate 100 copies of bcd_fadd to create a 100-digit BCD ripple-carry adder. Your adder should add two 100-digit BCD numbers (packed into 400-bit vectors) and a carry-in to produce a 100-digit sum and carry out.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
//False Verion module top_module( input [399:0] a, b, input cin, outputreg cout, outputreg [399:0] sum ); genvar i , j ; reg [99:0] temp_cout ; assign cout = temp_cout[99] ; generate bcd_fadd U0( a[3:0] , b[3:0] , cin , temp_cout[0] , sum[3:0]) ; for (i = 7 , j = 0; i < 400 ; i = i + 4 , j++) begin : name bcd_fadd U1( a[i:i-3] , b[i:i-3] , temp_cout[j] , sum[i:i-3]) ; end endgenerate endmodule
报错信息:Error (10170): Verilog HDL syntax error at top_module.v(12) near text: “,”; expecting “;”
You are given a 100-bit input vector in[99:0]. We want to know some relationships between each bit and its neighbour:
out_both: Each bit of this output vector should indicate whether both the corresponding input bit and its neighbour to the left are ‘1’. For example, out_both[98] should indicate if in[98] and in[99] are both 1. Since in[99] has no neighbour to the left, the answer is obvious so we don’t need to know out_both[99].
out_any: Each bit of this output vector should indicate whether any of the corresponding input bit and its neighbour to the right are ‘1’. For example, out_any[2] should indicate if either in[2] or in[1] are 1. Since in[0] has no neighbour to the right, the answer is obvious so we don’t need to know out_any[0].
out_different: Each bit of this output vector should indicate whether the corresponding input bit is different from its neighbour to the left. For example, out_different[98] should indicate if in[98] is different from in[99]. For this part, treat the vector as wrapping around, so in[99]‘s neighbour to the left is in[0].
//Flase vesion module top_module( input [15:0] a, b, c, d, e, f, g, h, i, input [3:0] sel, outputreg [15:0] out ); always @(*)begin case(sel) 4'b0000 : out = a ; 4'b0001 : out = b ; 4'b0010 : out = c ; 4'b0011 : out = d ; 4'b0100 : out = e ; 4'b0101 : out = f ; 4'b0110 : out = g ; 4'b0111 : out = h ; 4'b1000 : out = i ; default : out = 16'hFFFF ;//十六进制应该为4'hFFFF //踩过的坑 : out = 1 ; out = 0xFFFF ; out = 4'hFFFF endcase end endmodule
256-to-1 4-bit multiplexer
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.
Hint
With this many options, a case statement isn’t so useful.
Vector indices can be variable, as long as the synthesizer can figure out that the width of the bits being selected is constant. It’s not always good at this. An error saying “… is not a constant” means it couldn’t prove that the select width is constant. In particular, in[ sel*4+3 : sel*4 ] does not work. // verilog 索引不支持全为变量
Bit slicing (“Indexed vector part select”, since Verilog-2001) has an even more compact syntax.
1 2 3 4 5 6 7 8 9
module top_module( input [1023:0] in, input [7:0] sel, output [3:0] out ); assign out = in[sel * 4 + 3 : sel * 4] ;
endmodule
error : sel is not a constant File ;
1 2 3 4 5 6 7 8 9 10
//True module top_module( input [1023:0] in, input [7:0] sel, output [3:0] out ); assign out = in[sel * 4 +: 4] ;//从sel*4向上四位 endmodule
Arithmetic Circuits
3-bit binary adder
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.
module full_adder( input a , b , cin , output cout , sum ); assign cout= a & b | a & cin | b & cin ; assign sum = a ^ b ^ cin ; endmodule
Signed addition overflow
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.
1 2 3 4 5 6 7 8 9 10 11
//Flase vesion module top_module ( input [7:0] a, input [7:0] b, output [7:0] s, output overflow ); assign { overflow , s } = a + b ; //注意题中的signed overflow , 并不等于进位cout endmodule
module top_module( input a, input b, input c, output out );
// SOP form: Three prime implicants (1 term each), summed. // POS form: One prime implicant (of 3 terms) // In this particular case, the result is the same for both SOP and POS. // it's easier by using SOP assign out = (a | b | c); endmodule
4-variable
1 2 3 4 5 6 7 8 9
module top_module( input a, input b, input c, input d, output out ); assign out = (!b & !c) | (!a & !d) | (!a & b & c) | (a & c & d) ; endmodule
4-variable
1 2 3 4 5 6 7 8 9 10
module top_module( input a, input b, input c, input d, output out ); assign out = a | (!b & c) ; //用0去算!f更简单 endmodule
4-variable
1 2 3 4 5 6 7 8 9 10
//Stupid vesion module top_module( input a, input b, input c, input d, output out ); assign out = (!a & !b) & (c ^ d) | (!a & b) & !(c ^ d) | a & b & (c ^ d) | (a & !b) & !(c ^ d); endmodule
1 2 3 4 5 6 7 8 9
// Wise vesion module top_module( input a, input b, input c, input d, output out ); assign out = a ^ b ^ c ^ d ; endmodule
如果会奇偶校验便能一眼看出:abcd中有奇数个1,卡诺图为1 .反之为0.
Minimum SOP and POS
1 2 3 4 5 6 7 8 9 10 11
module top_module ( input a, input b, input c, input d, output out_sop, output out_pos ); assign out_sop = c & d | !a & !b & c ; assign out_pos = c & (!a | b) & (!b | d) ; endmodule