HDLBits_刷题_持续更新中

一、Getting Started

1.1Getting Started

1.1.1 编译后提示的意思

当你把代码写完然后编译之后,会给出相应的提示:

  • 如果语言的编译和线路的仿真都正确,并且符合题目要求,则会提示Success!
  • 编译错误,则会提示Compile Error
  • 电路仿真错误,则会提示Simulation Error
  • 如果语言的编译和线路的仿真都正确,但是不符合题目要求,则会提示Incorrect
  • 可以在My Stats 查看或者分享我们写题目的进度,可以理解为自动存档哈。如图1.1所示。
    HDLBits_刷题_持续更新中_第1张图片
1.1.2 网站的几个重要的板块

见下图即可。

HDLBits_刷题_持续更新中_第2张图片

1.1.3 问题的翻译与解答

HDLBits_刷题_持续更新中_第3张图片
意思:创建一个没有输入只有一个输出的电路,且输出总是为1。
解题代码如下:

module top_module( output one );
// Insert your code here
    assign one = 1'b1;
endmodule

1.2Output Zero

网站相关介绍也在第一节介绍之后将主要进行问题的翻译与解答。

1.2.1题目与解答

HDLBits_刷题_持续更新中_第4张图片
意思:创建一个没有输入,一个输出且输出为0的电路。
代码如下:

module top_module(
    output zero
);// Module body starts after semicolon
	assign zero=1'b0;
endmodule

二 、Verilog Language

2.1 Basics

2.1.1 Simple wire

HDLBits_刷题_持续更新中_第5张图片
题目:创建一个模块,将输入与输出像一根线一样连接起来。
代码如下:

module top_module( input in, output out );
	assign out = in ;
endmodule
2.1.2 Four wires

HDLBits_刷题_持续更新中_第6张图片
题目:创建一个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

HDLBits_刷题_持续更新中_第7张图片
题目:创建一个实现非门的模块。
代码如下:

module top_module( input in, output out );

    assign out = ~in;
endmodule
2.1.4 AND gate

HDLBits_刷题_持续更新中_第8张图片
题目:创建一个实现与门的模块。
代码如下:

module top_module( 
    input a, 
    input b, 
    output out );
    
	assign out = a & b;
endmodule
2.1.5 NOR gate

HDLBits_刷题_持续更新中_第9张图片
题目:创建一个实现或非门的模块。
代码如下:

module top_module( 
    input a, 
    input b, 
    output out );

    assign out = ~(a|b);
endmodule
2.1.6 XNOR gate

HDLBits_刷题_持续更新中_第10张图片
题目:创建一个实现同或门的模块。
代码如下:

module top_module( 
    input a, 
    input b, 
    output out );
    
    assign out = ~(a^b);
endmodule
2.1.7 Declaring wires

这个小节出现了线网数据类型wire,当内部结构越来越复杂时,一个模块的输入输出并非直接连接时,声明一个线网数据类型的变量(相当于中间变量)。
HDLBits_刷题_持续更新中_第11张图片
题目:实现如图所示的电路。创建两条中间线网(取任何你想取的名字)去连接与门和或门,
代码如下:

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

HDLBits_刷题_持续更新中_第12张图片
代码如下:

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;

HDLBits_刷题_持续更新中_第13张图片
代码如下:

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 declaration
	
    assign 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

HDLBits_刷题_持续更新中_第14张图片
题目:如图所示,注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和b
    assign 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

HDLBits_刷题_持续更新中_第15张图片
代码如下:

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

HDLBits_刷题_持续更新中_第16张图片

题目:如图所示。
代码如下:

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

