一、ringer(电话响铃)
问题描述:Suppose you are designing a circuit to control a cellphone’s ringer and vibration motor. Whenever the phone needs to ring from an incoming call (input ring), your circuit must either turn on the ringer (output ringer = 1) or the motor (output motor = 1), but not both. If the phone is in vibrate mode (input vibrate_mode = 1), turn on the motor. Otherwise, turn on the ringer.
Try to use only assign statements, to see whether you can translate a problem description into a collection of logic gates.
设计提示: When designing circuits, one often has to think of the problem “backwards”, starting from the outputs then working backwards towards the inputs. This is often the opposite of how one would think about a (sequential, imperative) programming problem, where one would look at the inputs first then decide on an action (or output). For sequential programs, one would often think “If (inputs are ___ ) then (output should be ___ )”. On the other hand, hardware designers often think “The (output should be ___ ) when (inputs are ___ )”.
The above problem description is written in an imperative form suitable for software programming (if ring then do this), so you must convert it to a more declarative form suitable for hardware implementation (assign ringer = ___). Being able to think in, and translate between, both styles is one of the most important skills needed for hardware design.
简述:非振动模式时,来电话(ring == 1)时响铃(ringer == 1);震动模式时(vibrate_mode == 1),来电话时震动(motor == 1)
用两个 assign 语句完成设计
不能用 if_else 语句,因为两种模式时并列关系,同时发生,而 if_else 是顺序执行,有先后关系。
module top_module (
input ring,
input vibrate_mode,
output ringer, // Make sound
output motor // Vibrate
);
assign ringer = ring & (~vibrate_mode); //不是震动模式,且来电话了(ring == 1)
assign motor = ring & vibrate_mode; //是震动模式,且来电话了(ring == 1)
endmodule
二、3 bit population count(计数电路)
问题描述:A “population count” circuit counts the number of '1’s in an input vector. Build a population count circuit for a 3-bit input vector.
module top_module(
input [2:0] in,
output [1:0] out );
//方法1,真值表可得
assign out[1] = in[0]&in[1] | in[1]&in[2] | in[0]&in[2];
//只要in有两位或以上为1,则out[1]为1
assign out[0] = in[0] ^ in[1] ^ in[2];
//assign out[0] = (~in[2] & ~in[1] & in[0]) | (~in[2] & in[1] & ~in[0]) | (in[2] & ~in[1] & ~in[0]) | (in[2] & in[1] & in[0]);的简化
//方法2
assign out = in[0]+in[1]+in[2];
//方法3
always @(*) begin
case (in)
3'd0: out = 2'd0;
3'd1: out = 2'd1;
3'd2: out = 2'd1;
3'd3: out = 2'd2;
3'd4: out = 2'd1;
3'd5: out = 2'd2;
3'd6: out = 2'd2;
3'd7: out = 2'd3;
endcase
end
endmodule
三、gates and vectors
问题描述:You are given a four-bit input vector in[3: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 (higher index) are ‘1’. For example, out_both[2] should indicate if in[2] and in[3] are both 1. Since in[3] has no neighbour to the left, the answer is obvious so we don’t need to know out_both[3].(每一位和它的前一位都是1)
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].(每一位和它的低一位有一个是1)
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[2] should indicate if in[2] is different from in[3]. For this part, treat the vector as wrapping around, so in[3]'s neighbour to the left is in[0].(每一位和它的前一位相同,且认为vector是循环的,即in[3]的前一位是in[1])
知识点:vector的选择和组合
//我的解
module top_module(
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different );
assign out_both = {(in[2]&in[3]) , (in[1]&in[2]) , (in[0]&in[1])};
assign out_any = {(in[3]|in[2]) , (in[2]|in[1]) , (in[1]|in[0])};
assign out_different = {(in[3]^in[0]) , (in[2]^in[3]) , (in[1]^in[2]) , (in[0]^in[1])};
endmodule
//答案
module top_module (
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different
);
// Use bitwise operators and part-select to do the entire calculation in one line of code
// in[3:1] is this vector: in[3] in[2] in[1]
// in[2:0] is this vector: in[2] in[1] in[0]
// Bitwise-OR produces a 3 bit vector. | | |
// Assign this 3-bit result to out_any[3:1]: o_a[3] o_a[2] o_a[1]
// Thus, each output bit is the OR of the input bit and its neighbour to the right:
// e.g., out_any[1] = in[1] | in[0];
// Notice how this works even for long vectors.
assign out_any = in[3:1] | in[2:0];
assign out_both = in[2:0] & in[3:1];
// XOR 'in' with a vector that is 'in' rotated to the right by 1 position: {in[0], in[3:1]}
// The rotation is accomplished by using part selects[] and the concatenation operator{}.
assign out_different = in ^ {in[0], in[3:1]};
endmodule
四、multiplexers(多路复用器)
1、2 to 1 multiplexer
问题描述:Create a one-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
module top_module (
input a,
input b,
input sel,
output out
);
//方法1
assign out = (sel & b) | (~sel & a); // Mux expressed as AND and OR
//方法2
assign out = sel ? b : a;
//当a,b是多元向量时方法1不再适用,只能使用三元运算
endmodule
2、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.
Expected solution length: Around 1–5 lines.
提示:
- 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[sel4+3 : sel4 ] does not work.
- Bit slicing (“Indexed vector part select”, since Verilog-2001) has an even more compact syntax.
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]; // 选择从索引“sel*4”开始,然后选择总宽度为 4 位,并增加 (+:) 索引号。
// assign out = in[sel*4+3 -: 4]; // 选择从索引“sel*4+3”开始,然后选择总宽度为 4 位,索引号递减 (-:)。
// Note: The width (4 in this case) must be constant.
endmodule
五、一位全加器
//我的
module add1 ( input a, input b, input cin, output sum, output cout );
wire [1:0] s = a + b + cin;
assign sum = s[0];
assign cout = s[1];
endmodule
//better one
module add1 ( input a, input b, input cin, output sum, output cout );
assign sum=a^b^cin;
assign cout=cout = a&b | a&cin | b&cin;
endmodule