hdlbits网站:HDLBits (01xz.net)
verilog language部分:【hdlbits】个人学习交流分享(带答案)——verilog language部分-CSDN博客
正文:
Basic gates
basic gates这一块内容很简单,很多之前verilog language部分就做过,这部分直接放答案
wire
module top_module (
input in,
output out);
assign out=in;
endmodule
GND
module top_module (
output out);
assign out=1'b0;
endmodule
NOR
module top_module (
input in1,
input in2,
output out);
assign out=~(in1|in2);
endmodule
another gate
module top_module (
input in1,
input in2,
output out);
assign out=in1&(~in2);
endmodule
two gates
module top_module (
input in1,
input in2,
input in3,
output out);
wire a;
assign a=~(in1^in2);
assign out=a^in3;
endmodule
more logic gates
module top_module(
input a, b,
output out_and,
output out_or,
output out_xor,
output out_nand,
output out_nor,
output out_xnor,
output out_anotb
);
assign out_and=a&b;
assign out_or=a|b;
assign out_xor=a^b;
assign out_nand=~(a&b);
assign out_nor=~(a|b);
assign out_xnor=~(a^b);
assign out_anotb=a&(~b);
endmodule
7420 chip
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
truth tables
module top_module(
input x3,
input x2,
input x1, // three inputs
output f // one output
);
assign f=(x2&~x3)|(x1&x3);
endmodule
two-bit equality
module top_module ( input [1:0] A, input [1:0] B, output z );
assign z=(A==B)?1'b1:1'b0;
endmodule
simple circuit A
module top_module (input x, input y, output z);
assign z=(x^y)&x;
endmodule
simple circuit B
module top_module ( input x, input y, output z );
assign z=~(x^y);
endmodule
combine circuit A and B
module top_module (input x, input y, output z);
wire o1, o2, o3, o4;
A ia1 (x, y, o1);
B ib1 (x, y, o2);
A ia2 (x, y, o3);
B ib2 (x, y, o4);
assign z = (o1 | o2) ^ (o3 & o4);
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
ring or vibrate?
答案1:从输入条件思考,编写if else语句
module top_module (
input ring,
input vibrate_mode,
output ringer, // Make sound
output motor // Vibrate
);
always @(*)begin
if(ring)begin//来电
if(vibrate_mode)begin//振动模式,打开电机关闭铃声
motor=1;
ringer=0;
end
else begin//关闭振动模式,打开铃声关闭电机
motor=0;
ringer=1;
end
end
else begin//不来电
motor=0;
ringer=0;
end
end
endmodule
我们当然可以如上代码先查看条件和输入,寻找得到什么样的输出,即“输入→输出”的逻辑。
设计电路时,我们还可以“倒着”思考问题,从输出开始,向前寻找满足条件的输入,当得到这种输出时候,对应可以有那些情况的输入条件,就是“输出→输入”的思考逻辑。
module top_module (
input ring,
input vibrate_mode,
output ringer, // Make sound
output motor // Vibrate
);
assign ringer=(vibrate_mode==0&ring==1)?1:0;//当响铃声时候,输入要求是来电且关闭振动模式
assign motor=(vibrate_mode==1&ring==1)?1:0;//当开电机时候,输入要求是来电且开启振动模式
endmodule
这里assign语句就是“输出→输入”的思考逻辑。
thermostat
module top_module (
input too_cold,
input too_hot,
input mode,
input fan_on,
output heater,
output aircon,
output fan
);
assign heater=(too_cold==1&mode==1)?1:0;
assign aircon=(too_hot==1&mode==0)?1:0;
assign fan=fan_on|heater|aircon;//同上一题,三个assign是从输出结果寻找满足条件的输入
endmodule
3-bit population count
module top_module(
input [2:0] in,
output [1:0] out );
assign out=in[0]+in[1]+in[2];
endmodule
gates and vectors
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:0]&in[3:1];
assign out_any=in[2:0]|in[3:1];
assign out_different[2:0]=in[2:0]^in[3:1];
assign out_different[3]=in[3]^in[0];
endmodule
even longer vectors
module top_module(
input [99:0] in,
output [98:0] out_both,
output [99:1] out_any,
output [99:0] out_different );
assign out_both=in[98:0]&in[99:1];
assign out_any=in[98:0]|in[99:1];
assign out_different[98:0]=in[98:0]^in[99:1];
assign out_different[99]=in[99]^in[0];
endmodule
Multiplexers
2-to-1 multiplexers
module top_module(
input a, b, sel,
output out );
assign out=(sel)?b:a;
endmodule
2-to-1 bus multiplexers
module top_module(
input [99:0] a, b,
input sel,
output [99:0] out );
assign out=(sel)?b:a;
endmodule
9-to-1 multiplexers
module top_module(
input [15:0] a, b, c, d, e, f, g, h, i,
input [3:0] sel,
output [15:0] out );
always @(*)begin
case(sel)
4'd0:out=a;
4'd1:out=b;
4'd2:out=c;
4'd3:out=d;
4'd4:out=e;
4'd5:out=f;
4'd6:out=g;
4'd7:out=h;
4'd8:out=i;
default:out=16'b1111111111111111;
endcase
end
endmodule
256-to-1 multiplexers
module top_module(
input [255:0] in,
input [7:0] sel,
output out );
assign out=in[sel];//数据流写法,SEL=0 选择 IN[0],SEL=1 选择 IN[1],类推
endmodule
256-to-1 4-bit multiplexers
题目要求:创建一个 4 位宽、256:1 的多路复用器。256 个 4 位输入全部封装到一个 1024 位输入向量中。SEL=0 应选择 [3:0] 中的位,SEL=1 选择 [7:4] 中的位,SEL=2 选择 [11:8] 中的位,依此类推。
根据题目描述,结合上一题的数据流写法,很自然会想到这样写:
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out=in[4*sel+3:4*sel];
endmodule
从数据传输意思上是对的,但是verilog没有这样的语法,所以语法错误综合报错。
正确的写法可以这样写:
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out=in[sel*4+:4];//+号代表向上取,:后面4代表向上取共4位
endmodule
也可以写成拼接的形式,拼接形式算是比较原始不高级但是很有效的办法:
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out={in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4]};
endmodule
Arithmetic cirucits
half adder
module top_module(
input a, b,
output cout, sum );
assign{cout,sum}=a+b;
endmodule
full adder
module top_module(
input a, b, cin,
output cout, sum );
assign{cout,sum}=a+b+cin;
endmodule
3-bit binary adder
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
assign {cout[0],sum[0]}=a[0]+b[0]+cin;
assign {cout[1],sum[1]}=a[1]+b[1]+cout[0];
assign {cout[2],sum[2]}=a[2]+b[2]+cout[1];
endmodule
adder
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum);
wire a,b,c;
assign{a,sum[0]}=x[0]+y[0];
assign{b,sum[1]}=x[1]+y[1]+a;
assign{c,sum[2]}=x[2]+y[2]+b;
assign{sum[4],sum[3]}=x[3]+y[3]+c;
endmodule
signed addition overflow
这里需要介绍一点判断有符号数溢出的知识,判断两个有符号数运算后是否溢出,有多种办法,其中一种办法是这样的:
设有符号数A与B相加,A的符号位是As,B的符号位是Bs,运算结果符号位是Ss,则
V=(As&Bs&(~Ss))+((~As)&(~Bs)&Ss),V=0无溢出,V=1有溢出。
无溢出的结果,As、Bs、Ss全为0或者全为1,两种情况分别代入上式V均为0
有溢出,As=0、Bs=0、Ss=1或As=1、Bs=1、Ss=0,了;两种情况分别代入上式V均为1
关于溢出判断更多了解可参考: 2.2.4_加减运算和溢出判断_哔哩哔哩_bilibili
回到本题,补码最高位[7]位是符号位,所以代码如下:
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
); //
assign s=a+b;
assign overflow=(a[7]&b[7]&~s[7])|(~a[7]&~b[7]&s[7]);
endmodule
100-bit binary adder
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
assign{cout,sum}=a+b+cin;
endmodule
4-digit BCD adder
module top_module (
input [15:0] a, b,
input cin,
output cout,
output [15:0] sum );
wire c,d,e;
bcd_fadd bcd_fadd_1(a[3:0],b[3:0],cin,c,sum[3:0]);
bcd_fadd bcd_fadd_2(a[7:4],b[7:4],c,d,sum[7:4]);
bcd_fadd bcd_fadd_3(a[11:8],b[11:8],d,e,sum[11:8]);
bcd_fadd bcd_fadd_4(a[15:12],b[15:12],e,cout,sum[15:12]);
endmodule
Karnaugh Map to circuit
3-variable
module top_module(
input a,
input b,
input c,
output out );
assign out=a|c|b;
endmodule
4-variable
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out=(~a&~d)|(~b&~c)|(a&~b&d)|(b&c&d);
endmodule
4-variable
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out= a|(~b&c);
endmodule
4-variable
这种卡诺图,ab和cd是按照格雷码写的,里面的0和1全都不相邻,就是经典的各个元素异或,这是数电的知识。
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out=a^b^c^d;
endmodule
minimum SOP and POS
做这道题需要清楚SOP和POS,卡诺图化简时候,
SOP形式是找出所有当输出为1(最小项)的输入组合(最小项之和)
POS形式则是找出所有当输出为0(最大项)的输入组合(最大项之积)
具体可以参考:卡诺图化简及逻辑函数的规范范式:SOP与POS形式_sop和pos-CSDN博客
module top_module (
input a,
input b,
input c,
input d,
output out_sop,
output out_pos
);
assign out_sop=(c&d)|(~a&~b&c);
assign out_pos=c&(~a|b)&(~b|~c|d);
endmodule
Karnaugh Map
module top_module (
input [4:1] x,
output f );
assign f=(~x[1]&x[3])|(x[2]&x[4]);
endmodule
Karnaugh Map
module top_module (
input [4:1] x,
output f
);
assign f=(~x[2]&~x[4])|(~x[1]&x[3])|(x[2]&x[3]&x[4]);
endmodule
K-Map implemented with a multiplexer
题目描述:对于下面的Karnaugh图,给出使用一个4对1多路复用器和所需数量的2对1多路复用器的电路实现,但使用尽可能少的多路复用器。不允许使用任何其他逻辑门,必须使用 a 和 b 作为多路复用器选择器输入,如下面的 4 对 1 多路复用器所示。您要实现标记为 top_module 的部分,以便整个电路(包括 4 对 1 多路复用器)实现 K 映射。
因为ab是多路选择器的选择端,所以我们可以从ab入手分析
ab=00输出mux_in[0],就是卡诺图第一列,输出什么取决于cd,由卡诺图知c是1时候输出为1,c是0时候输出同d;
ab=01输出mux_in[1],就是卡诺图第二列,输出为0;
ab=10输出mux_in[2],就是卡诺图第四列,输出什么取决于d,d是1时候输出是0,d是0时候输出是1;
ab=11输出mux_in[3],就是卡诺图第三列,输出什么取决于cd,c是1时候输出取决于d,c是0时候输出是0;
module top_module (
input c,
input d,
output [3:0] mux_in
);
assign mux_in[0] = c?1:d;
assign mux_in[1] = 0;
assign mux_in[2] = d?0:1;
assign mux_in[3] = c?d:0;
endmodule