HDLBits_刷题_持续更新中_第17张图片
题目:(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

HDLBits_刷题_持续更新中_第18张图片

题目: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

HDLBits_刷题_持续更新中_第19张图片
题目: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

HDLBits_刷题_持续更新中_第20张图片

题目: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

HDLBits_刷题_持续更新中_第21张图片

题目: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

HDLBits_刷题_持续更新中_第22张图片
题目:提供的模块如图所示。
代码如下(详解看注释):

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 @(*)
    begin
        case (sel)
            //组合逻辑所以阻塞赋值(=),注意不要用连续赋值关键词assign
            2'b00: q = d;  
            2'b01: q = temp_wire_left;
            2'b10: q = temp_wire_right;
            2'b11: q = temp_mod_out;
            default:;
        endcase
    end
endmodule

注意阻塞赋值与非阻塞赋值的不同(具体可以去看仿真的波形):

(1) 阻塞赋值(=) : 写在前面的语句先执行,写在后面的语句后执行,也就是说,它是顺序执行的,一般用于组合逻辑电路

(2) 非阻塞赋值(<=) :写在前面的语句与后面的语句同时执行,也就是说,它是并行执行的,跟书写顺序没有关系,一般用于时序逻辑电路。

2.3.6 Adder 1

HDLBits_刷题_持续更新中_第23张图片

题目:提供了一个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

HDLBits_刷题_持续更新中_第24张图片
题目:这里要求我们自己写出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};
endmodule

module 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

真值表与卡诺图如下:
HDLBits_刷题_持续更新中_第25张图片

2.3.8 Carry-select adder

前几个小节练习的进位加法器,只有前一个加法器加完之后才能进行后续的相加,这样使得数据相加很慢,可以用进位选择加法器来加快加法运算的速度。
HDLBits_刷题_持续更新中_第26张图片
题目:已经提供了模块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 @(*)
    begin
        case(mod_1_cout)
            1'b0: mod_mid_down_sum = mod_mid_sum;
            1'b1: mod_mid_down_sum = mod_down_sum;
            default:;
        endcase;
    end
    assign sum={mod_mid_down_sum,mod_up_sum};
endmodule
2.3.9 Adder-subtractor

加/减法器,当sub为0时为为加法器,为1时为减法器。这个也比较好理解,二进制的减法就是加上补码(一个数的补码就是,取反再低位加1)
一个数异或0就是本身,异或1就是取反。

HDLBits_刷题_持续更新中_第27张图片
代码如下:

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 @(*)
    begin
        out_alwaysblock = a & b;
    end
endmodule
2.4.2 Always blocks(clocked)

在这里插入图片描述
组合逻辑中,使用阻塞赋值,时序逻辑中使用非阻塞赋值。
HDLBits_刷题_持续更新中_第28张图片
题目:用三种当时构建异或门。
代码如下:

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 @(*)
    begin
        out_always_comb = a^b;
    end
    always @(posedge clk)
    begin
        out_always_ff <= a^b;
    end
    
endmodule
2.4.3 If statement

HDLBits_刷题_持续更新中_第29张图片
终于来到了我们熟悉的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 @(*)
    begin
        if(sel_b1 & sel_b2)
        begin
        	 out_always = b;
        end
        else  begin
             out_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;
        else
           shut_off_computer = 0;
            
    end

    always @(*) begin
        if (~arrived)
             //还没到达目的地,油箱没空就保持行驶
           keep_driving = ~gas_tank_empty;
        else
           //到了就不行驶了
           keep_driving = 0;
    end

endmodule
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 circuit
        case(sel) 
            //注意这里不需要begin
        	3'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;
        endcase
    end

endmodule
2.4.6 Priority encoder

优先编码器,使用case语句即可。
代码如下:

