1.combinational logic: 组合逻辑
1.1 basic gates: 基本逻辑门
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
注: 有个圈的是同或门XNOR, 没有圈的是异或门XOR.
module top_module (input in1,input in2,input in3,output out);assign out = in3 ^ (~in1 ^ in2);
endmodule
more logic gates
练习: 同时创建多个逻辑门, 使用两个输入a和b构建组合逻辑电路. 一共7个输出, 每个输出用逻辑门驱动. 分别实现and/or/xor/nand/nor/xnor/anotb(最后一个为 a and-not b).
注: anotb逻辑为a & (~b). 以下是chatGPT对anotb的解释.
解答
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 inputsoutput f // one output
);assign f = (~x3&x2&~x1)|(~x3&x2&x1)|(x3&~x2&x1)|(x3&x2&x1);endmodule
two-bit equality
练习: 当A=B的时候输出z为1, 否则为0.
module top_module ( input [1:0] A, input [1:0] B, output z ); assign z = (A == B) ? 1 : 0;
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 circuits A and B
练习: 搭建如下电路, 子模块为前两题中的A和B.
module top_module (input x, input y, output z);wire a1o;wire b1o;wire a2o;wire b2o;A IA1(x,y,a1o);B IB1(x,y,b1o);A IA2(x,y,a2o);B IB2(x,y,b2o);assign z = (a1o|b1o)^(a2o&b2o);
endmodulemodule A (input x, input y, output z);assign z = (x^y) & x;
endmodulemodule B ( input x, input y, output z );assign z = ~x^y;
endmodule
ring or vibrate?
module top_module (input ring,input vibrate_mode,output ringer, // Make soundoutput motor // Vibrate
);assign ringer = (ring & ~vibrate_mode)? 1 : 0;assign motor = (ring & vibrate_mode)? 1 : 0;
endmodule
thermostat
练习: A heating/cooling thermostat controls both a heater (during winter) and an air conditioner (during summer). Implement a circuit that will turn on and off the heater, air conditioning, and blower fan as appropriate.
The thermostat can be in one of two modes: heating (mode = 1) and cooling (mode = 0). In heating mode, turn the heater on when it is too cold (too_cold = 1) but do not use the air conditioner. In cooling mode, turn the air conditioner on when it is too hot (too_hot = 1), but do not turn on the heater. When the heater or air conditioner are on, also turn on the fan to circulate the air. In addition, the user can also request the fan to turn on (fan_on = 1), even if the heater and air conditioner are off.
Try to use only assign statements, to see whether you can translate a problem description into a collection of logic gates.
module top_module (input too_cold,input too_hot,input mode,input fan_on,output heater,output aircon,output fan
); assign fan = fan_on || (mode && too_cold) || (~mode && too_hot);assign heater = mode && too_cold;assign aircon = ~mode && too_hot;endmodule
3-bit population count
练习: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 );assign out = &in ? 3 : (^in ? 1 : (in ? 2 : 0));
//&in == 1 means in == 3'b111;
//^in == 1 means there are odd number of '1'
//in == 0 means there is no "1"
endmodule
gates and vectors
练习:
out_both: 指示输入vector的某一bit及其左边相邻的一个bit是否均为1. 例如当in[3:2] == 2'b11时, out_both[2] == 1.
out_any:指示输入vector的某一bit及其右边相邻的一个bit中, 是否有为1的bit. 例如当in[2]和in[1] 中至少有一位为1时, out_any[2] == 1.
out_different:指示输入vector的某一bit及其左边相邻的一个bit是否相等, 规定in[3]左侧bit为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:1] & in[2:0];assign out_any = in[3:1] | in[2:0];assign out_different = in[3:0] ^ {in[0], in[3:1]};
endmodule
even longer vectors
练习: 上一题的延伸, vector长度增加.
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[99:0] ^ {in[0], in[99:1]};
endmodule
1.2 Multiplexers:复用器(数据选择器)
2-to-1 multiplexer
练习: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;
endmodule
2-to-1 bus multiplexer
练习:Create a 100-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
module top_module( input [99:0] a, b,input sel,output [99:0] out );assign out = sel ? b : a;
endmodule
9-to-1 multiplexer
练习: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'.
Expected solution length: Around 15 lines.
module top_module( input [15:0] a, b, c, d, e, f, g, h, i,input [3:0] sel,output [15:0] out );always @(*)begincase(sel)0: out = a;1: out = b;2: out = c;3: out = d;4: out = e;5: out = f;6: out = g;7: out = h;8: out = i;default: out = 16'hffff;endcaseend
endmodule
256-to-1 multiplexer
练习: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.
module top_module( input [255:0] in,input [7:0] sel,output out );assign out = in[sel]; //还可以这样写???nb
endmodule
256-to-1 4-bit multiplexer
练习: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.
注意:代码中注释了一段会报错的写法, 报错如下:
Error (10734): Verilog HDL error at top_module.v(5): sel is not a constant File: /home/h/work/hdlbits.9892329/top_module.v Line: 5.
题目给的提示: 即①太多选择不适合用case语句; ②vector索引可以为变量,但需要综合器明白被选择的位宽是常量, 注释中的写法就不能满足该条件; ③可以用verilog-2001中的bit slicing方法来处理.
查阅到别人的三种解法, 均附在代码中.
module top_module( input [1023:0] in,input [7:0] sel,output [3:0] out );//assign out = in[4*sel+3:4*sel]; //会报错的写法, 以下是三种通过sim的写法.//assign out = in[4*sel+3 -:4]; //从4*sel+3往下的连续4bit//assign out = in[4*sel +:4]; //从4*sel往上的连续4bitassign out = {in[sel*4+3],in[sel*4+2],in[sel*4+1],in[sel*4]};
endmodule
1.3 Arithmetic Circuits
half adder
练习:Create a half adder. A half adder adds two bits (with no carry-in) and produces a sum and carry-out.
module top_module( input a, b,output cout, sum );//assign cout = a && b;//assign sum = a ^ b;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-bits binary adder : 例化full_adder解决
后面简单的题就不写了, 一直搞这种题浪费时间.
signed addition overflow: 二进制补码相加的溢出检测
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
kmap3: 无关项可以考虑也可以不考虑
module top_module(input a,input b,input c,input d,output out );
assign out = a | ~b&c ;
endmodule
K-map implemented with a multiplexer
实现一下电路, 输入为c和d, 输出为mux_in[3:0].
module top_module (input c,input d,output [3:0] mux_in
); always @(*)begincase({c,d})2'b00: mux_in = 4'b0100;2'b01: mux_in = 4'b0001;2'b11: mux_in = 4'b1001;2'b10: mux_in = 4'b0101;default: mux_in = 0;endcaseend
endmodule
2.Sequential Logic
2.1 latchs and flip-flops
detect an egde
只检测上升沿
module top_module (input clk,input [7:0] in,output [7:0] pedge
);reg [7:0] in_d;always @(posedge clk)begin//延一拍in_d <= in; endwire [7:0] burst;assign burst = in & ~in_d;//上升跳变的检测: 0-1integer i;always @(posedge clk)begin//跳变来临时将输出置1, 否则输出为0for(i = 0; i<8; i++)beginif(burst[i]) pedge[i] <= 1;else pedge[i] <= 0;endendendmodule
detect both egde
检测上升沿和下降沿
module top_module (input clk,input [7:0] in,output [7:0] anyedge
);reg [7:0] in_d;always @(posedge clk)begin//延一拍in_d <= in; endwire [7:0] burst;assign burst = (in & ~in_d) | (~in & in_d);//上升下降跳变的检测: 0-1 (异或)integer i;always @(posedge clk)begin//跳变来临时将输出置1, 否则输出为0for(i = 0; i<8; i++)beginif(burst[i]) anyedge[i] <= 1;else anyedge[i] <= 0;endend
endmodule
edge capture register
实现输入信号的下降沿检测, 检测输出保持, 除非被reset为0
moduletop_module(input clk,input reset,input [31:0] in,output [31:0] out
);reg [31:0] in_d;always @(posedge clk)begin//延一拍in_d <= in; endwire [31:0] nburst;assign nburst = ~in & in_d;//下降跳变的检测: 0-1integer i;always @(posedge clk)begin//跳变来临时将输出置1, 否则输出为0if(reset) out <= 0;else beginfor(i = 0; i<32; i++)beginout[i] <= nburst[i] ? 1 : out[i];endendend
endmodule
dual-edge triggered flip-flop
双边沿触发器, 一开始的思路也是q1/q2分别用上升沿/下降沿触发, 但用了q = q1|q2的逻辑, 参考帖子并画图后意识到自己写的逻辑有问题. 用assign q = clk? q1:q2是对的.
module top_module (input clk,input d,output q
);reg q1,q2;always @(posedge clk)beginq1 <= d; endalways @(negedge clk)beginq2 <= d; endassign q = clk? q1:q2;
endmodule
下面是大佬提供的另外一种方法, 点击跳转, 根本想不到, 学习一下
双边沿触发器的理解参考另一篇文章, 点击跳转
module top_module (input clk,input d,output q
);
reg q1,q2;
always @(posedge clk) beginq1 <= d ^ q2;
end
always @(negedge clk) beginq2 <= d ^ q1;
end
assign q = q1 ^ q2; //q = q1 ^ q2 = (d ^ q2) ^ q2 = q1 ^ (d ^ q1) = dendmodule
Counter1-12
题目什么意思没搞懂, 跳了, 解答可以参考这篇文章