Verilog基础(四):组合逻辑
电路 (Circuits)
组合逻辑 (Combinational Login)
基础门电路
- Wire类型
实现如下电路:
- Module Declaraction
module top_module (
input in,
output out);
- Solution
module top_module (
input in,
output out);
assign out =in;
endmodule
- 接地 – GND
实现如下电路:
- Module Declaraction
module top_module (
output out);
- Solution
module top_module (
output out);
assign out = 'b0;
endmodule
- 或非门 (NOR)
实现如下电路:
[外链图片转存中…(img-rrC5KOrq-1738668675073)]
- Module Declaraction
module top_module (
input in1,
input in2,
output out);
- Solution
module top_module (
input in1,
input in2,
output out);
assign out = ~(in1|in2);
endmodule
- 其他的门
实现如下电路:
- Module Declaraction
module top_module (
input in1,
input in2,
output out);
- Solution
module top_module (
input in1,
input in2,
output out);
assign out = in1&~in2;
endmodule
- 两个门
实现如下电路:
- Module Declaraction
module top_module (
input in1,
input in2,
input in3,
output out);
- Solution
module top_module (
input in1,
input in2,
input in3,
output out);
wire out1;
assign out1 = ~(in1^in2);
assign out = in3^ out1;
endmodule
- 7420模块
创建如下电路:
- Module Declaraction
module top_module (
input p1a, p1b, p1c, p1d,
output p1y,
input p2a, p2b, p2c, p2d,
output p2y );
- Solution
module top_module (
input p1a, p1b, p1c, p1d,
output p1y,
input p2a, p2b, p2c, p2d,
output p2y );
assign p1y = ~(p1a&p1b&p1c&p1d);
assign p2y = ~(p2a&p2b&p2c&p2d);
endmodule
- 小练习 – Two-bit equality
若A==B则输出1,否则输出0
- Module Declaraction
module top_module ( input [1:0] A, input [1:0] B, output z );
- Solution
module top_module ( input [1:0] A, input [1:0] B, output z );
assign z = ((A[1]==B[1])&&(A[0]==B[0]))?1:0;
endmodule
- 简单电路A
实现一个模块,具有z = (x^y) & x
功能
- Module Declaraction
module top_module (input x, input y, output z);
- Solution
module top_module (input x, input y, output z);
assign z = (x^y)&x;
endmodule
- 简单电路B
电路B可以通过以下模拟波形来描述:
[外链图片转存中…(img-8UTGCuab-1738668675074)]
- Module Declaraction
module top_module ( input x, input y, output z );
- Solution
module top_module ( input x, input y, output z );
assign z = ~(x^y);
endmodule
- 组合电路AB
通过电路A,B构建如下电路:
[外链图片转存中…(img-XRsWORya-1738668675074)]
- Module Declaraction
module top_module ( input x, input y, output z );
- Solution
module top_module (input x, input y, output z);
wire z1,z2,z3,z4,out1,out2;
A ins1(x,y,z1);
B ins2(x,y,z2);
A ins3(x,y,z3);
B ins4(x,y,z4);
assign out1 = z1 | z2;
assign out2 = z3 & z4;
assign z = out1 ^ out2;
endmodule
module A(input x, input y, output z);
assign z = (x^y) & x;
endmodule
module B ( input x, input y, output z );
assign z = ~(x^y);
endmodule
- 恒温器
实现一个加热/冷却恒温器控制器.
执行一个电路,根据需要打开和关闭加热器、空调和鼓风机风扇.
恒温器可以处于两种模式之一:加热(mode=1)和冷却(mode=0).
在加热模式下,当加热器太冷(too_cold=1)时,打开加热器,但不要使用空调.在冷却模式下,当空调太热(too_hot=1)时打开空调,但不要打开加热器.
当加热器或空调打开时,也打开风扇使空气循环.
此外,即使加热器和空调关闭,用户也可以请求风扇打开(fan_on=1).
尝试只使用assign语句,以查看是否可以将问题描述转换为逻辑门集合.
- Module Declaraction
module top_module (
input too_cold,
input too_hot,
input mode,
input fan_on,
output heater,
output aircon,
output fan
);
- Solution
module top_module (
input too_cold,
input too_hot,
input mode,
input fan_on,
output heater,
output aircon,
output fan
);
always @(*) begin
if(fan_on == 1) begin
fan = 1;
end
else begin
fan = 0;
end
if(mode == 1) begin
heater = mode;
if(too_cold) begin
heater = 1;
fan = 1;
aircon = 0;
end
else begin
heater = 0;
aircon = 0;
end
end
else begin
if(too_hot) begin
aircon = 1;
fan = 1;
heater = 0;
end
else begin
aircon = 0;
heater = 0;
end
end
end
endmodule
- 3位计数器
计算3位vector中1的个数
- Module Declaraction
module top_module(
input [2:0] in,
output [1:0] out );
- Solution
module top_module(
input [2:0] in,
output [1:0] out );
reg [1:0]num;
integer i;
always @(*) begin
num = 0;
for(i=0;i<3;i=i+1) begin
if(in[i] == 1) begin
num = num + 2'b1;
end
end
end
assign out = num;
endmodule
- 门与容器
给定4位vector,请给出每个位与其相临位之间的关系.
-
out_both
: 判断相应位与其左临位是否均为1,不考虑in[3]
-
out_any
: 判断相应位与其右临位是否含有’1’,不考虑in[0]
-
out_different
: 判断相应位与其左临位是否不同,in[3[
是in[0]
的左临位 -
Module Declaraction
module top_module(
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different );
- Solution
module top_module(
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different );
integer i;
reg [2:0]both;
reg [3:1]any;
reg [3:0]different;
always @(*) begin
both = 0;
any = 0;
different = 0;
for(i=0;i<3;i=i+1) begin
if((in[i]&in[i+1]) == 1) begin
both[i] = 1;
end
end
for(i=1;i<4;i=i+1) begin
if((in[i]|in[i-1]) == 1) begin
any[i] = 1;
end
end
for(i=0;i<4;i=i+1) begin
if(i<3) begin
if(in[i]^in[i+1]) begin
different[i] = 1;
end
end
else begin
if(in[3]^in[0]) begin
different[3] = 1;
end
end
end
end
assign out_both = both;
assign out_any[3:1] = any[3:1];
assign out_different = different;
endmodule
- 更长的数组
给定4位vector,请给出每个位与其相临位之间的关系.
-
out_both
: 判断相应位与其左临位是否均为1,不考虑in[3]
-
out_any
: 判断相应位与其右临位是否含有’1’,不考虑in[0]
-
out_different
: 判断相应位与其左临位是否不同,in[3[
是in[0]
的左临位 -
Module Declaraction
module top_module(
input [99:0] in,
output [98:0] out_both,
output [99:1] out_any,
output [99:0] out_different );
- Solution
module top_module (
input [99:0] in,
output [98:0] out_both,
output [99:1] out_any,
output [99:0] out_different
);
// See gatesv for explanations.
assign out_both = in & in[99:1];
assign out_any = in[99:1] | in ;
assign out_different = in ^ {in[0], in[99:1]};
endmodule
多路选择器(Multiplexers)
- 2选1多路选择器
创建一个1位宽的2对1多路选择器.当sel=0时,选择a;当sel=1时,选择b.
- Module Declaraction
module top_module(
input a, b, sel,
output out );
- Solution
module top_module (
input a,
input b,
input sel,
output out
);
assign out = (sel & b) | (~sel & a); // Mux expressed as AND and OR
// Ternary operator is easier to read, especially if vectors are used:
// assign out = sel ? b : a;
endmodule
- 2选1总线选择器
创建一个100位宽的2对1多路选择器.当sel=0时,选择a;当sel=1时,选择b.
- Module Declaraction
module top_module(
input [99:0] a, b,
input sel,
output [99:0] out );
- Solution
module top_module (
input [99:0] a,
input [99:0] b,
input sel,
output [99:0] out
);
assign out = sel ? b : a;
// The following doesn't work. Why?
// assign out = (sel & b) | (~sel & a);
endmodule
- 9选1多路选择器
创建一个16位宽的9对1多路选择器.sel=0选择a,sel=1选择b等.对于未使用的情况(sel=9到15),将所有输出位设置为“1”.
- Module Declaraction
module top_module(
input [15:0] a, b, c, d, e, f, g, h, i,
input [3:0] sel,
output [15:0] out );
- Solution
module top_module (
input [15:0] a,
input [15:0] b,
input [15:0] c,
input [15:0] d,
input [15:0] e,
input [15:0] f,
input [15:0] g,
input [15:0] h,
input [15:0] i,
input [3:0] sel,
output logic [15:0] out
);
// Case statements can only be used inside procedural blocks (always block)
// This is a combinational circuit, so use a combinational always @(*) block.
always @(*) begin
out = '1; // '1 is a special literal syntax for a number with all bits set to 1.
// '0, 'x, and 'z are also valid.
// I prefer to assign a default value to 'out' instead of using a
// default case.
case (sel)
4'h0: out = a;
4'h1: out = b;
4'h2: out = c;
4'h3: out = d;
4'h4: out = e;
4'h5: out = f;
4'h6: out = g;
4'h7: out = h;
4'h8: out = i;
endcase
end
endmodule
- 256选1多路选择器
创建一个1位宽、256对1的多路选择器.256个输入全部打包成一个256位输入vector.sel=0选择in[0],sel=1选择in[1],sel=2选择in[2]等等.
- Module Declaraction
module top_module(
input [255:0] in,
input [7:0] sel,
output out );
- Solution
module top_module (
input [255:0] in,
input [7:0] sel,
output out
);
// Select one bit from vector in[]. The bit being selected can be variable.
assign out = in[sel];
endmodule
- 256选1 4位选则器
创建一个4位宽、256对1的多路选择器.sel=0应选择in[3:0]
,sel=1选择in[7:4]
,sel=2选择in[11:8]
等.
- Module Declaraction
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
- Solution
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
reg [7:0]index;
assign out[3:0] = in[4*sel+:4];
endmodule
运算电路
- 半加器
创建一个半加器,对两个位做加法并输出结果与进位.
- Module Declaraction
module top_module(
input a, b,
output cout, sum );
- Solution
module top_module(
input a, b,
output cout, sum );
assign {cout,sum} = a + b;
endmodule
- 全加器
创建一个全加器,对两位及进位做加法,输出结果与进位
- Module Declaraction
module top_module(
input a, b, cin,
output cout, sum );
- Solution
module top_module(
input a, b, cin,
output cout, sum );
assign {cout,sum} = a + b + cin;
endmodule
- 3位加法器
创建一个三位全加器,把每位相加的进位都输出出来.
- Module Declaraction
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
- Solution
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
FullAdder ins1(a[0],b[0],cin,cout[0],sum[0]);
FullAdder ins2(a[1],b[1],cout[0],cout[1],sum[1]);
FullAdder ins3(a[2],b[2],cout[1],cout[2],sum[2]);
endmodule
module FullAdder(
input a, b, cin,
output cout, sum
);
assign {cout, sum} = a + b + cin;
endmodule
-adder练习
实现如下电路:
- Module Declaraction
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum);
- Solution
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum
);
// This circuit is a 4-bit ripple-carry adder with carry-out.
assign sum = x+y; // Verilog addition automatically produces the carry-out bit.
// Verilog quirk: Even though the value of (x+y) includes the carry-out, (x+y) is still considered to be a 4-bit number (The max width of the two operands).
// This is correct:
// assign sum = (x+y);
// But this is incorrect:
// assign sum = {x+y}; // Concatenation operator: This discards the carry-out
endmodule
- 溢出检测
假设您有两个8位的补码,A[7:0]和B[7:0].这些数字加在一起产生s[7:0].还要计算是否发生了(有符号的)溢出.
- Module Declaraction
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
);
- Solution
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
);
EightBitsAdder ins(a, b, s, overflow);
endmodule
module FullAdder(
input a, b, cin,
output sum, cout
);
assign {cout, sum} = a + b + cin;
endmodule
module EightBitsAdder(
input [7:0] x,
input [7:0] y,
output [7:0] s,
output overflow
);
wire [7:0] cout1;
FullAdder ins0(x[0],y[0],0,s[0],cout1[0]);
FullAdder ins1(x[1],y[1],cout1[0],s[1],cout1[1]);
FullAdder ins2(x[2],y[2],cout1[1],s[2],cout1[2]);
FullAdder ins3(x[3],y[3],cout1[2],s[3],cout1[3]);
FullAdder ins4(x[4],y[4],cout1[3],s[4],cout1[4]);
FullAdder ins5(x[5],y[5],cout1[4],s[5],cout1[5]);
FullAdder ins6(x[6],y[6],cout1[5],s[6],cout1[6]);
FullAdder ins7(x[7],y[7],cout1[6],s[7],cout1[7]);
always @(*) begin
if(cout1[7]^cout1[6]) begin
overflow = 1;
end
else begin
overflow = 0;
end
end
endmodule
- 100位加法器
创建一个100位加法器.
- Module Declaraction
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
- Solution
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
assign {cout,sum} = a+b+cin;
endmodule
- BCD加法器
您将获得一个BCD(二进制编码十进制)一位加法器,名为BCD_fadd,它对两个BCD数字及进位做加法,产生一个和与进位.
module bcd_fadd {
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );
创建一个4BCD位加法器.
- Module Declaraction
module top_module(
input [15:0] a, b,
input cin,
output cout,
output [15:0] sum );
- Solution
module top_module (
input [15:0] a, b,
input cin,
output cout,
output [15:0] sum
);
wire [3:0] inter_cout;
bcd_fadd bcd_fadd0_inst
(
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.cout(inter_cout[0]),
.sum(sum[3:0])
);
genvar i;
generate
for (i = 1; i <=3; i = i + 1) begin: gen_bcd_adders
bcd_fadd bcd_fadd_insts
(
.a(a[4*(i+1)-1 : 4*i]),
.b(b[4*(i+1)-1 : 4*i]),
.cin(inter_cout[i-1]),
.cout(inter_cout[i]),
.sum(sum[4*(i+1)-1 : 4*i])
);
end
endgenerate
assign cout = inter_cout[3];
endmodule