module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
    
    always@(*) begin
    	case (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;
    	endcase
    end
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 @(*) begin
        casez(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;
        endcase
    end
endmodule

方法二、casex

  module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
    always @(*) begin
        casex(in) //使用casex
            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;
        endcase  //都是endcase
    end
endmodule

方法三、用问号来替代z或x

 module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
    always @(*) begin
        casez(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;
        endcase
    end
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:begin
            up = 1'b0;down = 1'b0; left = 1'b0;right = 1'b0;
        end
        endcase   
    end
endmodule
  

2.5 More Verilog Features

2.5.1 Conditional ternary operator

HDLBits_刷题_持续更新中_第30张图片
题目:使用条件运算符从四个无符号数据中找到最小的数据。
代码如下:

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

使用方式如下图所示:
HDLBits_刷题_持续更新中_第31张图片
题目:用精简算子,给一个8位的数据,做一个偶校验。
代码如下:

module top_module (
    input [7:0] in,
    output parity); 
    
	assign parity = ^in;
    
endmodule
  
2.5.3 Reduction:Even wider gates

HDLBits_刷题_持续更新中_第32张图片
代码如下:

module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
	assign out_and=&in;
    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 @(*)
    begin
        for(int i=0;i<100;i=i+1) begin
            out[i] =in[99-i]; 
        end
    end
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) begin
            if(in[i]==1'b1)begin
                out=out+1;
            end
            else
                out=out;
        end
    end 
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用于接顶层模块cin
                adder_full add100(
                    .a(a[i]),
                    .b(b[i]),
                    .cin(cin),
                    .cout(cout[i]),
                    .sum(sum[i])
                );
            end
            else begin
               adder_full add100(
                    .a(a[i]),
                    .b(b[i]),
                    .cin(cout[i-1]),
                    .cout(cout[i]),
                    .sum(sum[i])
                );
                end
        end       
    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

HDLBits_刷题_持续更新中_第33张图片
BCD加法器就是用4个二进制表示一个十进制数的加法器。
代码如下:

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );

    wire [99:0] cout_temp;
    
    generate
        genvar i;
        for(i=0;i<100;i++)begin:add10
            if(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]);
            end
            else begin
                bcd_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]);
            end
        end
    endgenerate
    assign 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

HDLBits_刷题_持续更新中_第34张图片
代码如下:

module top_module (
    input in1,
    input in2,
    output out);

    assign out = in1 & (~in2);
        
endmodule
3.1.1.5 Two gate

HDLBits_刷题_持续更新中_第35张图片

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

HDLBits_刷题_持续更新中_第36张图片
代码如下:

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

真值表如图所示:
HDLBits_刷题_持续更新中_第37张图片
利用真值表画卡诺图即可。
代码如下:

module top_module( 
    input x3,
    input x2,
    input x1,  // three inputs
    output 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

HDLBits_刷题_持续更新中_第38张图片
列出真值表即可得出答案。
代码如下:

module top_module ( input x, input y, output z );
    assign z=~(x^y);
    
endmodule
3.1.1.12 Combine circuts A and B

HDLBits_刷题_持续更新中_第39张图片
注意他这里的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;
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
3.1.1.13 Ring or vibrate

HDLBits_刷题_持续更新中_第40张图片
题目:如果ring=1的情况下,要么闹铃要么震动,但是两者不会同时发生。当vibrate_mode=1 时,震动否则闹铃。
代码如下:

module top_module (
    input ring,
    input vibrate_mode,
    output ringer,       // Make sound
    output motor         // Vibrate
);

    assign motor = ring & vibrate_mode;
    assign ringer= ring & ~vibrate_mode ;
endmodule
3.1.1.14 Thermostat

HDLBits_刷题_持续更新中_第41张图片
列出真值表,如下:HDLBits_刷题_持续更新中_第42张图片
卡诺图如下:
HDLBits_刷题_持续更新中_第43张图片
代码如下:

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 @(*)
    begin
        temp=0;
        for(int i=0;i<3;i=i+1) begin
            if(in[i]==1'b1)begin
            	temp=temp+1;    
            end
            else begin
                temp=temp;
            end
        end
        out=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 @(*)
    begin
        case (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;	
        endcase
    end
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]);  
    
endmodule

module full_add( 
    input a, b, cin,
    output cout, sum );

    assign {cout ,sum } = a+b+cin;
         
endmodule
3.1.3.4 Adder

HDLBits_刷题_持续更新中_第44张图片

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;
endmodule

module full_add( 
    input a, b, cin,
    output cout, sum );

    assign {cout ,sum } = a+b+cin;
         
endmodule
3.1.3.5 Signed addition overflow

在这里插入图片描述

有符号的运算,考虑溢出情况(见下图);
HDLBits_刷题_持续更新中_第45张图片
代码如下:

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

HDLBits_刷题_持续更新中_第46张图片

module top_module ( 
    input [15:0] a, b,
    input cin,
    output cout,
    output [15:0] sum );

    wire [3:0] temp;
    generate
        genvar i;
        for(i=0;i<4;i=i+1)begin :add_bcd
            if(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]); 
            else
                bcd_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]); 
        end
    endgenerate
    assign cout=temp[3];
    
