HDLBits_刷题_持续更新中
一、Getting Started
1.1Getting Started
1.1.1 编译后提示的意思
当你把代码写完然后编译之后,会给出相应的提示:
- 如果语言的编译和线路的仿真都正确,并且符合题目要求,则会提示Success!
- 编译错误,则会提示Compile Error
- 电路仿真错误,则会提示Simulation Error
- 如果语言的编译和线路的仿真都正确,但是不符合题目要求,则会提示Incorrect
- 可以在My Stats 查看或者分享我们写题目的进度,可以理解为自动存档哈。如图1.1所示。

1.1.2 网站的几个重要的板块
见下图即可。

1.1.3 问题的翻译与解答

意思:创建一个没有输入只有一个输出的电路,且输出总是为1。
解题代码如下:
module top_module( output one );
// Insert your code hereassign one = 1'b1;
endmodule
1.2Output Zero
网站相关介绍也在第一节介绍之后将主要进行问题的翻译与解答。
1.2.1题目与解答

意思:创建一个没有输入,一个输出且输出为0的电路。
代码如下:
module top_module(output zero
);// Module body starts after semicolonassign zero=1'b0;
endmodule
二 、Verilog Language
2.1 Basics
2.1.1 Simple wire

题目:创建一个模块,将输入与输出像一根线一样连接起来。
代码如下:
module top_module( input in, output out );assign out = in ;
endmodule
2.1.2 Four wires

题目:创建一个3输入4输出的模块,用线实现如图所示的连接。
代码如下:
module top_module( input a,b,c,output w,x,y,z );assign w=a,x=b,y=b,z=c;endmodule
2.1.3 Inverter

题目:创建一个实现非门的模块。
代码如下:
module top_module( input in, output out );assign out = ~in;
endmodule
2.1.4 AND gate

题目:创建一个实现与门的模块。
代码如下:
module top_module( input a, input b, output out );assign out = a & b;
endmodule
2.1.5 NOR gate

题目:创建一个实现或非门的模块。
代码如下:
module top_module( input a, input b, output out );assign out = ~(a|b);
endmodule
2.1.6 XNOR gate

题目:创建一个实现同或门的模块。
代码如下:
module top_module( input a, input b, output out );assign out = ~(a^b);
endmodule
2.1.7 Declaring wires
这个小节出现了线网数据类型wire,当内部结构越来越复杂时,一个模块的输入输出并非直接连接时,声明一个线网数据类型的变量(相当于中间变量)。

题目:实现如图所示的电路。创建两条中间线网(取任何你想取的名字)去连接与门和或门,
代码如下:
module top_module(input a,input b,input c,input d,output out,output out_n ); //这两个线网类型的变量,在没有器件连接时为高阻态Z wire temp1,temp2; assign temp1 = a&b;assign temp2 = c&d;assign out = temp1|temp2;assign out_n = ~out;
endmodule
2.1.8 7458 chip

代码如下:
module top_module ( input p1a, p1b, p1c, p1d, p1e, p1f,output p1y,input p2a, p2b, p2c, p2d,output p2y );assign p1y = (p1a&p1c&p1b) | (p1d&p1f&p1e);assign p2y = (p2a&p2b) | (p2c&p2d);
endmodule
2.2 Vectors
2.2.1 Vectors
可以一次性初始化许多条线,注意维度应该在变量名字的前面。
规则:type [upper:lower] vector_name;
eg. wire [99:0] my_vector;

代码如下:
module top_module ( input wire [2:0] vec,output wire [2:0] outv,output wire o2,output wire o1,output wire o0 ); // Module body starts after module declarationassign outv[2:0]= vec[2:0];assign o0 = vec[0],o1 = vec[1],o2 = vec[2];
endmodule
2.2.2 Vectors in more detail
题目:构建一个组合电路,将输入的16位分割成低8位和高8位。
代码如下:
module top_module( input wire [15:0] in,output wire [7:0] out_hi,output wire [7:0] out_lo );assign out_hi[7:0] = in[15:8];assign out_lo[7:0] = in[7:0];
endmodule
2.2.3 Vector part select

题目:就是把四个字节的容器里的每个字节调换位置。
代码如下:
module top_module( input [31:0] in,output [31:0] out );assign out[31:24] = in[7:0];assign out[23:16] = in[15:8];assign out[15:8] = in[23:16];assign out[7:0] = in[31:24];endmodule
2.2.4 Bitwise operators

题目:如图所示,注out_not[5:0]]高3位是b。
代码如下:
module top_module( input [2:0] a,input [2:0] b,output [2:0] out_or_bitwise,output out_or_logical,output [5:0] out_not
);assign out_or_bitwise[2:0] = a[2:0]|b[2:0]; //a[2:0]和b[2:0]可以直接写成a和bassign out_or_logical = a[2:0]||b[2:0];//assign out_not[5:3] = ~b[2:0]; 这种方法也可以//assign out_not[2:0] = ~a[2:0];assign out_not[5:0] = {{~b[2:0]},{~a[2:0]}};endmodule
2.2.5 Four-input gates

代码如下:
module top_module( input [3:0] in,output out_and,output out_or,output out_xor
);assign out_and = ∈ //每一位相与assign out_or = |in;assign out_xor = ^in;endmodule
2.2.6 Vector concatenation operator
拼接符{}
用法:
{3’b111, 3’b000} => 6’b111000
{1’b1, 1’b0, 3’b101} => 5’b10101
{4’ha, 4’d10} => 8’b10101010

