前言
-
之前的文章《如何学习verilog,如何快速入门?》中提到了verilog学习,推荐了一个可以练习的网站:hdlbits网站,那自己也玩玩这个网站。
-
这篇文章,是接着《verilog练习:hdlbits网站上的做题笔记(3)》写的!
3. Circuits
3.1 Combinational Logic
3.1.1 Basic Gates
3.1.1.1 Wire(Exams/m2014 q4h)
module top_module (
input in,
output out);
assign out = in;
endmodule
3.1.1.2 GND(Exams/m2014 q4i)
module top_module (
output out);
assign out = 1'b0;
endmodule
3.1.1.3 NOR(Exams/m2014 q4e)
module top_module (
input in1,
input in2,
output out);
assign out = ~(in1|in2);
endmodule
3.1.1.4 Another gate(Exams/m2014 q4f)
module top_module (
input in1,
input in2,
output out);
assign out = in1&(~in2);
endmodule
3.1.1.5 Two gates(Exams/m2014 q4g)
module top_module (
input in1,
input in2,
input in3,
output out);
assign out = (in1 ~^ in2)^in3;
endmodule
3.1.1.6 More logic gates(Gates)
There are 7 outputs, each with a logic gate driving it:
out_and: a and b
out_or: a or b
out_xor: a xor b
out_nand: a nand b
out_nor: a nor b
out_xnor: a xnor b
out_anotb: a and-not b
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
3.1.1.7 7420 chip(7420)
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
3.1.1.8 Truth tables(Truthtable1)
3-8译码器
module top_module(
input x3,
input x2,
input x1, // three inputs
output f // one output
);
// assign f = x3 & x1 | x2 & x1 | ~x3 & x2;
always@(*)begin
case({x3,x2,x1})
3'b000 : f = 0;
3'b001 : f = 0;
3'b010 : f = 1;
3'b011 : f = 1;
3'b100 : f = 0;
3'b101 : f = 1;
3'b110 : f = 0;
3'b111 : f = 1;
endcase
end
endmodule
3.1.1.9 Two-bit equality(Mt2015 eq2)
Create a circuit that has two 2-bit inputs A[1:0] and B[1:0], and produces an output z. The value of z should be 1 if A = B, otherwise z should be 0.
module top_module ( input [1:0] A, input [1:0] B, output z );
assign z = A==B?1:0;
endmodule
3.1.1.10 Simple circuit A(Mt2015 q4a)
z = (x^y) & x
module top_module (input x, input y, output z);
assign z = (x^y) & x;
endmodule
3.1.1.11 Simple circuit B(Mt2015 q4b)
module top_module ( input x, input y, output z );
assign z = x ~^ y;
endmodule
3.1.1.12 Combine circuits A and B(Mt2015 q4)
module top_module (input x, input y, output z);
wire z1,z2;
assign z1 = (x^y) & x;
assign z2 = x ~^ y;
assign z = (z1 | z2)^(z1 & z2);
endmodule
3.1.1.13 Ring or vibrate?(Ringer)
传入响铃信号时,如果处于振动状态则传入
module top_module (
input ring,
input vibrate_mode,
output ringer, // Make sound
output motor // Vibrate
);
assign ringer = (ring & ~vibrate_mode)?1:0;
assign motor = (ring & vibrate_mode)?1:0;
endmodule
3.1.1.14 Thermostat(Thermostat)
恒温器可以采用以下两种模式之一:加热(mode = 1)和冷却(mode = 0)。在加热模式下,当温度太低(too_cold = 1)时请打开加热器,但不要使用空调。在制冷模式下,当温度过高时(too_hot = 1)打开空调,但不要打开加热器。当加热器或空调打开时,还要打开风扇以使空气流通。此外,即使加热器和空调关闭,用户也可以要求风扇打开(fan_on = 1)。
尝试仅使用assign语句,以查看是否可以将问题描述转换为逻辑门的集合。
module top_module (
input too_cold,
input too_hot,
input mode,
input fan_on,
output heater,
output aircon,
output fan
);
assign heater = mode & too_cold;
assign aircon = ~mode & too_hot;
assign fan = fan_on|heater|aircon;
endmodule
3.1.1.15 3-bit population count(Popcount3)
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 );
integer i;
always@(*)begin
out = 2'b00;
for(i=0;i<3;i=i+1)begin
if(in[i]==1'b1)
out = out + 1'b1;
else
out = out;
end
end
endmodule
3.1.1.16 Gates and vectors(Gatesv)
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]. 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].
- 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].
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[3]&in[2]},{in[2]&in[1]},{in[1]&in[0]}};
assign out_any = {{in[3]|in[2]},{in[2]|in[1]},{in[1]|in[0]}};
assign out_different = {{in[3]^in[0]},{in[3]^in[2]},{in[2]^in[1]},{in[1]^in[0]}};
endmodule
//第二种方法:第一反应真的不是这个!
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[3:1] & in[2:0];
assign out_any = in[3:1] | in[2:0];
assign out_different = {in[0], in[3:1]} ^ in;
endmodule
3.1.1.17 Even longer vectors(Gatesv100)
在上一题的基础上扩展了
module top_module(
input [99:0] in,
output [98:0] out_both,
output [99:1] out_any,
output [99:0] out_different );
integer i;
always@(*)begin
for(i=0;i<100;i=i+1)begin
if(i==99)
out_different[i] = {in[i]^in[0]};
else begin
out_both[i] = {{in[i+1]&in[i]}};
out_any[i+1]={in[i+1]|in[i]};
out_different[i] = {in[i+1]^in[i]};
end
end
end
endmodule
//第二种方法:第一反应真的不是这个!
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[99:1] & in[98:0];
assign out_any = in[99:1] | in[98:0];
assign out_different = {in[0], in[99:1]} ^ in;
endmodule
3.1.2 Multiplexers
3.1.2.1 2-to-1 multiplexer(Mux2to1)
Create a one-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
module top_module(
input a, b, sel,
output out );
//assign out = sel?b:a;
assign out = (~sel & a)|(sel & b);//这种写法是二选一多路选择器的本质!
endmodule
3.1.2.2 2-to-1 bus multiplexer(Mux2to1v)
Create a 100-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b
3.1.2.3 9-to-1 multiplexer(Mux9to1v)
Create a 16-bit wide, 9-to-1 multiplexer. sel=0 chooses a, sel=1 chooses b, etc. For the unused cases (sel=9 to 15), set all output bits to ‘1’.
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)
'd0:out=a;
'd1:out=b;
'd2:out=c;
'd3:out=d;
'd4:out=e;
'd5:out=f;
'd6:out=g;
'd7:out=h;
'd8:out=i;
default:out='hffff;
endcase
end
endmodule
3.1.2.4 256-to-1 multiplexer(Mux256to1)
Create a 1-bit wide, 256-to-1 multiplexer. The 256 inputs are all packed into a single 256-bit input vector. sel=0 should select in[0], sel=1 selects bits in[1], sel=2 selects bits in[2], etc.
Expected solution length: Around 1 line
//提示一行完成(本来想着用循环语句的,结果还可以这样!)
module top_module(
input [255:0] in,
input [7:0] sel,
output out );
assign out = in[sel];
endmodule
3.1.2.5 256-to-1 4-bit multiplexer(Mux256to1v)
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.
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
这一题有意思!本来想着是用下面一行代码完事,结果编译不过去!
assign out=in[(sel*4+3):sel*4];
于是乎,通过尝试,发现下面这种方式可以!
assign out = {in[sel * 4 + 3], in[sel * 4 + 2], in[sel * 4 + 1], in[sel * 4]};
但是,这还是不够!于是又通过检索,发现还有种高大上的写法!
//assign out=in[(sel*4+3):sel*4];(错误的写法)
//assign out = {in[sel * 4 + 3], in[sel * 4 + 2], in[sel * 4 + 1], in[sel * 4]};
assign out = in[sel*4+:4];//从sel*4开始,选择比特序号大于sel*4的4位bit,相当于[sel*4+3:sel*4]
assign out = in[sel*4+3-:4];//从sel*4+3开始,选择比特序号小于sel*4+3的4位bit,相当于[sel*4+3:sel*4]
前面这两种写法,参考微信推文Verilog专题(七)如何用一行code描述256to1的Mux,担心下一次这个链接打不开了,于是截图
3.1.3 Arithmetic Circuits
3.1.3.1 Half adder(Hadd)
创建一个半加法器。半加法器将两个位相加(无进位),并产生总和与进位。
module top_module(
input a, b,
output cout, sum );
//assign {cout,sum} = a + b;
assign cout = a & b;
assign sum = a ^ b;
endmodule
3.1.3.2 Full adder(Fadd)
创建一个完整的加法器。一个全加法器将三个位(包括进位)相加,并产生一个总和与一个进位。
module top_module(
input a, b, cin,
output cout, sum );
//assign {cout,sum}=a+b+cin;
assign sum = a^b^cin;
//assign cout = ( a & b )|( a & cin )|( b & cin );
assign cout = a & b | (a | b) & cin;
endmodule
3.1.3.3 3-bit binary adder(Adder3)
Now that you know how to build a full adder, make 3 instances of it to create a 3-bit binary ripple-carry adder. The adder adds two 3-bit numbers and a carry-in to produce a 3-bit sum and carry out. To encourage you to actually instantiate full adders, also output the carry-out from each full adder in the ripple-carry adder. cout[2] is the final carry-out from the last full adder, and is the carry-out you usually see.
//行波进位加法器
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
integer i;
always@(*)begin
for(i=0;i<3;i=i+1)begin
if(i == 0)begin
sum[i] = a[i] ^ b[i] ^ cin;
cout[i]=a[i]&b[i] | a[i]&cin | b[i]&cin;
end
else begin
sum[i] = a[i] ^ b[i] ^ cout[i-1];
cout[i]=a[i]&b[i] | a[i]&cout[i-1] | b[i]&cout[i-1];
end
end
end
endmodule
3.1.3.4 Adder(Exams/m2014 q4j)
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum);
//assign sum = x + y;//这一行代码就可以替换下面所有!
wire [3:0] cout;
wire [3:0] sum_i;
assign sum_i[0]=x[0]^y[0];
assign cout[0]=x[0]&y[0];
assign sum_i[1]=x[1]^y[1]^cout[0];
assign cout[1]=x[1]&y[1]|x[1]&cout[0]|y[1]&cout[0];
assign sum_i[2]=x[2]^y[2]^cout[1];
assign cout[2]=x[2]&y[2]|x[2]&cout[1]|y[2]&cout[1];
assign sum_i[3]=x[3]^y[3]^cout[2];
assign cout[3]=x[3]&y[3]|x[3]&cout[2]|y[3]&cout[2];
assign sum = {cout[3],sum_i};
endmodule
3.1.3.5 Signed addition overflow(Exams/ece241 2014 q1c)
假设您有两个有符号的输入,即a [7:0]和b [7:0]。这些数字相加产生s [7:0]。同时计算是否发生(有符号的)溢出。
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
); //
// assign s = ...
// assign overflow = ...
assign s = a + b;
assign overflow = a[7] & b[7] & ~s[7] | ~a[7] & ~b[7] & s[7];
//assign overflow = (a[7]==b[7])?((a[7])?(!s[7]?1:0):(s[7]?1:0)):0;
endmodule
一个有符号数的最高位代表正负,最高位是0代表正数,最高位是1代表负数。那什么时候会发生溢出(overflow)的情况?只有两个正数(负数)相加才会发生溢出,相减(即一正一负)是不会发生溢出的。
两个正数相加(符号位都为0),如果结果为负数,则发生溢出;两个负数相加(符号位都为1),如果结果为正数,则发生溢出,其他情况都为没有发生溢出。
3.1.3.6 100-bit binary adder(Adder100)
创建一个100位二进制加法器。加法器将两个100位数字和一个进位相加,以产生100位总和并执行。
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
assign {cout,sum}=a+b+cin;
endmodule
3.1.3.7 4-digit BCD adder(Bcdadd4)
You are provided with a BCD (binary-coded decimal) one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out.
module bcd_fadd {
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );
Instantiate 4 copies of bcd_fadd to create a 4-digit BCD ripple-carry adder. Your adder should add two 4-digit BCD numbers (packed into 16-bit vectors) and a carry-in to produce a 4-digit sum and carry out.
module top_module(
input [15:0] a, b,
input cin,
output cout,
output [15:0] sum );
wire[2:0] cout_1;
bcd_fadd u1(
.a (a[3:0] ),
.b (b[3:0] ),
.cin (cin ),
.cout (cout_1[0] ),
.sum (sum[3:0] )
);
bcd_fadd u2(
.a (a[7:4] ),
.b (b[7:4] ),
.cin (cout_1[0] ),
.cout (cout_1[1] ),
.sum (sum[7:4] )
);
bcd_fadd u3(
.a (a[11:8] ),
.b (b[11:8] ),
.cin (cout_1[1] ),
.cout (cout_1[2] ),
.sum (sum[11:8] )
);
bcd_fadd u4(
.a (a[15:12] ),
.b (b[15:12] ),
.cin (cout_1[2] ),
.cout (cout ),
.sum (sum[15:12] )
);
endmodule
3.1.4 Karnaugh Map to Circuit
为什么对这部分没有任何印象?
3.1.4.1 3-variable(Kmap1)
实现下面的卡诺图描述的电路
module top_module(
input a,
input b,
input c,
output out );
assign out = a |b |c ;//只要不全为0,就输出1
endmodule
3.1.4.2 4-variable(Kmap2)
实现下面的卡诺图描述的电路。
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = ~a & ~d | ~b & ~c | b & c & d | a & c & d;
endmodule
3.1.4.3 4-variable(Kmap3)
实现下面的卡诺图描述的电路。
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = ~b & c | a & c | a & ~d;
endmodule
3.1.4.4 4-variable(Kmap4)
实现下面的卡诺图描述的电路。
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = ~a & b & ~c & ~d | a & ~b & ~c & ~d |
~a & ~b & ~c & d | a & b & ~c & d |
~a & b & c & d | a & ~b & c & d |
~a & ~b & c & ~d | a & b & c & ~d;
endmodule
3.1.4.5 Minimum SOP and POS(Exams/ece241 2013 q3)
A single-output digital system with four inputs (a,b,c,d) generates a logic-1 when 2, 7, or 15 appears on the inputs, and a logic-0 when 0, 1, 4, 5, 6, 9, 10, 13, or 14 appears. The input conditions for the numbers 3, 8, 11, and 12 never occur in this system. For example, 7 corresponds to a,b,c,d being set to 0,1,1,1, respectively.
Determine the output out_sop in minimum SOP form, and the output out_pos in minimum POS form.
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 | ~d) & (a | b | ~c));
endmodule
3.1.4.6 Karnaugh map(Exams/m2014 q3)
考虑下面的卡诺图所示的函数f。实现此功能。d无关紧要,这意味着您可以选择输出任何方便的值。
3.1.4.7 Karnaugh map(Exams/2012 q1g)
考虑下面的卡诺图所示的函数f。实现此功能。(原始问题要求简化功能的SOP和POS形式。)
module top_module (
input [4:1] x,
output f
);
assign f = ~x[1] & x[3] | x[2] & x[3] & x[4] | ~x[2] & ~x[4];
endmodule
3.1.4.8 K-map implemented with a multiplexer(Exams/ece241 2014 q3)
对于以下卡诺图,请使用一个4对1多路复用器和所需的2对1多路复用器,但要使用尽可能少的电路,以给出电路实现方案。不允许使用任何其他逻辑门,并且必须使用a和b作为多路复用器选择器输入,如下面的4对1多路复用器所示。
module top_module (
input c,
input d,
output [3:0] mux_in
);
assign mux_in[0] = c ? 1'b1 : d;
assign mux_in[1] = 1'b0;
assign mux_in[2] = d ? 1'b0 : 1'b1;
assign mux_in[3] = c ? d : 1'b0;
/*
assign mux_in[0] = c | d;
assign mux_in[1] = 1'b0;
assign mux_in[2] = ~d;
assign mux_in[3] = c & d;
*/
endmodule
后记
冲冲冲!