目录
1.Conditional ternary operator
4.Combinational for-loop: Vector reversal 2
5.Combinational for-loop: 255-bit population count
6.Generate for-loop: 100-bit binary adder 2
7.Generate for-loop: 100-digit BCD adder
2.5 More Verilog Features
1.Conditional ternary operator
Verilog has a ternary conditional operator ( ? : ) much like C:
(condition ? if_true : if_false)
This can be used to choose one of two values based on condition (a mux!) on one line, without using an if-then inside a combinational always block.
Examples:
(0 ? 3 : 5) // This is 5 because the condition is false. (sel ? b : a) // A 2-to-1 multiplexer between a and b selected by sel. always @(posedge clk) // A T-flip-flop. q <= toggle ? ~q : q; always @(*) // State transition logic for a one-input FSM case (state) A: next = w ? B : A; B: next = w ? A : B; endcase assign out = ena ? q : 1'bz; // A tri-state buffer ((sel[1:0] == 2'h0) ? a : // A 3-to-1 mux (sel[1:0] == 2'h1) ? b : c )
A Bit of Practice
Given four unsigned numbers, find the minimum. Unsigned numbers can be compared with standard comparison operators (a < b). Use the conditional operator to make two-way min circuits, then compose a few of them to create a 4-way min circuit. You'll probably want some wire vectors for the intermediate results.
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);//
// assign intermediate_result1 = compare? true: false;
assign min=a<b?(a<c?(a<d?a:d):(c<d?c:d)):(b<c?(b<d?b:d):(c<d?c:d));
endmodule
2.Reduction operators
You're already familiar with bitwise operations between two values, e.g., a & b or a ^ b. Sometimes, you want to create a wide gate that operates on all of the bits of one vector, like (a[0] & a[1] & a[2] & a[3] ... ), which gets tedious if the vector is long.
The reduction operators can do AND, OR, and XOR of the bits of a vector, producing one bit of output:
& a[3:0] // AND: a[3]&a[2]&a[1]&a[0]. Equivalent to (a[3:0] == 4'hf) | b[3:0] // OR: b[3]|b[2]|b[1]|b[0]. Equivalent to (b[3:0] != 4'h0) ^ c[2:0] // XOR: c[2]^c[1]^c[0]
These are unary operators that have only one operand (similar to the NOT operators ! and ~). You can also invert the outputs of these to create NAND, NOR, and XNOR gates, e.g., (~& d[7:0]).
A Bit of Practice
Parity checking is often used as a simple method of detecting errors when transmitting data through an imperfect channel. Create a circuit that will compute a parity bit for a 8-bit byte (which will add a 9th bit to the byte). We will use "even" parity, where the parity bit is just the XOR of all 8 data bits.
module top_module (
input [7:0] in,
output parity);
assign parity=^in;
endmodule
3.Reduction: Even wider gates
Build a combinational circuit with 100 inputs, in[99:0].
There are 3 outputs:
- out_and: output of a 100-input AND gate.
- out_or: output of a 100-input OR gate.
- out_xor: output of a 100-input XOR gate.
-
module top_module( input [99:0] in, output out_and, output out_or, output out_xor ); assign out_and=∈ assign out_or=|in; assign out_xor=^in; endmodule
4.Combinational for-loop: Vector reversal 2
Given a 100-bit input vector [99:0], reverse its bit ordering.
module top_module(
input [99:0] in,
output [99:0] out
);
generate
genvar i;
for (i=0;i<100;i=i+1)begin:reverse
assign out[99-i]=in[i];
end
endgenerate
endmodule
5.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.
module top_module(
input [254:0] in,
output [7:0] out );
integer i;
reg [7:0]count;
always@(*)begin
count = 1'b0;
for(i=0;i<255;i=i+1)begin
if (in[i])
count=count+1'b1;
else
count=count;
end
end
assign out=count;
endmodule
6.Generate for-loop: 100-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.
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
integer i;
always@(*)begin
for (i=0;i<100;i=i+1)begin
if (i==0)begin
sum[0]=cin^a[0]^b[0];
cout[0]=(cin&a[0] )| (cin&b[0]) | (a[0]&b[0]);
end
else begin
sum[i]=cout[i-1]^a[i]^b[i];
cout[i]=(cout[i-1]&a[i] )| (cout[i-1]&b[i]) | (a[i]&b[i]);
end
end
end
endmodule
7.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.
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.
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire [99:0]count1;
generate
genvar i;
for (i=0;i<100;i=i+1)begin:add
if (i==0)begin
bcd_fadd bcd_fadd_1(
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.cout(count1[0]),
.sum(sum[3:0])
);
end
else begin
bcd_fadd bcd_fadd_2(
.a(a[4*i+3:4*i]),
.b(b[4*i+3:4*i]),
.cin(count1[i-1]),
.cout(count1[i]),
.sum(sum[4*i+3:4*i])
);
end
end
assign cout=count1[99];
endgenerate
endmodule