题目:如图所示。
代码如下:
module top_module (input [4:0] a, b, c, d, e, f,output [7:0] w, x, y, z );assign {w,x,y,z} = {a,b,c,d,e,f,{2'b11}};endmodule
2.2.7 Vector reversal 1
题目:将输入的每个位翻转。
代码如下:
方法一:
module top_module( input [7:0] in,output [7:0] out
);always @(*) begin //组合逻辑电路for (integer i=0; i<8; i++) out[i] = in[8-i-1];end
endmodule
方法二:
module top_module( input [7:0] in,output [7:0] out
);assign out[7:0]={ in[0],in[1],in[2],in[3],in[4],in[5],in[6],in[7] };
endmodule
2.2.8 Replication operator
题目:将8位的一个数据扩展成32位的数据,要求复制符号位来增加数据的位数
代码如下:
module top_module (input [7:0] in,output [31:0] out );assign out[31:0] ={{24{in[7]}} ,{in[7:0]}};
endmodule
2.2.9 More replication

题目:(XNOR 为同或的意思)将图示数据全部同或,再并入到一个25位的容器里。
代码如下:
module top_module (input a, b, c, d, e,output [24:0] out );//assign out = { {~{5{a}}^{a,b,c,d,e}},{~{5{b}}^{a,b,c,d,e}},{~{5{c}}^{a,b,c,d,e}},{~{5{d}}^{a,b,c,d,e}},{~{5{e}}^{a,b,c,d,e}} };
endmodule
2.3 Modules:Hierarchy
本小节就进入了模块化设计,也就是模块的例化。例化的方式有两种,按照位置例化或名字例化。为了代码的可读性一般使用名字例化。具体如何使用看下面的练习。
2.3.1 Modules

题目:mod_a模块已经给出,把他按上图所示,与顶层模块进行例化。
代码如下:
一、按名字的方式例化。(更加推荐)
module top_module ( input a, input b, output out );mod_a temp_mod( //这里的temp_mod模块名字随便取,主要是为了区分多个不同的例化。.in1(a), //in1是mod_a模块的输入,a是top_module的输入.in2(b),.out(out) //这种例化的方式可以清晰的看到与引脚之间的连接。); endmodule
二、按位置的方式例化。
module top_module ( input a, input b, output out );mod_a temp_mod(a,b,out); //这种例化的方式看不出引脚之间的连接,但是他更加简便endmodule
2.3.2 Connecting ports by position

题目:mod_a 模块已经给出,要求使用位置例化
代码如下:
module top_module ( input a, input b, input c,input d,output out1,output out2
);mod_a temp_mod (out1,out2,a,b,c,d);
endmodule
2.3.3 Connecting ports by name

题目:mod_a 模块已经给出,要求使用名字例化
代码如下:
module top_module ( input a, input b, input c,input d,output out1,output out2
);mod_a temp_mod (.in1(a),.in2(b),.in3(c),.in4(d),.out1(out1),.out2(out2)); //注意括号内的是顶层模块引脚
endmodule
2.3.4 Three modules

题目:my_dff 模块已经给出,该模块具有两个输入和一个输出(它实现了 D 触发器)。将它例化出三个模块,然后将它们连接在一起,形成一个3位的移位寄存器。clk 端口需要连接到所有例化出来的模块。my_diff 模块如图红线已经框出
代码如下:
module top_module ( input clk, input d, output q );wire temp_wire_left; //线网类型数据,作为第一,二个模块连接的线。wire temp_wire_right;//线网类型数据,作为第二,三个模块连接的线。my_dff mod_1 //例化出模块1(.clk(clk),.d(d),.q(temp_wire_left));my_dff mod_2 //例化出模块2(.clk(clk),.d(temp_wire_left),.q(temp_wire_right));my_dff mod_3 //例化出模块3(.clk(clk),.d(temp_wire_right),.q(q));
endmodule
2.3.5 Module and vectors

题目:提供的模块如图所示。
代码如下(详解看注释):
module top_module ( input clk, input [7:0] d, input [1:0] sel, output [7:0] q
);
//module my_dff8 ( input clk, input [7:0] d, output [7:0] q );//线网类型数据,作为第一,二个模块连接的线。wire [7:0] temp_wire_left; //线网类型数据,作为第二,三个模块连接的线。wire [7:0] temp_wire_right;//线网类型数据,作为第三个模块输出。wire [7:0] temp_mod_out;//下面是三个例化my_dff8 mod_1(.clk(clk),.d(d),.q(temp_wire_left));my_dff8 mod_2(.clk(clk),.d(temp_wire_left),.q(temp_wire_right));my_dff8 mod_3(.clk(clk),.d(temp_wire_right),.q(temp_mod_out));//这里是一个数据选择器always @(*)begincase (sel)//组合逻辑所以阻塞赋值(=),注意不要用连续赋值关键词assign2'b00: q = d; 2'b01: q = temp_wire_left;2'b10: q = temp_wire_right;2'b11: q = temp_mod_out;default:;endcaseend
endmodule
注意阻塞赋值与非阻塞赋值的不同(具体可以去看仿真的波形):
(1) 阻塞赋值(=) : 写在前面的语句先执行,写在后面的语句后执行,也就是说,它是顺序执行的,一般用于组合逻辑电路。
(2) 非阻塞赋值(<=) :写在前面的语句与后面的语句同时执行,也就是说,它是并行执行的,跟书写顺序没有关系,一般用于时序逻辑电路。
2.3.6 Adder 1

题目:提供了一个16位加法器模块名为add16,创建一个32位的加法器。
代码如下(详解看注释):
module top_module(input [31:0] a,input [31:0] b,output [31:0] sum
);//题目中摆放在上面模块的sum输出连接的线wire [15:0] sum_up_out;//题目中摆放在上面模块的cout输出连接的线wire [15:0] cout_up_out;//题目中摆放在下面模块的cout输出连接的线wire [15:0] sum_down_out;//实例化add16 add16_up(.a(a[15:0]),.b(b[15:0]),.cin(0),.sum(sum_up_out),.cout(cout_up_out));add16 add16_down(.a(a[31:16]),.b(b[31:16]),.cin(cout_up_out),.sum(sum_down_out),//输出没有连接则直接不写.cout() );//注意题目中摆放再下面模块的sum输出是高位assign sum = {sum_down_out,sum_up_out};
endmodule
2.3.7 Adder 2

题目:这里要求我们自己写出1位全加器的模块,16为加法器就是通过例化这个1位全加器得来,因此不写就会报错。注意:不要求我们自己写出16位加法器模块,题目已经提供。
代码如下:
module top_module (input [31:0] a,input [31:0] b,output [31:0] sum
);//这部分与2.3.6小结一样wire [15:0] mod_2_sum,mod_1_sum;wire [15:0] mod_1_cout;add16 mod_1(.a(a[15:0]),.b(b[15:0]),.cin(0),.cout(mod_1_cout),.sum(mod_1_sum));add16 mod_2(.a(a[31:16]),.b(b[31:16]),.cin(mod_1_cout),.cout(),.sum(mod_2_sum));assign sum = {mod_2_sum,mod_1_sum};
endmodulemodule add1 ( input a, input b, input cin, output sum, output cout );//根据真值表和卡诺图得来,过程见下图。assign sum = (~cin&a&(~b))|(cin&(~a)&(~b))|(~cin&(~a)&b)|(cin&a&b);assign cout =(a&b)|(cin&b)|(cin&a);endmodule
真值表与卡诺图如下:

2.3.8 Carry-select adder
前几个小节练习的进位加法器,只有前一个加法器加完之后才能进行后续的相加,这样使得数据相加很慢,可以用进位选择加法器来加快加法运算的速度。

题目:已经提供了模块add16 模块。数据选择器并不是要算出一位选择一位,而是把高位全部算好了,低位的进位一算出,则数据相加的结果就直接出来了。
代码如下:
module top_module(input [31:0] a,input [31:0] b,output [31:0] sum
);wire [15:0] mod_1_cout;wire [15:0] mod_up_sum,mod_mid_sum,mod_down_sum;wire [15:0] mod_mid_down_sum;add16 mod_up(.a(a[15:0]),.b(b[15:0]),.cin(0),.cout(mod_1_cout),.sum(mod_up_sum));add16 mod_mid(.a(a[31:16]),.b(b[31:16]),.cin(0),.cout(),.sum(mod_mid_sum));add16 mod_down(.a(a[31:16]),.b(b[31:16]),.cin(1),.cout(),.sum(mod_down_sum));always @(*)begincase(mod_1_cout)1'b0: mod_mid_down_sum = mod_mid_sum;1'b1: mod_mid_down_sum = mod_down_sum;default:;endcase;endassign sum={mod_mid_down_sum,mod_up_sum};
endmodule
2.3.9 Adder-subtractor
加/减法器,当sub为0时为为加法器,为1时为减法器。这个也比较好理解,二进制的减法就是加上补码(一个数的补码就是,取反再低位加1)
一个数异或0就是本身,异或1就是取反。

代码如下:
module top_module(input [31:0] a,input [31:0] b,input sub,output [31:0] sum
);wire [15:0] mod_1_cout;add16 mod_up(.a(a[15:0]),//一个16位的数和一个1位的数无法进行异或,因此用拼接符增加数据位数到16位.b(b[15:0]^{16{sub}}),.cin(sub),.cout(mod_1_cout),.sum(sum[15:0]));add16 mod_mid(.a(a[31:16]),.b(b[31:16]^{16{sub}}),.cin(mod_1_cout),.cout(),.sum(sum[31:16]));
endmodule
2.4 Procedures
2.4.1 Always blocks(combination)
组合逻辑always块是等价于assign的,但是语法上有不同。

注意:
always 是过程赋值语句,数据类型一定要是 寄存器(reg)类型。
assign 是连续赋值语句,数据类型一定要是线网(wire)类型。

代码如下:
module top_module(input a, input b,output wire out_assign,output reg out_alwaysblock
);assign out_assign = a & b;always @(*)beginout_alwaysblock = a & b;end
endmodule
2.4.2 Always blocks(clocked)

组合逻辑中,使用阻塞赋值,时序逻辑中使用非阻塞赋值。

题目:用三种当时构建异或门。
代码如下:
module top_module(input clk,input a,input b,output wire out_assign,output reg out_always_comb,output reg out_always_ff );//连续赋值assign out_assign = a^b;//组合过程赋值always @(*)beginout_always_comb = a^b;endalways @(posedge clk)beginout_always_ff <= a^b;endendmodule
2.4.3 If statement

终于来到了我们熟悉的if else了0.0!!!!安排。
代码如下:
module top_module(input a,input b,input sel_b1,input sel_b2,output wire out_assign,output reg out_always ); assign out_assign = (sel_b1 & sel_b2)? b:a;always @(*)beginif(sel_b1 & sel_b2)beginout_always = b;endelse beginout_always = a; end end
endmodule
2.4.4 If statement latches
(1)在组合逻辑中,我们要防止锁存器的产生。因为我们组合逻辑不花里胡哨输入变,输出直接跟着变,不保存状态。那怎么避免呢,就是把所有情况都写出来,if else 还有 case default 成双成对出现。
(2)在时序逻辑中,即使不把所有情况都列出,也不会产生锁存器。
代码如下:
module top_module (input cpu_overheated,output reg shut_off_computer,input arrived,input gas_tank_empty,output reg keep_driving ); //always @(*) begin//cpu过热if (cpu_overheated)//关机shut_off_computer = 1;elseshut_off_computer = 0;endalways @(*) beginif (~arrived)//还没到达目的地,油箱没空就保持行驶keep_driving = ~gas_tank_empty;else//到了就不行驶了keep_driving = 0;endendmodule
2.4.5 Case statement
case 很熟悉了,不多说,注意case语法即可。
代码如下:
module top_module ( input [2:0] sel, input [3:0] data0,input [3:0] data1,input [3:0] data2,input [3:0] data3,input [3:0] data4,input [3:0] data5,output reg [3:0] out );always@(*) begin // This is a combinational circuitcase(sel) //注意这里不需要begin3'b000: out=data0; 3'b001: out=data1;3'b010: out=data2; 3'b011: out=data3; 3'b100: out=data4; 3'b101: out=data5; default:out=0;endcaseendendmodule
2.4.6 Priority encoder
优先编码器,使用case语句即可。
代码如下:
module top_module (input [3:0] in,output reg [1:0] pos );always@(*) begincase (in)4'b0000:pos=2'b00;4'b0001:pos=2'b00;4'b0010:pos=2'b01;4'b0011:pos=2'b00;4'b0100:pos=2'b10;4'b0101:pos=2'b00;4'b0110:pos=2'b01;4'b0111:pos=2'b00;4'b1000:pos=2'b11;4'b1001:pos=2'b00;4'b1010:pos=2'b01;4'b1011:pos=2'b00;4'b1100:pos=2'b10;4'b1101:pos=2'b00;4'b1110:pos=2'b01;4'b1111:pos=2'b00;default:pos=2'b00;endcaseend
endmodule
2.4.7 Priority encoder with casez
(1)假如case语句中想要使用z来表示,不在乎这一位数据是什么的话,就要使用casez语句。
(2)casex也是类似的使用,把z换成x即可,在casex语句下可以使用z,但是casez下不可以使用x**
(3)通常情况下用casez比用casex更好一些,因为×的存在可能会导致仿真出现令人误解和混乱的结果。
(4)在casex和 casez声明的标号中用?来代替z比较好,因为这样做比较清楚,是一个无关项,而不是一个高阻项。
题目:8位优先编码器。
代码如下:
方法一、casez
module top_module (input [7:0] in,output reg [2:0] pos );always @(*) begincasez(in)8'b0000_0000:pos=3'd0;8'bzzzz_zzz1:pos=3'd0;8'bzzzz_zz10:pos=3'd1;8'bzzzz_z100:pos=3'd2;8'bzzzz_1000:pos=3'd3;8'bzzz1_0000:pos=3'd4;8'bzz10_0000:pos=3'd5;8'bz100_0000:pos=3'd6;8'b1000_0000:pos=3'd7;default:pos=0;endcaseend
endmodule
方法二、casex
module top_module (input [7:0] in,output reg [2:0] pos );always @(*) begincasex(in) //使用casex8'b0000_0000:pos=3'd0;8'bzzzz_zzz1:pos=3'd0;8'bzzzz_zz10:pos=3'd1;8'bzzzz_z100:pos=3'd2;8'bzzzz_1000:pos=3'd3;8'bzzz1_0000:pos=3'd4;8'bzz10_0000:pos=3'd5;8'bz100_0000:pos=3'd6;8'b1000_0000:pos=3'd7;default:pos=0;endcase //都是endcaseend
endmodule
方法三、用问号来替代z或x
module top_module (input [7:0] in,output reg [2:0] pos );always @(*) begincasez(in)8'b0000_0000:pos=3'd0;8'b????_???1:pos=3'd0;8'b????_??10:pos=3'd1;8'b????_?100:pos=3'd2;8'b????_1000:pos=3'd3;8'b???1_0000:pos=3'd4;8'b??10_0000:pos=3'd5;8'b?100_0000:pos=3'd6;8'b1000_0000:pos=3'd7;default:pos=0;endcaseend
endmodule
2.4.8 Avoiding laches
还是那句话,case语句中default不能少!!!
代码如下:
module top_module (input [15:0] scancode,output reg left,output reg down,output reg right,output reg up ); always @(*) begin//初始化up = 1'b0;down = 1'b0; left = 1'b0;right = 1'b0;case (scancode) 16'he06b:left = 1'b1;16'he072:down = 1'b1;16'he074:right= 1'b1;16'he075:up = 1'b1; default:beginup = 1'b0;down = 1'b0; left = 1'b0;right = 1'b0;endendcase end
endmodule
2.5 More Verilog Features
2.5.1 Conditional ternary operator

题目:使用条件运算符从四个无符号数据中找到最小的数据。
代码如下:
module top_module (input [7:0] a, b, c, d,output [7:0] min);//wire [7:0] temp_min1,temp_min2;assign temp_min1=(a<b)?a:b;assign temp_min2=(c<d)?c:d;assign min =(temp_min1<temp_min2)?temp_min1:temp_min2;
endmodule
2.5.2 Reduction operators
使用方式如下图所示:

题目:用精简算子,给一个8位的数据,做一个偶校验。
代码如下:
module top_module (input [7:0] in,output parity); assign parity = ^in;endmodule
2.5.3 Reduction:Even wider gates

代码如下:
module top_module( input [99:0] in,output out_and,output out_or,output out_xor
);assign out_and=∈assign out_or =|in;assign out_xor=^in;
endmodule
2.5.4 Vector 100r

题目:翻转一下所给数据位的顺序。
代码如下:
module top_module( input [99:0] in,output [99:0] out
);always @(*)beginfor(int i=0;i<100;i=i+1) beginout[i] =in[99-i]; endend
endmodule
2.5.5 Combination for-loop:255-bit population count

题目:统计一个255位的数据,有多少个位是1。
代码如下:
module top_module( input [254:0] in,output [7:0] out );always @ ( * )begin//初始化out=0;for(int i=0;i<255;i=i+1) beginif(in[i]==1'b1)beginout=out+1;endelseout=out;endend
endmodule
2.5.6 Generate for-loop:100-bit binary adder 2
这里使用了generate 关键词注意语法,具体看代码注释。

题目:创建一个100位的二进制加法器
代码如下:
module top_module( input [99:0] a, b,input cin,output [99:0] cout,output [99:0] sum );//generate 用于循环例化,用法如下generate//generate 专用数据类型//!!!!!这里不可以给i赋值,如i=0 是错误的genvar i ; for(i=0;i<100;i=i+1) begin:add_100 //整个循环例化出整体模块的名称if(i==0) begin //第一个例化的cin用于接顶层模块cinadder_full add100(.a(a[i]),.b(b[i]),.cin(cin),.cout(cout[i]),.sum(sum[i]));endelse beginadder_full add100(.a(a[i]),.b(b[i]),.cin(cout[i-1]),.cout(cout[i]),.sum(sum[i]));endend endgenerate
endmodule//全加器模块的设计
module adder_full(input a,b,cin,output cout,sum
);//用真值表和卡诺图做的//方法一//assign sum = (~cin&a&(~b))|(cin&(~a)&(~b))// |(~cin&(~a)&b)|(cin&a&b);//assign cout =(a&b)|(cin&b)|(cin&a);//方法二//更加简便assign {cout,sum}=a+b+cin;
endmodule
2.5.7 Generate for-loop:100-bit BCD adder

BCD加法器就是用4个二进制表示一个十进制数的加法器。
代码如下:
module top_module( input [399:0] a, b,input cin,output cout,output [399:0] sum );wire [99:0] cout_temp;generategenvar i;for(i=0;i<100;i++)begin:add10if(i==0) begin bcd_fadd add(a[4*i+3:4*i],b[4*i+3:4*i],cin,cout_temp[i],sum[4*i+3:4*i]);endelse beginbcd_fadd add(a[4*i+3:4*i],b[4*i+3:4*i],cout_temp[i-1],cout_temp[i],sum[4*i+3:4*i]);endendendgenerateassign cout = cout_temp[99];
endmodule
三、Circuits
3.1 Combinational Logic
3.1.1Basic Gates
3.1.1.1 Wire
代码如下:
module top_module (input in,output out);assign out = in;
endmodule
3.1.1.2 GND
代码如下:
module top_module (output out);assign out=1'b0;
endmodule
3.1.1.3 NOR
代码如下:
module top_module (input in1,input in2,output out);assign out = ~( in1|in2 );
endmodule
3.1.1.4 Another gate

代码如下:
module top_module (input in1,input in2,output out);assign out = in1 & (~in2);endmodule
3.1.1.5 Two gate

module top_module (input in1,input in2,input in3,output out);wire temp_one;assign temp_one=~(in1^in2);assign out = temp_one ^ in3;endmodule
3.1.1.6 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
3.1.1.7 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
3.1.1.8 Truth tables
真值表如图所示:

利用真值表画卡诺图即可。
代码如下:
module top_module( input x3,input x2,input x1, // three inputsoutput f // one output
);assign f= ~x3&x2 | x3&x1;endmodule
3.1.1.9Two-bit equality

代码如下:
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 circut A

module top_module (input x, input y, output z);assign z = (x^y) & x;endmodule
3.1.1.11 Simple circut B

列出真值表即可得出答案。
代码如下:
module top_module ( input x, input y, output z );assign z=~(x^y);endmodule
3.1.1.12 Combine circuts A and B

注意他这里的AB模块没有提供。
代码如下:
module top_module (input x, input y, output z);wire temp1,temp2,temp3,temp4;wire temp_12,temp_34;A IA1(x,y,temp1);B IB1(x,y,temp2);A IA2(x,y,temp3);B IB2(x,y,temp4);assign temp_12 = temp1 | temp2;assign temp_34 = temp3 & temp4;assign z = temp_12^temp_34;
endmodulemodule 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
3.1.1.13 Ring or vibrate

题目:如果ring=1的情况下,要么闹铃要么震动,但是两者不会同时发生。当vibrate_mode=1 时,震动否则闹铃。
代码如下:
module top_module (input ring,input vibrate_mode,output ringer, // Make soundoutput motor // Vibrate
);assign motor = ring & vibrate_mode;assign ringer= ring & ~vibrate_mode ;
endmodule
3.1.1.14 Thermostat

列出真值表,如下:
卡诺图如下:

代码如下:
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 =( ~mode&too_hot )|fan_on|(mode&too_cold);endmodule
3.1.1.15 3-bit population count
题目:计一个Vector里1的个数。
代码如下:
module top_module( input [2:0] in,output [1:0] out );reg [1:0] temp;always @(*)begintemp=0;for(int i=0;i<3;i=i+1) beginif(in[i]==1'b1)begintemp=temp+1; endelse begintemp=temp;endendout=temp;end
endmodule
3.1.1.16 Gates and vexctors
直接见代码:
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[3:1]|in[2:0]; //与右边的位进行或运算assign out_different =in ^{in[0],in[3:1]};//与左边的位进行异或
endmodule
3.1.1.17 Even longer vectors
与上一题一样,注意使用verctor的移位即可。
代码如下:
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[99:1]|in[98:0]; //与右边的位进行或运算assign out_different =in ^{in[0],in[99:1]};//与左边的位进行异或
endmodule
3.1.2 Multiplexer
3.1.2.1 2-to-1 multiplexer

代码如下:
module top_module( input a, b, sel,output out ); assign out = (sel==0)? a:b ;endmodule
3.1.2.2 2-to-1 bus multiplexer

代码如下:
module top_module( input [99:0] a, b,input sel,output [99:0] out );assign out = (sel==0)? a:b ;
endmodule
3.1.2.3 9-to-1 multiplexer

代码如下:
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) 4'b0000:out=a;4'b0001:out=b;4'b0010:out=c;4'b0011:out=d;4'b0100:out=e;4'b0101:out=f;4'b0110:out=g;4'b0111:out=h;4'b1000:out=i;default:out=16'b1111_1111_1111_1111; endcaseend
endmodule
3.1.2.4 256-to-1 multiplexer

代码如下:
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

代码如下:
module top_module( input [1023:0] in,input [7:0] sel,output [3:0] out );//经典的错误标准的零分,因为verilog没有这个语法//assign out = in[sel*4+3:sel*4];//正确的做法assign out = in[sel*4+3-:4];
endmodule
3.1.3 Arithmetic Circuit
3.1.3.1 Half adder
代码如下:
module top_module( input a, b,output cout, sum );assign {cout,sum} = a+b;endmodule
3.1.3.2 Full adder
module top_module( input a, b, cin,output cout, sum );assign {cout ,sum } = a+b+cin;endmodule
3.1.3.3 3-bit binary adder
module top_module( input [2:0] a, b,input cin,output [2:0] cout,output [2:0] sum );full_add add1(a[0],b[0],cin, cout[0],sum[0]); full_add add2(a[1],b[1],cout[0],cout[1],sum[1]); full_add add3(a[2],b[2],cout[1],cout[2],sum[2]); endmodulemodule full_add( input a, b, cin,output cout, sum );assign {cout ,sum } = a+b+cin;endmodule
3.1.3.4 Adder

module top_module (input [3:0] x,input [3:0] y, output [4:0] sum);wire [3:0] temp;full_add add1(x[0],y[0], ,temp[0],sum[0]);full_add add2(x[1],y[1],temp[0],temp[1],sum[1]);full_add add3(x[2],y[2],temp[1],temp[2],sum[2]);full_add add4(x[3],y[3],temp[2],temp[3],sum[3]);assign sum[4]=temp[3];//还可以直接 sum = x + y;
endmodulemodule full_add( input a, b, cin,output cout, sum );assign {cout ,sum } = a+b+cin;endmodule
3.1.3.5 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
3.1.3.6 100-bit binary adder

前面有写过需要例化很多模块时可以使用generate关键字来解决,这里我们有一个更加简单的方法来解决,那就是行为描述。
代码如下:
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

module top_module ( input [15:0] a, b,input cin,output cout,output [15:0] sum );wire [3:0] temp;generategenvar i;for(i=0;i<4;i=i+1)begin :add_bcdif(i==0)bcd_fadd add10(a[4*i+3:4*i],b[4*i+3:4*i],cin, temp[i],sum[4*i+3:4*i]); elsebcd_fadd add10(a[4*i+3:4*i],b[4*i+3:4*i],temp[i-1],temp[i],sum[4*i+3:4*i]); endendgenerateassign cout=temp[3];endmodule
3.1.4 Karnaugh Map to Circuit
卡诺图走起!!!!!
3.1.4.1 3-variable

module top_module(input a,input b,input c,output out ); assign out= a | c | b;endmodule
3.1.4.2 4-variable

代码如下:
module top_module(input a,input b,input c,input d,output out ); // 1 2 3 4assign out = (~d & ~a) | (~c & ~b) | (c&d&b) | (d&a&~b);
endmodule
3.1.4.3 4-variable

代码如下:
注意其中的d代表不在乎他为1还是0。
module top_module(input a,input b,input c,input d,output out ); assign out = a | (c & ~b );endmodule
3.1.4.4 4-variable

直接硬刚吧!!!没法化简。
代码如下:
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
SOP (与或),POS(或与)

解题过程如下图:

代码如下:
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 & (~b|d) & (~a|b);
endmodule
3.1.4.6 Karnaugh map

代码如下:
module top_module (input [4:1] x, output f );assign f=(~x[1]&x[3]) | (x[2]&x[4]);
endmodule
3.1.4.7 Karnaugh map

代码如下:
module top_module (input [4:1] x,output f
); assign f = (~x[4]&~x[2]) | (&x[4:2]) | (~x[1]&x[3]);endmodule
3.1.4.8 K-map implemented with a multiplexer

代码如下:
module top_module (input c,input d,output [3:0] mux_in
); //注意不能用逻辑门//只能用选择器//ab=2'b00;assign mux_in[0]=c?1:(d?1:0);//ab=2'b01;assign mux_in[1]=0;//ab=2'b11;assign mux_in[3]=c?(d?1:0):0;//ab=2'b10;assign mux_in[2]=c?(d?0:1):(d?0:1);endmodule
3.2 Sequential Logic
3.2.1 Latches and Flip-Flops
(1) D flip-flop
代码如下:
module top_module (input clk, // Clocks are used in sequential circuitsinput d,output reg q );////D 触发器 上升沿有效always @(posedge clk)beginq<=d;end
endmodule
(2) D flip-flops
8位的D触发器,与单个触发器设计一样。
代码如下:
module top_module (input clk,input [7:0] d,output [7:0] q
);always @(posedge clk)beginq<=d;end
endmodule
(3) DFF with reset

代码如下:
module top_module (input clk,input reset, // Synchronous resetinput [7:0] d,output [7:0] q
);//同步复位always @(posedge clk)begin//注意这里是高电平有效if(reset)q<=8'b0;elseq<=d;end
endmodule
(4) DFF with reset value
代码如下:
module top_module (input clk,input reset,input [7:0] d,output [7:0] q
);//时钟下降沿有效always @(negedge clk)begin//注意这里是高电平有效if(reset)q<=8'h34;elseq<=d;end
endmodule
(5) DFF with asynchronous reset

代码如下:
module top_module (input clk,input areset, // active high asynchronous resetinput [7:0] d,output [7:0] q
);//时钟上升沿有效always @(posedge clk or posedge areset )beginif(areset)q<=8'b0;elseq<=d;end
endmodule
(6) DFF with byte enable

代码如下:
module top_module (input clk,input resetn,input [1:0] byteena,input [15:0] d,output [15:0] q
);always @(posedge clk)beginif(!resetn)q<=16'b0;else beginq[15:8] <= byteena[1]?d[15:8]:q[15:8];q[7:0] <= byteena[0]?d[7:0] :q[7:0 ];endend
endmodule
(7) D Latch
module top_module (input d, input ena,output q);always @ (*)beginif(ena)q=d;elseq=q;end
endmodule
(8) DFF

异步复位
代码如下:
module top_module (input clk,input d, input ar, // asynchronous resetoutput q);always @ (posedge clk or posedge ar)beginif(ar)q<=0;elseq<=d;endendmodule
(9) DFF

代码如下:
module top_module (input clk,input d, input r, // synchronous resetoutput q);always @ (posedge clk)beginif(r)q<=0;elseq<=d;end
endmodule
(10) DFF + gate

代码如下:
module top_module (input clk,input in, output out);always @ (posedge clk)beginout<=in^out;end
endmodule
(11) MUX and DFF

注意这里一定要审题:不要把整个图都给他搞出来了
代码如下:
module top_module (input clk,input L,input r_in,input q_in,output reg Q);always @(posedge clk)beginQ<=L?r_in:q_in;end
endmodule
(12) MUX and DFF

代码如下:
module top_module (input clk,input w, R, E, L,output Q
);always @(posedge clk)beginQ<=L?R:(E?w:Q);end
endmodule
(13) DFFs and gates

//正确代码
module top_module (input clk,input x,output z
); reg [2:0] Q;always@(posedge clk)beginQ[0] <= Q[0] ^ x;Q[1] <= ~Q[1] & x;Q[2] <= ~Q[2] | x;endassign z = ~(| Q);endmodule
错误代码:
提交之后一直显示错误,目前没有发现错误原因
module top_module (input clk,input x,output z
); wire D0,D1,D2;wire Q0,Q1,Q2;assign D0 = x ^ Q0;assign D1 = x & !Q1;assign D2 = x | !Q2;DFF aff1(clk,D0,Q0);DFF aff2(clk,D1,Q1);DFF aff3(clk,D2,Q2);assign z = !(Q0 | Q1 | Q2);endmodulemodule DFF (input clk,input d,output reg q);always@(posedge clk)q <= d;
endmodule
(14) Creat circuit from trurh table

代码如下:
module top_module (input clk,input j,input k,output Q); always @(posedge clk)beginQ <=j? (k?~Q:1):(k?0:Q);end
endmodule
(15) Detect an egde

题目:检测上升沿
代码如下:
module top_module (input clk,input [7:0] in,output [7:0] pedge
);//in_temp为in上一个cycle的值!!!!//假如in=1,in_temp=0;则为检测到了一个上升沿reg [7:0] in_temp;//检测in的上升沿,检测到之后给pedge一个脉冲always @ (posedge clk)beginin_temp <= in;pedge <= in & ~in_temp; end
endmodule
(15) Detect both egde

module top_module (input clk,input [7:0] in,output [7:0] anyedge
);//in_temp为in上一个cycle的值!!!!//假如in=1,in_temp=0;则为检测到了一个上升沿//in=0,in_temp=1;则为下降沿,都符合本题意reg [7:0] in_temp;always @ (posedge clk)beginin_temp <= in;//便于理解写出了两种情况// pedge <= (in & ~in_temp) & (~in & in_temp); //更加简洁的写法anyedge <= in ^ in_temp; end
endmodule
(16) Egde capture register

module top_module (input clk,input reset,input [31:0] in,output [31:0] out
);//捕获下降沿reg [31:0] in_temp;always @(posedge clk) beginin_temp <= in;//每一位都要检测for(int i=0;i<32;i=i+1)begin//这里的case条件用到了拼接运算符//当然这里使用if语句也完全okcase ({in_temp[i] & ~in[i] ,reset})2'b01:out[i] = 1'b0;2'b10:out[i] = 1'b1;//reset的优先级更加高一些2'b11:out[i] = 1'b0;default : out[i]=out[i];endcaseendendendmodule
(17) Dual-edge rtiggered flip-flop
双沿触发器

module top_module (input clk,input d,output q
);reg P_q,N_q;always @ (posedge clk)beginP_q<=d;endalways @ (negedge clk)beginN_q<=d;endassign q = clk ? P_q:N_q;
endmodule
3.2.2 Counters
(1)Four-bit binnary counter

代码如下:
module top_module (input clk,input reset, // Synchronous active-high resetoutput [3:0] q);always @ (posedge clk) beginif(reset)q<=4'b0;else if(q==4'b1111)q<=4'b0;elseq<=q+1'b1;end
endmodule
(2)Decade counter
代码如下:
module top_module (input clk,input reset, // Synchronous active-high resetoutput [3:0] q);always @ (posedge clk) beginif(reset)q<=4'b0;else if(q>=4'b1001)q<=4'b0;elseq<=q+1'b1;end
endmodule
(3)Decade counter again

代码如下:
module top_module (input clk,input reset,output [3:0] q);always @ (posedge clk) beginif(reset)q<=4'b0001;else if(q>=4'b1010)q<=4'b1;elseq<=q+1'b1;end
endmodule
**(4)Slow decade counter **
注意这里在普通的计数器加了一个控制(slowena),当他为1时计数器才加1;

代码如下:
module top_module (input clk,input slowena,input reset,output [3:0] q);always @ (posedge clk) beginif(reset)q<=4'b0;else if (slowena)beginif(q>=4'b1001)q<=4'b0;elseq<=q+1'b1;endelseq<=q;end
endmodule
(5)Counter 1-12
已给4位计数器模块:

题目:用所给模块例化一个1~12 的计数器。
module top_module (input clk,input reset,input enable,output [3:0] Q,output c_enable,output c_load,output [3:0] c_d
); //使能端assign c_enable = enable; //重新装载值//当复位或者工作状态下计数值到达12时,装载值设为1assign c_load = reset | ((Q==4'd12) && (enable == 1'b1)); assign c_d = c_load;//例化count4 the_counter (clk, c_enable, c_load, c_d ,Q );endmodule
(6)Counter 1000
题目:1000Hz分频成1Hz
module top_module (input clk,input reset,output OneHertz,output [2:0] c_enable
); ////one: 个位 ten: 十位 hundred:百位wire [3:0] one, ten, hundred;// [2] [1] [0] assign c_enable = {one == 4'd9 && ten == 4'd9 ,one == 4'd9 , 1'b1};//1000hz 计数1000次时为1秒即1hzassign OneHertz = (one == 4'd9 && ten == 4'd9 && hundred == 4'd9);bcdcount counter0 (clk, reset, c_enable[0],one);bcdcount counter1 (clk, reset, c_enable[1],ten);bcdcount counter2 (clk, reset, c_enable[2],hundred);endmodule
(7)4-digit decimal counter

题目:构建4个十进制计数器,每个十进制数用四位表示
module top_module (input clk,input reset, // Synchronous active-high resetoutput [3:1] ena,output [15:0] q);reg [3:0] one,ten,hundred,thousand;//个位递增always @(posedge clk) beginif(reset || one == 4'd9) beginone <= 4'd0;end else beginone<= one + 1'b1;end end//十位递增always @(posedge clk) beginif(reset || ((one==4'd9) && (ten==4'd9))) beginten <= 4'd0;end else if(ena[1]) beginten <= ten +1'b1;endend//百位递增always @(posedge clk) beginif(reset || ((one==4'd9) && (ten ==4'd9) && (hundred==4'd9))) beginhundred <= 4'd0;end else if (ena[2])beginhundred <= hundred +1'b1;endend//千位递增always @(posedge clk) beginif(reset || ((one==4'd9)&& (ten ==4'd9) && (hundred==4'd9) && (thousand == 4'd9))) beginthousand <= 4'd0;end else if (ena[3])beginthousand <= thousand + 1'b1;endendassign q = {thousand,hundred,ten,one};//十位应该增加assign ena[1] = (one == 4'd9)?1'b1:1'b0;//百位应该增加assign ena[2] = ((one == 4'd9) && (ten == 4'd9))?1'b1:1'b0;//千位应该增加assign ena[3] = ((one == 4'd9) && (ten == 4'd9) && (hundred == 4'd9))?1'b1:1'b0;endmodule
(8)12-hour counter
难点在各种繁杂临界点判断
module top_module(input clk,input reset,input ena,output pm,output [7:0] hh,output [7:0] mm,output [7:0] ss); /**组合逻辑用wire变量类型*时序逻辑用reg 变量类型*/wire ss_en,ss_60_en;/*秒个位进十位的进位脉冲;秒计满60秒的进位脉冲*/reg [3:0] ss_one,ss_ten;/*秒的个位和十位*/wire mm_en,mm_60_en;/*分个位进十位的进位脉冲;分计满60分钟的进位脉冲*/reg [3:0] mm_one,mm_ten;/*分的个位和十位*/wire hh_en,pm_en;/*时个位进十位的进位脉冲;产生AM PM转换脉冲*/reg [3:0] hh_one,hh_ten;/*时的个位和十位*//** 真实的输出*/assign ss = {ss_ten,ss_one};assign mm = {mm_ten,mm_one};assign hh = {hh_ten,hh_one};/** 秒的个位*/always @(posedge clk) beginif(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00 AM*/ss_one <= 4'b0;endelse if(ena) beginif(ss_one == 4'd9) beginss_one <= 4'b0;endelsess_one <= ss_one +1'b1;endend/** 秒的十位*/assign ss_en = (ss_one==4'd9 && ena) ? 1'b1:1'b0; /*秒个位进十位的脉冲信号*/always @(posedge clk) beginif(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00:00 AM*/ss_ten <= 4'b0;endelse if(ss_en) beginif(ss_one == 4'd9 && ss_ten == 4'd5) beginss_ten <= 4'b0;endelsess_ten <= ss_ten + 1'b1;endend/** 分的个位*/assign ss_60_en = (ss_one==4'd9 && ss_ten == 4'd5 && ena) ? 1'b1:1'b0; /*秒计时60秒时,向分进位的脉冲*/always @(posedge clk) beginif(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00 :00 AM*/mm_one <= 4'b0;endelse if(ss_60_en) beginif(mm_one==4'd9) beginmm_one <= 4'b0;endelsemm_one <= mm_one + 1'b1;endend/** 分的十位*/assign mm_en = (mm_one == 4'd9 && ena && ss_one == 4'd9 && ss_ten ==4'd5)? 1'b1:1'b0;always @(posedge clk) beginif(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00:00 AM*/mm_ten <= 4'b0;endelse if(mm_en) beginif(mm_one == 4'd9 && mm_ten == 4'd5 && ss_one == 4'd9 && ss_ten == 4'd5) beginmm_ten <= 4'b0;endelsemm_ten <= mm_ten + 1'b1;endend/* * 时的个位*/assign mm_60_en = (mm_one == 4'd9 && mm_ten == 4'd5 && ss_one == 4'd9 && ss_ten == 4'd5)?1'b1:1'b0;always @(posedge clk) beginif(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00:00 AM*/hh_one <= 4'd2;endelse if(mm_60_en) begin /*注意判断0点和9点这两个临界条件*///12:59:59if(hh_one==4'd2 && hh_ten==4'd1 && mm_one == 4'd9 && mm_ten == 4'd5 && ss_one == 4'd9 && ss_ten == 4'd5) beginhh_one <= 4'b1; /*12点过后就是1点了*/end//9:59:59else if(hh_one==4'd9 && hh_ten==4'd0 && mm_one == 4'd9 && mm_ten == 4'd5 && ss_one == 4'd9 && ss_ten == 4'd5)beginhh_one <=4'b0; /*9点之后是10点*/endelse hh_one <= hh_one + 1'b1;endend/* * 时的十位*/assign hh_en = (hh_one==4'd9 && hh_ten==4'd0 && mm_one == 4'd9 && mm_ten == 4'd5 && ss_one == 4'd9 && ss_ten == 4'd5)?1'b1:1'b0;always @(posedge clk) beginif (reset) beginhh_ten <= 4'b1;endelse if ((hh_one == 4'd2) && (hh_ten == 4'd1) && (mm_one == 4'd9) && (mm_ten == 4'd5) && ena && (ss_one == 4'd9) && (ss_ten == 4'd5)) beginhh_ten <= 4'd0;end else if(hh_en) beginhh_ten <= 4'd1;endend//11:59:59 AM-> PMassign pm_en = ((hh_one == 4'd1) && (hh_ten == 4'd1) && (mm_one == 4'd9) && (mm_ten == 4'd5) && ena && (ss_one == 4'd9) && (ss_ten == 4'd5))?1'b1:1'b0;always @(posedge clk) beginif(reset) beginpm <= 1'b0;endelse if(pm_en) beginpm <= ~pm;endend
endmodule
3.2.3 Shift Registers
(1) 4-bit shift register

module top_module(input clk,input areset, // async active-high reset to zeroinput load,input ena,input [3:0] data,output reg [3:0] q); always @(posedge clk,posedge areset) begin /*异步复位,因此要添加areset */if(areset) begin /* 如果复位为1,则输出全部置零*/q <= 4'b0000;endelse if(load) begin/*load 比ena的优先级更加高*/q <= data[3:0];/*load有效时,输出装载data里的值*/ endelse if(ena) beginq <= {1'b0,{q[3:1]}};/*q[3] becomes zero, q[0] is shifted out and disappears*/endelseq <= q;end
endmodule
(2) Left/right rotator

module top_module(
input clk,
input load,
input [1:0] ena,
input [99:0] data,
output reg [99:0] q);
//1.建立一个一百位可左移可右移的寄存器,同步置位和使能//2.这个寄存器移入的位来自另一个寄存器的移出位//3.不像上一题的移入位是0,移出位舍弃//4.如果使能,这寄存器的每一位不会被修改或者舍弃,而是一直循环always @(posedge clk) beginif(load) begin /*load 优先级更高*/q <= data;endelse begincase (ena) 2'b00:q<=q;/*保持*/2'b01:q<={q[0],q[99:1]};/*向右移一位*/2'b10:q<={q[98:0],q[99]};/*向左移一位*/2'b11:q<=q;/*保持*/default:q<=q;endcaseendend
endmodule
(3) Left/right arithmetic shift by 1 or 8

逻辑移位:寄存器中整组数据进行移位,空位补0,只有数字位置的变化,无数量的变化。
算术移位:寄存器中带符号数的移位,移位时,符号位保持不变,仅数量变化。
module top_module(input clk,input load,input ena,input [1:0] amount,input [63:0] data,output reg [63:0] q); always @(posedge clk) beginif( load )beginq <= data;end else if(ena) begincase (amount)2'b00:q <= {q[62:0],1'b0};2'b01:q <= {q[55:0],8'b0};2'b10:q <= {q[63],q[63:1]};2'b11:q <= {{8{q[63]}},q[63:8]};endcaseend elseq <= q;end
endmodule
(4) 5-bit LFSR
Galois LFSR 就是在正常的移位寄存器中加入一些抽头(异或门)从而实现有效状态(不会有全零状态)最大化(2^n - 1)。

module top_module(input clk,input reset,output [4:0] q
);always @(posedge clk) beginif(reset)q <= 5'h1;elseq <= {q[0],q[4],{q[3]^q[0]},q[2],q[1]};end
endmodule
(5) 3-bit LFSR

1.图中r0,r1,r2分别连接SW[0], SW[1], SW[2。]
2.Clock 连接KEY[0], L连接KEY[1]。
3.Q连接LEDR
注意:模块化会使代码更加简洁
代码如下:
module top_module (input [2:0] SW, // Rinput [1:0] KEY, // L and clkoutput [2:0] LEDR); // Q//例化左边第一个dff_plus inst_left(.clk(KEY[0]),.in_1(SW[0]),.in_0(LEDR[2]),.sel(KEY[1]),.q(LEDR[0]));//例化中间那个dff_plus inst_mid(.clk(KEY[0]),.in_1(SW[1]),.in_0(LEDR[0]),.sel(KEY[1]),.q(LEDR[1]));//例化右边那个dff_plus inst_right(.clk(KEY[0]),.in_1(SW[2]),.in_0(LEDR[1]^LEDR[2]), //抽头.sel(KEY[1]),.q(LEDR[2]));
endmodule
//实现电路图中的一个模块
module dff_plus(input clk,input in_0,input in_1,input sel,output q
);//数据选择器输入wire in_temp;assign in_temp = sel ? in_1 : in_0;reg q_temp = 0;always @(posedge clk) beginq_temp <= in_temp;endassign q = q_temp;
endmodule
(6) 32-bit LFSR
题目:建立一个 32-bit Galois LFSR 抽头的位置放在32, 22, 2, 和 1.
module top_module(input clk,input reset, // Active-high synchronous reset to 32'h1output [31:0] q
); always @(posedge clk) beginif(reset)q <= 32'h1;else //tap 32 22 2 1q <= {q[0],{q[31:23]},{q[22]^q[0]},{q[21:3]},{q[2]^q[0]},{q[1]^q[0]}};end
endmodule
(6) Shift register

module top_module (input clk,input resetn, // synchronous resetinput in,output out);wire [2:0] qtemp;//输出中间态//例化左边第一个dff_res dff1(.clk(clk),.re_n(resetn),.in_temp(in),.q(qtemp[0]));//例化左边第二个dff_res dff2(.clk(clk),.re_n(resetn),.in_temp(qtemp[0]),.q(qtemp[1]));//例化左边第三个dff_res dff3(.clk(clk),.re_n(resetn),.in_temp(qtemp[1]),.q(qtemp[2]));//例化左边第四个dff_res dff4(.clk(clk),.re_n(resetn),.in_temp(qtemp[2]),.q(out));
endmodulemodule dff_res(input clk,input re_n,input in_temp,output q
);always @(posedge clk) begin //同步if(!re_n) //低有效q <= 1'b0;elseq <= in_temp;end
endmodule
(7) Shift register

module top_module (input [3:0] SW,input [3:0] KEY,output [3:0] LEDR
); //MUXDFF dff3(.clk(KEY[0]),.wData(KEY[3]),.ena(KEY[1]),.r_tmp(SW[3]),.l_tmp(KEY[2]),.q(LEDR[3]));MUXDFF dff2(.clk(KEY[0]),.wData(LEDR[3]),.ena(KEY[1]),.r_tmp(SW[2]),.l_tmp(KEY[2]),.q(LEDR[2]));MUXDFF dff1(.clk(KEY[0]),.wData(LEDR[2]),.ena(KEY[1]),.r_tmp(SW[1]),.l_tmp(KEY[2]),.q(LEDR[1]));MUXDFF dff0(.clk(KEY[0]),.wData(LEDR[1]),.ena(KEY[1]),.r_tmp(SW[0]),.l_tmp(KEY[2]),.q(LEDR[0]));endmodulemodule MUXDFF (input clk,input wData,input ena,input r_tmp,input l_tmp,output q
);wire [1:0] tmp;//组合逻辑assign tmp[0] = ena ? wData : q;assign tmp[1] = l_tmp ? r_tmp : tmp[0];//时序逻辑块always @(posedge clk) beginq <= tmp[1];end
endmodule
(8) 3-input LUT
可以解决组合逻辑使用门电路带来的延时的不确定性,LUT(查找表)相当于SRAM,把输入当成地址,输出当成该地址上的值。
module top_module (input clk,input enable,input S,input A, B, C,output Z ); reg [7:0] q;//第一、建立一个8bit移位寄存器,且是将S移入第0位,最高位舍弃。always @(posedge clk) beginif(enable)beginq <= {q[6:0],S};endelse beginq <= q;endend//A,B,C 为000 时 Z = q[0],,,assign Z = q[{A,B,C}]; //此处的{A,B,C}为3bit 3‘b000 = 3'd0;以此类推
endmodule
3.2.4 More Circuits
(1)Rule 90
题目:输出为旁边两位的异或,并且data【-1】和data【512】为0;
module top_module(input clk,input load,input [511:0] data,output [511:0] q ); always @(posedge clk) beginif(load) beginq <= data;end else begin// 错位相异或即可得到输出// q[512] and q[-1] are both zero q <= {1'b0,q[511:1]}^{q[510:0],1'b0};endend
endmodule
(2)Rule 110
一维细胞自动机

题目与上一题一样,但是真值表不一样,直接看也看不出来,因此使用了卡诺图化简(数电的基础知识)。

再表述出来即可。
module top_module(input clk,input load,input [511:0] data,output [511:0] q
);//left -- A ;center -- B ;right -- C ;reg [511:0] A,B,C;//左边那一位assign A = {1'b0,q[511:1]};//中间位assign B = q;//右边那一位assign C = {q[510:0],1'b0};always @(posedge clk)beginif(load)beginq <= data;endelse begin//根据题中给的真值表,卡诺图化简得来q <= ~B&C | ~A&B | B&~C;endend
endmodule
(3)Conway’s Game of Life 16*16
二维细胞自动机

举例(0,0)边界的邻居:

假设棋盘是这样的:下图举例了q[0]邻居位置,同理可以推测出棋盘上每一个位置的邻居

module top_module(input clk,input load,input [255:0] data,output [255:0] q ); //用于记录邻居存活的个数reg [3:0] sum;//下一个状态reg [255:0] q_next;always @(posedge clk) beginif(load)q <= data;else beginfor(integer i=0;i<256;i++) beginif(i==0)//左上角sum = q[1]+q[16]+q[17]+q[240]+q[241]+q[15]+q[31]+q[255];else if(i==15)//右上角sum = q[14]+q[16]+q[0]+q[240]+q[254]+q[30]+q[31]+q[255];else if(i==240)//左下角sum = q[0]+q[15]+q[239]+q[241]+q[1]+q[224]+q[225]+q[255];else if(i==255)//右下角sum = q[0]+q[15]+q[14]+q[224]+q[238]+q[240]+q[239]+q[254];else if(0<i & i<15)//上边界 //注意这里的书写不可以是0sum = q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17]+q[i+239]+q[i+240]+q[i+241];else if(i%16==0)//左边界sum = q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17]+q[i-16]+q[i-15]+q[i+31];else if(i%16==15)//右边界sum = q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i-17]+q[i-16]+q[i-15]+q[i-31];else if(240<i & i<255)//下边界sum = q[i-1]+q[i+1]+q[i-17]+q[i-16]+q[i-15]+q[i-239]+q[i-240]+q[i-241];else //非边界sum = q[i-1]+q[i+1]+q[i-17]+q[i-16]+q[i-15]+q[i+15]+q[i+16]+q[i+17];//判断规则见本题第一个图case (sum)2:q_next[i]=q[i]; //周围有两个则不变3:q_next[i]=1; //有三个则繁衍default:q_next[i]=0; //其余情况都减员endcaseendq <= q_next;endend
endmodule
3.2.5 Finite State Machines
(1)Simple FSM1

module top_module(input clk,input areset, // Asynchronous reset to state Binput in,output out);// //状态编码parameter A=0, B=1; reg state, next_state;always @(*) begin // This is a combinational always block// State transition logiccase (state)B: begin//看状态图 输入为1则下一个状态也是Bif(in == 1'b1)next_state = B;elsenext_state = A;endA: beginif(in == 1'b1)next_state = A;elsenext_state = B;endendcaseend//异步所以要包含areset的敏感列表always @(posedge clk, posedge areset) begin // This is a sequential always block// State flip-flops with asynchronous resetif(areset)state <= B;elsestate <= next_state;end// Output logicassign out = (state == B);
endmodule
(2)Simple FSM1s
与(1)一致 不过是同步复位了
// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);input clk;input reset; // Synchronous reset to state Binput in;output out;// reg out;parameter A = 0, B = 1;reg present_state, next_state;always @(posedge clk) begin //同步复位if (reset) begin present_state <= B;endelsepresent_state <= next_state;endalways @(*) begincase(present_state)A:beginif(in == 1'b1)next_state = A;elsenext_state = B;endB:beginif(in == 1'b1)next_state = B;elsenext_state = A;endendcaseendassign out = (present_state == B);
endmodule
(3)Simple FSM2
2输入1输出的异步复位状态机;
module top_module(input clk,input areset, // Asynchronous reset to OFFinput j,input k,output out); // parameter OFF=0, ON=1; reg state, next_state;always @(*) begincase(state)OFF: beginif(j== 1'b1)next_state = ON;elsenext_state = OFF;endON : beginif(k == 1'b1)next_state = OFF;elsenext_state = ON;endendcaseendalways @(posedge clk, posedge areset) beginif(areset)state <= OFF;else beginstate <= next_state;endend// Output logicassign out = (state == ON);endmodule
(3)Simple FSM2 S

module top_module(input clk,input reset, // Synchronous reset to OFFinput j,input k,output out); // parameter OFF=0, ON=1; reg state, next_state;always @(*) begin// State transition logiccase(state)OFF: beginif(j== 1'b1)next_state = ON;elsenext_state = OFF;endON : beginif(k == 1'b1)next_state = OFF;elsenext_state = ON;endendcaseendalways @(posedge clk) begin// State flip-flops with synchronous resetif(reset)state <= OFF;else beginstate <= next_state;endend// Output logicassign out = (state == ON);
endmodule
(4)Simple state transitions 3

module top_module(input in,input [1:0] state,output [1:0] next_state,output out); ////状态编码A=2'b00, B=2'b01, C=2'b10, D=2'b11.parameter A=0, B=1, C=2, D=3;// State transition logic: next_state = f(state, in)always @ (*)begincase (state)A: beginif(in == 1'b1)next_state = B;elsenext_state = A;endB: beginif(in == 1'b1)next_state = B;elsenext_state = C;endC: beginif(in == 1'b1)next_state = D;elsenext_state = A;endD: beginif(in == 1'b1)next_state = B;elsenext_state = C;endendcaseend// Output logic: out = f(state) for a Moore state machinealways @(*) begincase (state)A:out = 0;B:out = 0;C:out = 0;D:out = 1;endcaseend
endmodule
(5)Simple one-hot state transitions 3

(1)one-hot 编码:这种编码方式所用的D触发器比递增二进制编码多,状态数就等于触发器的数量,这使得译码电路就比较简单,因此他的速度非常快。
(2)格雷编码:能够避免进入错误状态,常用于高可靠性设计。
(3)递增二进制编码:效率高,但是会导致很大的组合逻辑。
ps:编码方式见下图:
module top_module(input in,input [3:0] state,output [3:0] next_state,output out); //parameter A=0, B=1, C=2, D=3;// State transition logic: Derive an equation for each state flip-flop.assign next_state[A] = state[A]&(~in) | state[C]&(~in);assign next_state[B] = state[A]&in | state[B]&in | state[D]∈assign next_state[C] = state[B]&(~in) | state[D]&(~in);assign next_state[D] = state[C]∈// Output logic: assign out = state[D];endmodule
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

