Module cseladd
In this exercise, you are provided with the same module add16
as the previous exercise, which adds two 16-bit numbers with carry-in and produces a carry-out and 16-bit sum. You must instantiate three of these to build the carry-select adder, using your own 16-bit 2-to-1 multiplexer.
Connect the modules together as shown in the diagram below. The provided module add16
has the following declaration:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cout1,cout2,cout3;
wire [15:0]sum2,sum3;
add16 inst1(a[15:0],b[15:0],1'b0,sum[15:0],cout1);
add16 inst2(a[31:16],b[31:16],1'b0,sum2,cout2);
add16 inst3(a[31:16],b[31:16],1'b1,sum3,cout3);
assign sum[31:16]=cout1?sum3:sum2;
endmodule
这道题没啥说的,就最后用一个assign选择一下,比直接用always@要少几行代码量。
Module addsub
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
Use a 32-bit wide XOR gate to invert the b input whenever sub is 1. (This can also be viewed as b[31:0] XORed with sub replicated 32 times. See replication operator.). Also connect the sub input to the carry-in of the adder.
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [31:0] b_q;
wire cout;
assign b_q = b^{32{sub}}; //使用32位的异或门。
add16 a0(a[15:0],b_q[15:0],sub,sum[15:0],cout);
add16 a1(a[31:16],b_q[31:16],cout,sum[31:16],);
endmodule
注意下那个异或门,说的是sub信号要展宽到32bite。
Alwaysblock1
Build an AND gate using both an assign statement and a combinational always block. (Since assign statements and combinational always blocks function identically, there is no way to enforce that you're using both methods. But you're here for practice, right?...)
意思是使用组合逻辑块或者assign 写一个与门电路。
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
output wire out_assign,
output reg out_alwaysblock
);
assign out_assign = a & b ;
always @(*) begin
out_alwaysblock = a & b ;
end
endmodule
Alwaysblock2
在这道题中,前两个输出都是纯粹的组合逻辑,后面一个是组合逻辑经过时序寄存一拍输出。
// synthesis verilog_input_version verilog_2001
module top_module(
input clk,
input a,
input b,
output wire out_assign,
output reg out_always_comb,
output reg out_always_ff );
//-----------------------------------
assign out_assign=a^b;
//-----------------------------------
always@(*)begin
out_always_comb=a^b;
end
//-----------------------------------
always@(posedge clk)begin
out_always_ff<= out_always_comb;
end
endmodule
Always if
A bit of practice
Build a 2-to-1 mux that chooses between a and b. Choose b if both sel_b1 and sel_b2 are true. Otherwise, choose a. Do the same twice, once using assign statements and once using a procedural if statement.
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
assign out_assign=(sel_b1&sel_b2)?b:a;
always@(*)begin
if ((sel_b1&sel_b2)==1'b1)
out_always=b;
else
out_always=a;
end
endmodule
Always if2
Demonstration
The following code contains incorrect behaviour that creates a latch. Fix the bugs so that you will shut off the computer only if it's really overheated, and stop driving if you've arrived at your destination or you need to refuel.
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer = 0;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
else
keep_driving=0;
end
endmodule
这道题的意思是条件分支要完备,除非是特别需要所以故意的,否则尽量避免生成锁存器。
Always case
A bit of practice
Case statements are more convenient than if statements if there are a large number of cases. So, in this exercise, create a 6-to-1 multiplexer. When sel is between 0 and 5, choose the corresponding data input. Otherwise, output 0. The data inputs and outputs are all 4 bits wide.
Be careful of inferring latches (See.always_if2)
// synthesis verilog_input_version verilog_2001
module top_module (
input [2:0] sel,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output reg [3:0] out );//
always@(*) begin // This is a combinational circuit
case(sel)
3'd0: out=data0;
3'd1: out=data1;
3'd2: out=data2;
3'd3: out=data3;
3'd4: out=data4;
3'd5: out=data5;
default: out =0;
endcase
end
endmodule
写一段组合逻辑case语句,大于5的输出默认值0。