endmodule
3.1.4 Karnaugh Map to Circuit

卡诺图走起!!!!!

3.1.4.1 3-variable

HDLBits_刷题_持续更新中_第47张图片

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

HDLBits_刷题_持续更新中_第48张图片
代码如下:

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

HDLBits_刷题_持续更新中_第49张图片
代码如下:
注意其中的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

HDLBits_刷题_持续更新中_第50张图片
直接硬刚吧!!!没法化简。
代码如下:

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(或与)
在这里插入图片描述
解题过程如下图:
HDLBits_刷题_持续更新中_第51张图片
代码如下:

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

HDLBits_刷题_持续更新中_第52张图片
代码如下:

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

HDLBits_刷题_持续更新中_第53张图片
代码如下:

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

HDLBits_刷题_持续更新中_第54张图片
代码如下:

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 circuits
    input d,
    output reg q );//
    //D 触发器 上升沿有效
    always @(posedge clk)
    begin
        q<=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)
    begin
        q<=d;
    end
endmodule

(3) DFF with reset
在这里插入图片描述
代码如下:

module top_module (
    input clk,
    input reset,            // Synchronous reset
    input [7:0] d,
    output [7:0] q
);
    //同步复位
    always @(posedge clk)
    begin
        //注意这里是高电平有效
        if(reset)
            q<=8'b0;
		else
            q<=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;
		else
            q<=d;
    end
endmodule

(5) DFF with asynchronous reset
在这里插入图片描述
代码如下:

module top_module (
    input clk,
    input areset,   // active high asynchronous reset
    input [7:0] d,
    output [7:0] q
);
    //时钟上升沿有效
    always @(posedge clk or posedge areset )
    begin
        if(areset)
            q<=8'b0;
		else
            q<=d;
    end
endmodule

(6) DFF with byte enable
HDLBits_刷题_持续更新中_第55张图片
代码如下:

module top_module (
    input clk,
    input resetn,
    input [1:0] byteena,
    input [15:0] d,
    output [15:0] q
);

    always @(posedge clk)
    begin
        if(!resetn)
            q<=16'b0;
        else begin
            q[15:8] <= byteena[1]?d[15:8]:q[15:8];
            q[7:0]  <= byteena[0]?d[7:0] :q[7:0 ];
        end
 			
    end
endmodule

(7) D Latch

module top_module (
    input d, 
    input ena,
    output q);

    always @ (*)
    begin
        if(ena)
            q=d;
        else
            q=q;
    end
endmodule

(8) DFF
HDLBits_刷题_持续更新中_第56张图片
异步复位
代码如下:

module top_module (
    input clk,
    input d, 
    input ar,   // asynchronous reset
    output q);
    always @ (posedge clk or posedge ar)
    begin
        if(ar)
            q<=0;
        else
            q<=d;
    end

endmodule

(9) DFF
HDLBits_刷题_持续更新中_第57张图片
代码如下:

module top_module (
    input clk,
    input d, 
    input r,   // synchronous reset
    output q);
    always @ (posedge clk)
    begin
        if(r)
            q<=0;
        else
            q<=d;
    end
endmodule

(10) DFF + gate
HDLBits_刷题_持续更新中_第58张图片
代码如下:

module top_module (
    input clk,
    input in, 
    output out);

    always @ (posedge clk)
    begin
		out<=in^out;
    end
endmodule

(11) MUX and DFF
HDLBits_刷题_持续更新中_第59张图片
注意这里一定要审题:不要把整个图都给他搞出来了
代码如下:

module top_module (
	input clk,
	input L,
	input r_in,
	input q_in,
	output reg Q);

    always @(posedge clk)
    begin
        Q<=L?r_in:q_in;
    end
endmodule

(12) MUX and DFF
HDLBits_刷题_持续更新中_第60张图片
代码如下:

module top_module (
    input clk,
    input w, R, E, L,
    output Q
);

    always @(posedge clk)
    begin
        Q<=L?R:(E?w:Q);
    end
endmodule

