HDLBits 答案汇总(持续更新)
目录
Vectors
Vectors in more detals
Vector part select
Bitewise operators
four input gates
Vector concatenation operations
Replication operators
More replication
Module
Three modules
Modules and vectors
Add1
Adder 2
Carry-select adder(Module cseladd)
Adder subtractor(Module addsub)
Vectors


Vectors in more detals


Vector part select
hint: 赋值的左右两侧都可以对矢量进行部分选择。

Bitewise operators
Hint:
按位布尔运算符:&,|,^,~
逻辑布尔运算符:&&,||,!


four input gates
hint: 矢量的按位布尔运算在矢量前加上布尔运算符即可。


Vector concatenation operations
Hint: 位宽必须进行标注,11必须标为 2'd11,才可以。
分号;必须是英文状态下的,而不是;中文状态下的。

module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );
assign {w[7:0]} = {a[4:0], b[4:2]};
assign {x[7:0]} = {b[1:0], c[4:0], d[4]};
assign {y[7:0]} = {d[3:0], e[4:1]};
assign {z[7:0]} = {e[0], f[4:0], 2'b11};
11. //second way
13. //assign {w, x, y, z} = {a, b, c, d, e, f, 2'b11};
endmodule
Replication operators
Hint: sign bit 符号位进行扩展保留,其他位保持不变即可。

module top_module (
input [7:0] in,
output [31:0] out );
assign out = {{24{in[7]}}, in [7:0]};
//second way
//assign out = {{24{in[7]}}, in};
endmodule
More replication
hint:结合矢量的按位布尔运算,连接符{},复制操作,3种操作复合。

module top_module (
input a, b, c, d, e,
output [24:0] out );
assign out = ~{{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}} ^ {5{a,b,c,,d,e}};
endmodule
Module
hint:
module top_module ( input a, input b, output out );
mod_a instance1 (a, b, out); //根据mod_a模块的输入输出声明(需要提前声明,题中给了)从左向右对应来写top_module的输入输出口。
//second way
//mod_a instance1 (.in1(a), .in2(b), .out(out));
endmodule
Connecting ports by name
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a instance1 (.out1(out1), .out2(out2), .in1(a), .in2(b), .in3(c), .in4(d));//括号外是实例化模块的接口,括号内是外界的接口
//second way
//mod_a(.out1(out1), .out2(out2), .in1(a), .in2(b), .in3(c), .in4(d));
//mod_a不进行命名也可以,不要忘了英文的句号. 而不是中文的
endmodule
Three modules
solution 1
module top_module ( input clk, input d, output q );
wire w1;
wire w2;
my_dff dff1(clk,d,w1);//括号内都是实例化模块之外的接口,实例化模块的接口顺序已经定义
//好,一一对应即可。
my_dff dff2(clk,w1,w2);
my_dff dff3(clk,w2,q);
endmodule
solution 2:
module top_module (
input clk,
input d,
output q
);
wire a, b; // Create two wires. I called them a and b.
// Create three instances of my_dff, with three different instance names (d1, d2, and d3).
// Connect ports by position: ( input clk, input d, output q)
my_dff d1 ( clk, d, a );
my_dff d2 ( clk, a, b );
my_dff d3 ( clk, b, q );
endmodule
Modules and vectors
solution:
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0] w1;
wire [7:0] w2;
wire [7:0] w3;
my_dff8 d1(clk,d,w1);
my_dff8 d2(clk,w1,w2);
my_dff8 d3(clk,w2,w3);
always @(*) begin
case(sel)
2'b00:
q=d;
2'b01:
q=w1;
2'b10:
q=w2;
2'b11:
q=w3;
endcase
end
endmodule
Add1
solution 1
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire w1;
add16 add1(a[15:0],b[15:0],1'b0,sum[15:0],w1);//注意是a[15:0],而不是[15:0] a。
add16 add2(a[31:16],b[31:16],w1,sum[31:16], );//不连接的接口直接空下就行,其前面的,可
11. //以不加。
13. endmodule
solution 2
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire w1;
add16 add1(
.a(a[15:0]),
.b(b[15:0]),
.cin(1'b0),
.sum(sum[15:0]),
.cout(w1)
);
add16 add2(
.a(a[31:16]),
.b(b[31:16]),
.cin(w1),
.sum(sum[31:16]),
.cout( )
);
23. endmodule
solution 3
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire w1,w2;
wire [15:0] low_out;
wire [15:0] high_out;
add16 add1(a[15:0],b[15:0],0,low_out,w1);//这个地方的0,可以直接写0,或者写成1'b0
add16 add2(a[31:16],b[31:16],w1,high_out,w2);
assign sum = {high_out, low_out};
17. endmodule
solution 4
将solution3中改为按名称连接即可。
Adder 2
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire w1;//分号;必须使用英文状态下的,不然可能会在其他地方报错
add16 block1 (a[15:0],b[15:0],1'b0,sum[15:0],w1);
add16 block2 (a[31:16],b[31:16],w1,sum[31:16]);
11. endmodule
13. module add1 ( input a, input b, input cin, output sum, output cout );
assign {cout,sum} = a + b + cin;//不需要再定义a,b,c等,在add16中已经对应过了,只需要对sum和cout定义即可,可以参考向量的拼接内容
16. endmodule
Carry-select adder(Module cseladd)
提前加法进位器,用资源换速度
将一个额外的新建第一个16位全加法电路加入系统中,并分别完成进位为0和1的情况下的运算操作;然后将第一个全加法电路的 cout 输出端与一个2选1 多路复用电路相连,并利用该复用电路的功能选择并输出对应第二个全加法电路在特定进位条件下的运算结果。
这样一来,在运算过程中实现了对多个全加法电路运算过程的有效同步。

solution1
按位置
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire [15:0] highout0;
wire [15:0] highout1;
wire cout;
add16 low(a[15:0],b[15:0],0,sum[15:0],cout);
add16 high0(a[31:16],b[31:16],0,highout0);
add16 high1(a[31:16],b[31:16],1,highout1);
assign sum[31:16]=cout? highout1:highout0;//数据选择器的描述
endmodule
solution 2
按名称
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cout_out;
wire [15:0] high0;
wire [15:0] high1;//在声明线网时,必须进行位宽的设置,否则默认为 1 bit
add16 low(
.a(a[15:0]),
.b(b[15:0]),
.cin(1'b0),
.sum(sum[15:0]),
.cout(cout_out )
);
add16 high_out0(
.a(a[31:16]),
.b(b[31:16]),
.cin(1'b0),
.sum(high0),
.cout( ) //没有用的管脚可以直接不声明
);
add16 high_out1(
.a(a[31:16]),
.b(b[31:16]),
.cin(1'b1),
.sum(high1),
.out( )
);
assign sum[31:16] = cout_out?high1:high0;//注意high1和high0之间用的:连接
35. endmodule
Adder subtractor(Module addsub)
题目:
关键点:采用32位宽的XOR门,在sub信号为1的情况下翻转b输入。
问题:如何用Verilog实现这一功能?
解答:因为Verilog中没有直接的逻辑异或操作符(即只能执行两位的信息处理),所以必须利用按位布尔运算符^来进行操作。
具体来说,在将32位输入b与32位sub信号进行异或操作后(即计算b ^ sub),每次只能处理两位信息并执行相应的布尔操作。
因此当sub信号为1时(即{32{sub}}),计算结果等价于对b逐位取反(即~b)。
而加1的操作则由cin端子与sub端子相连来控制;当sub信号为0时(即{32{0}}),异或操作不会对b产生任何影响。
solution1 按位置
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [31:0] b_out;
wire cout_out;
assign b_out = b ^ {32{sub}};
add16 low(a[15:0],b_out[15:0],sub,sum[15:0],cout_out);
add16 high(a[31:16],b_out[31:16],cout_out,sum[31:16]);
endmodule
solution2 按名称
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [31:0] b_out;//将b_out直接声明为32bit数据,在下面时可以用[31:16],[15:0]区别
wire cout_out;
assign b_out = b ^ {32{sub}};
add16 low(
.a(a[15:0]),
.b(b_out[15:0]),
.cin(sub),
.sum(sum[15:0]),
.cout(cout_out)
);
add16 high(
.a(a[31:16]),
.b(b_out[31:16]),
.cin(cout_out),
.sum(sum[31:16])
);
endmodule