(13) DFFs and gates
HDLBits_刷题_持续更新中_第61张图片
//正确代码

module top_module (
    input clk,
    input x,
    output z
); 
    
    reg [2:0]	Q;
    always@(posedge clk)begin
        Q[0] <= Q[0] ^ x;
        Q[1] <= ~Q[1] & x;
        Q[2] <= ~Q[2] | x;
    end
    
    assign 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);
    
endmodule

module DFF (
	input clk,
    input d,
    output reg q);
    
always@(posedge clk)
    q <= d;
endmodule

(14) Creat circuit from trurh table
HDLBits_刷题_持续更新中_第62张图片
代码如下:

module top_module (
    input clk,
    input j,
    input k,
    output Q); 

    always @(posedge clk)
    begin
        Q <=j? (k?~Q:1):(k?0:Q);
    end
endmodule

(15) Detect an egde
HDLBits_刷题_持续更新中_第63张图片
题目:检测上升沿
代码如下:

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)
    begin
        in_temp <= in;
        pedge   <= in & ~in_temp; 
    end
endmodule

(15) Detect both egde
HDLBits_刷题_持续更新中_第64张图片

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)
    begin
        in_temp <= in;
        //便于理解写出了两种情况
        // pedge   <= (in & ~in_temp) & (~in & in_temp); 
        //更加简洁的写法
        anyedge   <= in ^ in_temp; 
    end
endmodule

(16) Egde capture register
HDLBits_刷题_持续更新中_第65张图片

module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);
	//捕获下降沿
    reg [31:0] in_temp;
    always @(posedge clk)   
    begin
        in_temp <= in;
        //每一位都要检测
        for(int i=0;i<32;i=i+1)
        begin
            //这里的case条件用到了拼接运算符
            //当然这里使用if语句也完全ok
            case ({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];
             endcase
        end
    end
    
endmodule

(17) Dual-edge rtiggered flip-flop
双沿触发器
HDLBits_刷题_持续更新中_第66张图片

module top_module (
    input clk,
    input d,
    output q
);

    reg P_q,N_q;
    always @ (posedge clk)
    begin
        P_q<=d;
    end
    always @ (negedge clk)
    begin
        N_q<=d;
    end
    assign q = clk ? P_q:N_q;
endmodule
3.2.2 Counters
(1)Four-bit binnary counter

HDLBits_刷题_持续更新中_第67张图片
代码如下:

module top_module (
    input clk,
    input reset,      // Synchronous active-high reset
    output [3:0] q);

    always @ (posedge clk) begin
        if(reset)
            q<=4'b0;
        else if(q==4'b1111)
            q<=4'b0;
        else
            q<=q+1'b1;
    end
endmodule
(2)Decade counter

代码如下:

module top_module (
    input clk,
    input reset,        // Synchronous active-high reset
    output [3:0] q);

    always @ (posedge clk) begin
        if(reset)
            q<=4'b0;
        else if(q>=4'b1001)
            q<=4'b0;
        else
            q<=q+1'b1;
    end
endmodule
(3)Decade counter again

在这里插入图片描述
代码如下:

module top_module (
    input clk,
    input reset,
    output [3:0] q);

        always @ (posedge clk) begin
        if(reset)
            q<=4'b0001;
            else if(q>=4'b1010)
            q<=4'b1;
        else
            q<=q+1'b1;
    end
endmodule

**(4)Slow decade counter **
注意这里在普通的计数器加了一个控制(slowena),当他为1时计数器才加1;
HDLBits_刷题_持续更新中_第68张图片
代码如下:

module top_module (
    input clk,
    input slowena,
    input reset,
    output [3:0] q);

    always @ (posedge clk) begin
        if(reset)
            q<=4'b0;
        else if (slowena)begin
            if(q>=4'b1001)
            	q<=4'b0;
        	else
            	q<=q+1'b1;
    	end
        else
            q<=q;
    end
endmodule
(5)Counter 1-12

已给4位计数器模块:
HDLBits_刷题_持续更新中_第69张图片
题目:用所给模块例化一个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时,装载值设为1
    assign 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秒即1hz
    assign 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 reset
    output [3:1] ena,
    output [15:0] q);
    
    reg [3:0] one,ten,hundred,thousand;
    //个位递增
    always @(posedge clk) begin
        if(reset || one == 4'd9) begin
            one <= 4'd0;
        end else begin
            one<= one + 1'b1;
        end   
    end
    //十位递增
    always @(posedge clk) begin
        if(reset || ((one==4'd9) && (ten==4'd9))) begin
            ten <= 4'd0;
        end else if(ena[1]) begin
            ten <= ten +1'b1;
        end
    end
    //百位递增
    always @(posedge clk) begin
        if(reset || ((one==4'd9) && (ten ==4'd9) && (hundred==4'd9))) begin
            hundred <= 4'd0;
        end else if (ena[2])begin
            hundred <= hundred +1'b1;
        end
    end
    //千位递增
    always @(posedge clk) begin
        if(reset || ((one==4'd9)&& (ten ==4'd9) && (hundred==4'd9) && (thousand == 4'd9))) begin
            thousand <= 4'd0;
        end else if (ena[3])begin
            thousand <= thousand + 1'b1;
        end
    end
    assign 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) begin
        if(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00 AM*/
            ss_one <= 4'b0;
        end
        else if(ena) begin
            if(ss_one == 4'd9) begin
                ss_one <= 4'b0;
            end
            else
                ss_one <= ss_one +1'b1;
        end
    end
    /*
     * 秒的十位
     */
    assign ss_en = (ss_one==4'd9 && ena) ? 1'b1:1'b0; /*秒个位进十位的脉冲信号*/
    always @(posedge clk) begin
        if(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00:00 AM*/
            ss_ten <= 4'b0;
        end
        else if(ss_en) begin
            if(ss_one == 4'd9 && ss_ten == 4'd5) begin
                ss_ten <= 4'b0;
            end
            else
                ss_ten <= ss_ten + 1'b1;
        end
    end
     /*
     * 分的个位
     */
    assign ss_60_en = (ss_one==4'd9 && ss_ten == 4'd5 && ena) ? 1'b1:1'b0; /*秒计时60秒时,向分进位的脉冲*/
    always @(posedge clk) begin
        if(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00 :00 AM*/
            mm_one <= 4'b0;
        end
        else if(ss_60_en) begin
            if(mm_one==4'd9) begin
                mm_one <= 4'b0;
            end
            else
                mm_one <= mm_one + 1'b1;
        end
    end
    /*
     * 分的十位
     */
    assign mm_en = (mm_one == 4'd9 && ena && ss_one == 4'd9 && ss_ten ==4'd5)? 1'b1:1'b0;
    always @(posedge clk) begin
        if(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00:00 AM*/
            mm_ten <= 4'b0;
        end
        else if(mm_en) begin
            if(mm_one == 4'd9 && mm_ten == 4'd5 && ss_one == 4'd9 && ss_ten == 4'd5) begin
                mm_ten <= 4'b0;
            end
            else
                mm_ten <= mm_ten + 1'b1;
        end
    end
    /* 
     * 时的个位
     */
    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) begin
        if(reset) begin/*reset的优先级高于enable,并且复位后时钟为12:00:00 AM*/
            hh_one <= 4'd2;
        end
         else if(mm_60_en) begin /*注意判断0点和9点这两个临界条件*/
             //12:59:59
             if(hh_one==4'd2 && hh_ten==4'd1 && mm_one == 4'd9 && mm_ten == 4'd5 && ss_one == 4'd9 && ss_ten == 4'd5) begin
                hh_one <= 4'b1; /*12点过后就是1点了*/
             end
             //9:59:59
             else 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)begin
                hh_one <=4'b0; /*9点之后是10点*/
             end
             else 
                hh_one <= hh_one + 1'b1;
        end
    end
    /* 
     * 时的十位
     */
    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) begin
    	if (reset) begin
        	hh_ten <= 4'b1;
    	end
    	else 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)) begin
        	hh_ten <= 4'd0;
    	end   
    	else if(hh_en) begin
        	hh_ten <= 4'd1;
    	end
    end
    //11:59:59 AM-> PM
    assign 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) begin
        if(reset) begin
            pm <= 1'b0;
        end
        else if(pm_en) begin
            pm <= ~pm;
        end
    end
endmodule
3.2.3 Shift Registers
(1) 4-bit shift register

HDLBits_刷题_持续更新中_第70张图片

module top_module(
    input clk,
    input areset,  // async active-high reset to zero
    input 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;
        end
        else if(load) begin/*load 比ena的优先级更加高*/
            q <= data[3:0];/*load有效时,输出装载data里的值*/ 
        end
        else if(ena) begin
            q <= {1'b0,{q[3:1]}};/*q[3] becomes zero, q[0] is shifted out and disappears*/
        end
        else
            q <= q;
    end
endmodule
(2) Left/right rotator

HDLBits_刷题_持续更新中_第71张图片
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) begin
        if(load) begin /*load 优先级更高*/
            q <= data;
        end
        else begin
            case (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;
            endcase
        end
    end
endmodule
(3) Left/right arithmetic shift by 1 or 8

HDLBits_刷题_持续更新中_第72张图片
逻辑移位:寄存器中整组数据进行移位,空位补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) begin
        if( load )begin
            q <= data;
        end else if(ena) begin
            case (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]};
            endcase
        end else
            q <= q;
    end
endmodule
(4) 5-bit LFSR

Galois LFSR 就是在正常的移位寄存器中加入一些抽头(异或门)从而实现有效状态(不会有全零状态)最大化(2^n - 1)。
HDLBits_刷题_持续更新中_第73张图片

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

HDLBits_刷题_持续更新中_第74张图片

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,      // R
	input [1:0] KEY,     // L and clk
	output [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) begin
        q_temp <= in_temp;
    end
    assign 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'h1
    output [31:0] q
); 
    always @(posedge clk) begin
        if(reset)
            q <= 32'h1;
        else //tap 32                   22                    2          1
            q <= {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

HDLBits_刷题_持续更新中_第75张图片

module top_module (
    input clk,
    input resetn,   // synchronous reset
    input 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)
    );  
endmodule

module dff_res(
    input clk,
    input re_n,
    input in_temp,
    output q
);
    always @(posedge clk) begin //同步
        if(!re_n) //低有效
            q <= 1'b0;
        else
            q <= in_temp;
    end
endmodule
(7) Shift register

HDLBits_刷题_持续更新中_第76张图片

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])
    );
    
endmodule

module 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) begin
        q <= 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) begin
        if(enable)begin
            q <= {q[6:0],S};
        end
        else begin
            q <= q;
        end
    end
    //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) begin
        if(load) begin
            q <= data;
        end else begin
            //     错位相异或即可得到输出
            //     q[512]       and          q[-1] are both zero            
            q <= {1'b0,q[511:1]}^{q[510:0],1'b0};
        end
    end
endmodule
(2)Rule 110

一维细胞自动机
HDLBits_刷题_持续更新中_第77张图片
题目与上一题一样,但是真值表不一样,直接看也看不出来,因此使用了卡诺图化简(数电的基础知识)。
HDLBits_刷题_持续更新中_第78张图片
再表述出来即可。

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)begin
        if(load)begin
        	q <= data;
        end
        else begin
            //根据题中给的真值表,卡诺图化简得来
            q <= ~B&C | ~A&B | B&~C;
        end
    end
endmodule
(3)Conway’s Game of Life 16*16

二维细胞自动机
HDLBits_刷题_持续更新中_第79张图片
举例(0,0)边界的邻居:
在这里插入图片描述
假设棋盘是这样的:下图举例了q[0]邻居位置,同理可以推测出棋盘上每一个位置的邻居
HDLBits_刷题_持续更新中_第80张图片

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) begin
        if(load)
            q <= data;
        else begin
            for(integer i=0;i<256;i++) begin
                if(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)//上边界 //注意这里的书写不可以是0
                    sum = 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; //其余情况都减员
                endcase
            end
            q <= q_next;
        end
    end
endmodule
3.2.5 Finite State Machines
(1)Simple FSM1

HDLBits_刷题_持续更新中_第81张图片

module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output out);//  
	//状态编码
    parameter A=0, B=1; 
    reg state, next_state;
    always @(*) begin    // This is a combinational always block
        // State transition logic
        case (state)
            B: begin
            	//看状态图 输入为1则下一个状态也是B
                if(in == 1'b1)
                    next_state = B;
                else
                    next_state = A;
            end
            A: begin
                if(in == 1'b1)
                    next_state = A;
                else
                    next_state = B;
            end
        endcase
    end
	//异步所以要包含areset的敏感列表
    always @(posedge clk, posedge areset) begin    // This is a sequential always block
        // State flip-flops with asynchronous reset
        if(areset)
            state <= B;
        else
            state <= next_state;
    end
    // Output logic
    assign 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 B
    input 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;
        end
        else
            present_state <= next_state;
    end
    always @(*) begin
        case(present_state)
            A:begin
                if(in == 1'b1)
                    next_state = A;
                else
                    next_state = B;
            end
            B:begin
                if(in == 1'b1)
                    next_state = B;
                else
                    next_state = A;
            end
        endcase
    end
    
    assign out = (present_state == B);
endmodule
(3)Simple FSM2

HDLBits_刷题_持续更新中_第82张图片2输入1输出的异步复位状态机;

module top_module(
    input clk,
    input areset,    // Asynchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF=0, ON=1; 
    reg state, next_state;

    always @(*) begin
        case(state)
            OFF: begin
                if(j== 1'b1)
                    next_state = ON;
                else
                    next_state = OFF;
            end
            ON : begin
                if(k == 1'b1)
                    next_state = OFF;
                else
                    next_state = ON;
            end
        endcase
    end

    always @(posedge clk, posedge areset) begin
        if(areset)
            state <= OFF;
        else begin
            state <= next_state;
        end
    end

    // Output logic
    assign out = (state == ON);

endmodule

(3)Simple FSM2 S

HDLBits_刷题_持续更新中_第83张图片

module top_module(
    input clk,
    input reset,    // Synchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF=0, ON=1; 
    reg state, next_state;
    always @(*) begin
        // State transition logic
        case(state)
            OFF: begin
                if(j== 1'b1)
                    next_state = ON;
                else
                    next_state = OFF;
            end
            ON : begin
                if(k == 1'b1)
                    next_state = OFF;
                else
                    next_state = ON;
            end
        endcase
    end
    always @(posedge clk) begin
        // State flip-flops with synchronous reset
        if(reset)
            state <= OFF;
        else begin
            state <= next_state;
        end
    end
    // Output logic
     assign out = (state == ON);
endmodule
(4)Simple state transitions 3

HDLBits_刷题_持续更新中_第84张图片

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 @ (*)begin
        case (state)
            A: begin
                if(in == 1'b1)
					next_state = B;
                else
                    next_state = A;
            end
           B: begin
                if(in == 1'b1)
					next_state = B;
                else
                    next_state = C;
            end
           C: begin
                if(in == 1'b1)
					next_state = D;
                else
                    next_state = A;
            end
           D: begin
                if(in == 1'b1)
					next_state = B;
                else
                    next_state = C;
            end
        endcase
    end
    // Output logic:  out = f(state) for a Moore state machine
    always @(*) begin
        case (state)
            A:out = 0;
            B:out = 0;
            C:out = 0;
            D:out = 1;
        endcase
    end
endmodule
(5)Simple one-hot state transitions 3

HDLBits_刷题_持续更新中_第85张图片

(1)one-hot 编码:这种编码方式所用的D触发器比递增二进制编码多,状态数就等于触发器的数量,这使得译码电路就比较简单,因此他的速度非常快。
(2)格雷编码:能够避免进入错误状态,常用于高可靠性设计。
(3)递增二进制编码:效率高,但是会导致很大的组合逻辑。
ps:编码方式见下图:
HDLBits_刷题_持续更新中_第86张图片

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]&in;
    assign next_state[C] = state[B]&(~in) | state[D]&(~in);
    assign next_state[D] = state[C]&in;

    // Output logic: 
    assign out = state[D];

endmodule

你可能感兴趣的:(数字IC,学习,fpga开发,Verilog)