HDLBits题解与知识点总结(更新中)

一、Getting Started

1.1、Getting Started

module top_module( output one );

// Insert your code here
    assign one = 1;

endmodule

1.2、Output Zero 

module top_module ( output zero );
	
	assign 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

module top_module( 
    input a,b,c,
    output w,x,y,z );
    assign w = a;
    assign x = b;
    assign y = b;
    assign z = c;

endmodule

2.1.3、Inverter

知识点:

1、位运算符总结:

  • ~        //取反
  • &        //按位与
  • |         //按位或
  • ^         //按位异或
  • ~^       //按位同或
module top_module( input in, output out );
    assign out = ~in;
endmodule

2.1.4、AND gate

知识点:

1、要注意区分“按位与(&)”和“逻辑与(&&)”

法一:

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

法二:

知识点:熟悉三目运算符,但是不可取,逻辑太复杂了,要用的器件更多,浪费资源。

module top_module( 
    input a, 
    input b, 
    output out );
    assign out = ( a == 1 && b == 1 ) ? 1 : 0;
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

知识点:同或(异或非门)

~a^b 等价于a~^b

module top_module( 
    input a, 
    input b, 
    output out );
    assign out = a~^b;

endmodule

2.1.7、Declaring wires

知识点:小个小型组合逻辑电路的实现

module top_module (
	input a,
	input b,
	input c,
	input d,
	output out,
	output out_n );
	
	wire w1, w2;		// Declare two wires (named w1 and w2)
	assign w1 = a&b;	// First AND gate
	assign w2 = c&d;	// Second AND gate
	assign out = w1|w2;	// OR gate: Feeds both 'out' and the NOT gate

	assign out_n = ~out;	// NOT gate
	
endmodule

2.1.8、7458

module top_module ( 
    input p1a, p1b, p1c, p1d, p1e, p1f,
    output p1y,
    input p2a, p2b, p2c, p2d,
    output p2y );
    wire w1, w2, w3, w4;
    assign w1 = p2a & p2b;
    assign w2 = p1c & p1b & p1a;
    assign w3 = p2c & p2d;
    assign w4 = p1f & p1e & p1d;
    assign p1y = w2 | w4;
    assign p2y = w1 | w3;
endmodule

2.2、Vector

2.2.1、Vectors

知识点:

类似于这种排线:

 

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 o0 = vec[0];
    assign o1 = vec[1];
    assign o2 = vec[2];
    assign outv = vec;

endmodule

2.2.2、Vectors in more detail

知识点:

1、vector声明:

wire [7:0] w;         // 8-bit wire
reg  [4:1] x;         // 4-bit reg
output reg [0:0] y;   // 1-bit reg, 虽然只有一根,但是他任然是一个vector
input wire [3:-2] z;  // 6-bit wire input ,里面允许有负数
output [3:0] a;       // 4-bit output wire,没有特殊声明的话,默认是wire类型
wire [0:7] b;         // 8-bit wire ,其中b[0]是最高位

2、Implicit nets

wire [2:0] a, c; // Two vectors
assign a = 3'b101; // a = 101 
assign b = a; // b = 1 ,关键在这里,这里默认创建的b是1-bit的,他只会取保留最低为的值
assign c = b; // c = 001 <-- bug ,这样c就不是我们预想的样子,接下来用c运算则会出现错误。
my_module i1 (d,e); // d and e are implicitly one-bit wide if not declared.
                    // This could be a bug if the port was intended to be a vector.
避免犯错:在开头的地方加上,`default_nettype

3、二维矩阵的定义

reg [7:0] mem [255:0];   // 256个8-bit
reg mem2 [28:0];         // 29个1-bit(1-bit是默认出来的)

4、向量中的部分元素获取

w[3:0]      // 获取w向量中的低四位
x[1]        // 获取w向量中的第一位
x[1:1]      // 同上,获取w向量中的第一位
z[-1:-2]    // z向量的最低两位
b[3:0]      // 若定义:wire [0:5] b,则b[3:0]表达是非法的。向量部分选择必须与声明的方向匹配                                 ,这里最容易出错。
assign w[3:0] = b[0:3];    // w[3]=b[0], w[2]=b[1], 以此类推
`default_nettype none     // Disable implicit nets. Reduces some types of bugs.
module top_module( 
    input wire [15:0] in,
    output wire [7:0] out_hi,
    output wire [7:0] out_lo );
    assign out_lo = in[7:0];
    assign out_hi = in[15:8];

endmodule

2.2.3、Vector part select

知识点:拼接符({})的灵活运用

module top_module( 
    input [31:0] in,
    output [31:0] out );//
    assign out[31:0] = {in[7:0],in[15:8],in[23:16],in[31:24]};
    // assign out[31:24] = ...;

endmodule

2.2.4、Bitwise operators

知识点:区分按位或与逻辑或

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 = a | b;
    assign out_or_logical = a || b;
    assign out_not = {~b,~a};

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 = in[0]&in[1]&in[2]&in[3];
    assign out_or = in[0]|in[1]|in[2]|in[3];
    assign out_xor = in[0]^in[1]^in[2]^in[3];

endmodule

2.2.6、Vector concatenation operator

知识点:拼接符({})

module top_module (
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z );//
	
    assign w = {a[4:0],b[4:2]};
    assign x = {b[1:0],c[4:0],d[4]};
    assign y = {d[3:0],e[4:1]};
    assign z = {e[0],f[4:0],1'b1,1'b1};
    // assign { ... } = { ... };

endmodule

2.2.7、Vector reveral 1

法一:用拼接符来做

module top_module( 
    input [7:0] in,
    output [7:0] out
);
        assign out = {in[0],in[1],in[2],in[3],in[4],in[5],in[6],in[7]};

endmodule

法二:引入循环

module top_module( 
    input [7:0] in,
    output [7:0] out
);
    integer i;
    always @(*) begin	
		for (i=0; i<8; i = i + 1)	// int is a SystemVerilog type. Use integer for pure Verilog.
			out[i] = in[8-i-1];
	end

endmodule

 法三:通过generate-for循环来实现。

module top_module( 
    input [7:0] in,
    output [7:0] out
);
	generate
		genvar i;
		for (i=0; i<8; i = i+1) begin: my_block_name
			assign out[i] = in[8-i-1];
		end
	endgenerate

endmodule

2.2.8、Replication operator

知识点:复制运算符。特点,两个花括号,不同于拼接符的一个花括号。(初学的时候容易犯错)

{num{vector}}
{5{1'b1}}           // 等价于:5'b11111 
{2{a,b,c}}          // 等价于:{a,b,c,a,b,c}
{3'd5, {2{3'd6}}}   // 等价于:9'b101_110_110(这前面是d,代表10进制)
module top_module (
    input [7:0] in,
    output [31:0] out );//
    assign out = {{24{in[7]}},in};

    // assign out = { replicate-sign-bit , the-input };

endmodule

2.2.9、More replication

知识点补充:a~^b等价于~a^b

module top_module (
	input a, b, c, d, e,
	output [24:0] out
);

	wire [24:0] top, bottom;
	assign top    = { {5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}} };
	assign bottom = {5{a,b,c,d,e}};
	assign out = ~top ^ bottom;	// Bitwise XNOR

	// This could be done on one line:
	// assign out = ~{ {5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}} } ^ {5{a,b,c,d,e}};
	
endmodule

2.3、Modules:Hierarchy

2.3.1、Modules

知识点:模块的调用有两种方式:1、按位置连接。2、按名字连接。

这里介绍下按名字连接

example : mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );

mod_a:你要调用模块的名字

instance2:实例化的名字

out、in1、in2:mod_a定义时候的输入与输出

wc、wa、wb:当前模块的输入与输出

module top_module ( input a, input b, output out );
    mod_a instance1 ( 
        .in1(a), 
        .in2(b), 
        .out(out) );

endmodule

当前一个叫top_module 的模块要取调用之前定义好的模块mod_a ,调用的时候给它取了个别名instance1 ,将信号按照与原理图接入到实例化的instance1中去。其实这个形式很像c++中的struct

2.3.2、Connecting ports by position

知识点:按位置连接,实例化模块的输入与输出必须与原函数完全相同

优点:按名称将信号连接到模块的端口可以使电线保持正确连接,即使端口列表发生更改。

缺点:通用性和可读性都比较差。

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a example1(out1,out2,a,b,c,d);

endmodule

2.3.3、Connecting ports by name

知识点:按名字连接,已经在2.3.1进行了详细描述,这里不再过多叙述。

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a u0(
        .out1(out1),
        .out2(out2),
        .in1(a),
        .in2(b),
        .in3(c),
        .in4(d)
    );

endmodule

2.3.4、Three modules

module top_module ( input clk, input d, output q );
    wire w1, w2;
    my_dff u0(
        .clk(clk),
        .d(d),
        .q(w1));
    my_dff u1(
        .clk(clk),
        .d(w1),
        .q(w2));
    my_dff u2(
        .clk(clk),
        .d(w2),
        .q(q));
endmodule

2.3.5、Modules and vectors

module top_module ( 
    input clk, 
    input [7:0] d, 
    input [1:0] sel, 
    output [7:0] q 
);
    wire [7:0] w1,w2,w3;

    my_dff8 u0(clk,d,w1);
    my_dff8 u1(clk,w1,w2);
    my_dff8 u2(clk,w2,w3);
    
    always @(*) begin
        case(sel)            // if-else is ok.
            2'b00: q = d;
            2'b01: q = w1;
            2'b10: q = w2;
            2'b11: q = w3; 
        endcase
    end
endmodule

 2.3.6、Adder1

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);	
    wire [15:0] sum1, sum2;
    wire cout1,cout2;
    add16 u0(a[15:0],b[15:0], 0, sum1,cout1);
    add16 u1(a[31:16],b[31:16],cout1 ,sum2,cout2);
    assign sum = {sum2,sum1};
endmodule

2.3.7、Adder2

知识点:

两个n位的a与b相加,必须用n+1位的sum来保存他们相加的结果,因为你要考虑他们进位的情况。具体见下面add1 模块。

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);//
    wire [15:0] sum1, sum2;
    wire cout1,cout2;
    add16 u0(a[15:0],b[15:0], 0, sum1,cout1);
    add16 u1(a[31:16],b[31:16],cout1 ,sum2,cout2);
    assign sum = {sum2,sum1};
endmodule

module add1 ( input a, input b, input cin,   output sum, output cout );
    wire [1:0] w1;
    assign w1 = a + b + cin; 
    assign sum = w1[0];
    assign cout = w1[1];
endmodule

2.3.8、Carry-select adder

知识点:电路图的设计思路很值得借鉴,为了防止延迟直接把两种情况提前开始做。

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire [15:0] sum0,sum1,sum2,sum3;
    wire cout0,cout1,cout2;
    add16 u0(a[15:0],b[15:0],0,sum0,cout0);
    add16 u1(a[31:16],b[31:16],0,sum1,cout1);
    add16 u2(a[31:16],b[31:16],1,sum2,cout2);
    always @(*) begin
        case(cout0)
            1'b0:sum3 = sum1;
            1'b1:sum3 = sum2;
        endcase
    end
    assign sum = {sum3,sum0};
endmodule

2.3.9、Adder-subtractor

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire [31:0] w1;		//异或门的输出
    wire [15:0] sum1,sum2;	// 加法器的输出
    wire cout1,cout2;		// 进位标志
    assign w1 = b^{32{sub}};
    add16 u0(a[15:0],w1[15:0],sub,sum1,cout1);
    add16 u1(a[31:16],w1[31:16],cout1,sum2,cout2);
    assign sum = {sum2,sum1};
endmodule

2.4、Procedures

2.4.1、Alawys blocks(combinational)

知识点:always块

组合电路:always @(*),他类似于assign赋值,只是它的块内可以实现多个信号同时赋值。最重要的是,块内部的表达可以很丰富,比如包含if-else,case等。

注意:always内部赋值必须是reg型,如果是wire型会报错

    always @(*) begin                    assign out1 = in1;
        out1 = in1;            等价于    assign out2 = in2; 
        out2 = in2;                           ...
            ...
    end
(out1、out2是reg型)

时钟电路: always @(posedge clk)

(*):只要信号有变化就执行。

posedge:clk的上升沿

negedge:clk的下降沿

// synthesis verilog_input_version verilog_2001
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)

知识点:阻塞赋值与非阻塞赋值

  • assign使用阻塞赋值(=)
  • 在组合always块内使用阻塞赋值(=)
  • 在时序always块中使用非阻塞赋值(<=)
// synthesis verilog_input_version verilog_2001
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

知识点:if-else与三目运算符

// synthesis verilog_input_version verilog_2001
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 == 1)&&(sel_b2 == 1)) ? b : a;
    always @(*) begin
        if((sel_b1 == 1)&&(sel_b2 == 1))
            out_always = b;
        else
            out_always = a; 
    end   
endmodule

2.4.4、If statement latches

知识点:如何避免电路生成锁存器

解决办法:组合电路必须在所有条件下为所有输出赋值,即考虑所有情况。第二种方法见2.4.7,如果不考虑所有情况该怎么办。

// synthesis verilog_input_version verilog_2001
module top_module (
    input      cpu_overheated,
    output reg shut_off_computer,
    input      arrived,
    input      gas_tank_empty,
    output reg keep_driving  ); //

    always @(*) begin
        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,类似于c语言中的switch-case语句。

// synthesis verilog_input_version verilog_2001
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)
            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 = 4'b0000;
        endcase
    end
endmodule

2.4.5、Priority encoder

知识点:case、casez、casex

 法一:把每种情况考虑到,不想写,麻烦

法二:合理利用casex

// synthesis verilog_input_version verilog_2001
module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
    always @(*) begin
        casex(in)
            4'bxxx1 : pos = 2'b00;
            4'bxx10 : pos = 2'b01;
            4'bx100 : pos = 2'b10;
            4'b1xxx : pos = 2'b11;
            default : pos = 2'b00;
        endcase
    end
endmodule

2.4.6、Priority encoder with casez

知识点:case,casez,casex。

// synthesis verilog_input_version verilog_2001
module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
    always @(*) begin
        casez(in)
            8'bzzzzzzz1:pos = 4'b000;
            8'bzzzzzz10:pos = 4'b001;
            8'bzzzzz100:pos = 4'b010;
            8'bzzzz1000:pos = 4'b011;
            8'bzzz10000:pos = 4'b100;
            8'bzz100000:pos = 4'b101;
            8'bz1000000:pos = 4'b110;
            8'b10000000:pos = 4'b111;
            default:pos = 4'b000;
        endcase
    end
endmodule

2.4.7、Avoiding latches

知识点:如何避免锁存器的生成。

在进入always快的时候为所有输出赋值。

// synthesis verilog_input_version verilog_2001
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;
            16'he072:down=1;
            16'he074:right=1;
            16'he075:up=1;
        endcase      
    end

endmodule

2.5、More Verilog Features

2.5.1、Conditional ternary operator

知识点:三目运算符(和c语言中的规则一模一样)

condition ? if_true : if_false;

module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);//
    
    wire [7:0] w1 ,w2;
    assign w1 = a <= b ? a :b;
    assign w2 = c <= d ? c :d;
    assign min = w1 <= w2 ? w1 : w2;
    // assign intermediate_result1 = compare? true: false;

endmodule

2.5.2、Reduction operators

知识点:

1、2.1.3已经介绍了位运算作用于两个对象。现在介绍它的第二种用法,对一个对象中的每个位进行位运算——缩减运算符。

example:

& a[3:0]     // 等价于:a[3]&a[2]&a[1]&a[0]. 
| b[3:0]     // 等级于:  b[3]|b[2]|b[1]|b[0]. 
^ c[2:0]     // 等价于: c[2]^c[1]^c[0]

2、信号的奇偶校验可以运用位运算符 ^ 。

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 = &in;
    assign out_or = |in;
    assign out_xor = ^in;

endmodule

2.5.4、Combinational for-loop:Vector reversal 2

知识点:$bits(out)能输出out这个vector的大小。——类似c++中,vector.size()。可以在2.5.5中应用一下。

module top_module( 
    input [99:0] in,
    output [99:0] out
);
    always@(*) begin
        for(integer i = 0;i<100;i = i + 1)
            out[i] = in[99 - i];
    end
endmodule

2.5.5、Combinational for-loop:255-bit population count

易错点:你要对一个对象进行算数运算的时候必须要给他赋初值。比如下面你如果丢掉(out = 0;)就会出错。

module top_module( 
    input [254:0] in,
    output [7:0] out );
    always @(*) begin
        out = 0;
        for(int i = 0;i<$bits(in);i = i + 1)
                out = out + in[i];
    end
endmodule

2.5.6、Generate for-loop:100-bit binary adder 2 ⭐

知识点:

1、全加器的实现

法一:

s = a1^a2^cin
cout = a1&a2 | a1&cin | a2&cin

 法二:

module top_module( 
    input a, b, cin,
    output cout, sum );
    wire [1:0] w1;
    assign w1 = a + b + cin;
    assign sum = w1[0];
    assign cout = w1[1];
    
endmodule

法一优于法二,法一就不用单独设置一个wire类型的数据来保存相加结果。

2、生成块(generate-endgenerate)——摘自《数字系统设计教程(第3版)》,夏宇闻

a、应用场景:

  • 对矢量(vector)中的多个位进行重复操作
  • 进行多个模块的实例引用的重复操作
  • 根据参数的定义来确定程序中是否应该包括某段Verilog代码的时候

b、生成实例的内容可以是以下的一个或多个类型:

  • 模块
  • 用户定义原语
  • 门级原语
  • 连续赋值语句
  • initial和always块

c、3种创建生成语句的方法

  • 循环生成
  • 条件生成
  • case生成

题解:

法一:always块

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    //---------------initial----------------
    assign sum[0] = a[0]^b[0]^cin;
    assign cout[0] = a[0]&b[0] | a[0]&cin | b[0]&cin;
    //---------------for loop---------------
    always @(*)begin
        for(integer i = 1;i<100;i++)begin
            sum[i] = a[i]^b[i]^cout[i-1];
            cout[i] = a[i]&b[i] | a[i]&cout[i-1] | b[i]&cout[i-1];
        end
    end
endmodule

法二:运用生成语句——没写出来QAQ

不知道错在哪里

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    
    assign cout[0] = cin;
    genvar i;
    generate for( i = 1 ; i < 100 ; i = i + 1) begin : r_loop
        always @(*) sum[i-1] = a[i-1]^b[i-1]^cout[i-1];
        always @(*) cout[i] = a[i-1]&b[i-1] | a[i-1]&cout[i-1] | b[i-1]&cout[i-1];
    end
    endgenerate
endmodule

2.5.7、Generate for-loop:100-digit BCD adder ⭐

知识点:生成块(generate-endgenerate),详情见题2.5.6

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    
    reg [100:0] cin_mid;
    assign cin_mid[0] = cin;
    genvar i;
    generate for(i = 1 ; i <= 100  ; i++) begin : r_loop
        bcd_fadd tt(
            a[4 * i  -1 : 4 * (i - 1)],
            b[4 * i  -1 : 4 * (i - 1)],
            cin_mid[i - 1],
            cin_mid[i],
            sum[4 * i  -1 : 4 * (i - 1)]
        );
    end 
    endgenerate
    assign cout = cin_mid[100];
endmodule

三、Circuits

3.1、Combinational Logic

3.1.1 Basic Gates

1、Wire

module top_module (
    input in,
    output out);
    assign out = in;

endmodule

2、GND

module top_module (
    output out);
	assign out = 1'b0;
endmodule

3、NOR        

知识点:知道关键字(nor)的使用

法一:使用关键词nor

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

endmodule

法二:使用位运算符

module top_module (
    input in1,
    input in2,
    output out);
    assign out = ~(in1|in2);
endmodule

 4、Another 

module top_module (
    input in1,
    input in2,
    output out);
    assign out = in1&~in2;
endmodule

5、Two gates

知识点:

关键字:xnor与关键字xor

 法一:用关键字

module top_module (
    input in1,
    input in2,
    input in3,
    output out);
    wire w1;
    xnor(w1 , in1, in2);
    xor(out ,w1,in3);

endmodule

法二:位运算 

module top_module (
    input in1,
    input in2,
    input in3,
    output out);
    wire w1;
	assign w1 = ~in1^in2;
    assign out = w1^in3;

endmodule

5、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
);
    and(out_and , a, b);
    or(out_or, a, b);
    xor(out_xor ,a ,b);
    nand(out_nand,a,b);
    nor(out_nor,a,b);
    xnor(out_xnor,a,b);
    assign out_anotb = a&~b;
endmodule

 6、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

7、Truth tables

知识点:真值表

module top_module( 
    input x3,
    input x2,
    input x1,  // three inputs
    output f   // one output
);
    assign f = ~x3&x2|x1&x2|x3&x1;
endmodule

8、Two-bit equality

法一:

module top_module ( input [1:0] A, input [1:0] B, output z ); 
    always @(*) begin 
        if(A == B) z = 1;
        else z = 0;
    end
endmodule

法二:

module top_module(
	input [1:0] A,
	input [1:0] B,
	output z);

	assign z = (A[1:0]==B[1:0]);	

endmodule

9、Simple circuit A

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

10、Simple circuit B

module top_module ( input x, input y, output z );
    assign z = ~x^y;

endmodule

11、Combine circuits A and B 

知识点:模块的调用

module top_module (input x, input y, output z);
    wire w1,w2,w3,w4;
    A_block u0(x,y,w1);
    B_block u1(x,y,w2);
    assign w3 = w1 | w2;
    assign w4 = w1 & w2;
    assign z = w3^w4; 
endmodule

module A_block (input x, input y, output z);
	assign z = x^y&x;
endmodule

module B_block ( input x, input y, output z );
    assign z = ~x^y;

endmodule

12、Ring or bibrate

知识点:画卡诺图,然后用verilog将其实现

ring
vibrate_mode
vibrate_mode
vibrate_mode
0000
0100
1101
1010
module top_module (
    input ring,
    input vibrate_mode,
    output ringer,       // Make sound
    output motor         // Vibrate
);
    assign ringer = ring&~vibrate_mode;
    assign motor = ring&vibrate_mode;

endmodule

13、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 = heater|aircon|fan_on;
    

endmodule

14、3-bit population count

法一:从卡诺图出发来写

module top_module( 
    input [2:0] in,
    output [1:0] out );
    assign out[1] = in[2]&in[1]|in[1]&in[0]|in[2]&in[0];
    assign out[0] = ~in[2]&~in[1]&in[0]|~in[2]&in[1]&~in[0]|in[2]&in[1]&in[0]|in[2]&~in[1]&~in[0];
endmodule

法二:用case把每种情况都考虑到

注意:做比较运算时候,verilog会将不同进制转换到同一进制下进行比较。

module top_module (
	input [2:0] in,
	output [1:0] out
);	
always @(*) begin
		case (in)
			3'd0: out = 2'd0;
			3'd1: out = 2'd1;
			3'd2: out = 2'd1;
			3'd3: out = 2'd2;
			3'd4: out = 2'd1;
			3'd5: out = 2'd2;
			3'd6: out = 2'd2;
			3'd7: out = 2'd3;
		endcase
	end
endmodule

15、Gates and vectors

知识点:错位比较

module top_module( 
    input [3:0] in,
    output [2:0] out_both,
    output [3:1] out_any,
    output [3:0] out_different );

    
    assign out_both = in[2:0]&in[3:1];
    assign out_any = in[2:0]|in[3:1];
    assign out_different = in^{in[0],in[3:1]};
    

endmodule

16、Even longer vectors

module top_module( 
    input [99:0] in,
    output [98:0] out_both,
    output [99:1] out_any,
    output [99:0] out_different );
    
    assign out_both = in[98:0]&in[99:1];
    assign out_any = in[98:0]|in[99:1];
    assign out_different = in^{in[0],in[99:1]};
    

endmodule

3.1.2、Multiplexers

1、2-to-1 multiplexers

module top_module( 
    input a, b, sel,
    output out ); 
    assign out = sel? a : b;
endmodule

2、2-to-1 bus multiplexers

module top_module( 
    input [99:0] a, b,
    input sel,
    output [99:0] out );
	assign out = sel? a : b;
endmodule

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'd0:out = a;
            4'd1:out = b;
            4'd2:out = c;
            4'd3:out = d;
            4'd4:out = e;
            4'd5:out = f;
            4'd6:out = g;
            4'd7:out = h;
            4'd8:out = i;
            default:out = {16{1'b1}};
        endcase
    end
endmodule

标准答案:

知识点:

'1是一种特殊的语法,他能将vector所有的位设为1的数字,[n:0]a = 'b。'0, 'x, 和'z 也是一样的

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
		out = '1;		
		case (sel)
			4'h0: out = a;
			4'h1: out = b;
			4'h2: out = c;
			4'h3: out = d;
			4'h4: out = e;
			4'h5: out = f;
			4'h6: out = g;
			4'h7: out = h;
			4'h8: out = i;
		endcase
	end
endmodule

4、256-to-1 multiplexer

module top_module( 
    input [255:0] in,
    input [7:0] sel,
    output out );
    assign out = in[sel];

endmodule

5、256-to-1 4 bit multiplexer⭐

知识点:

假设有一个向量A与向量a,与常量n与m:

A[a]是合法表达,此时允许a是一个变动的向量。

A[n:m]是合法表达的,此时n与m是不能为向量的,只能为常量,是一个确定的值,否则会报错。

A[4*(a+1):4*a]是非法表达,因为冒号:两边必须是常量

法一:

module top_module (
	input [1023:0] in,
	input [7:0] sel,
	output [3:0] out
);
assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};
endmodule

法二:

知识点:

assign out = in[sel*4 +: 4];

含义,选择从索引“sel*4”开始,然后选择总宽度为4位的索引号递增(+:)。

assign out = in[sel*4+3 -: 4];

含义,选择从索引“sel*4+3”开始,然后选择总宽度为4位的索引号递减(-:)。

注意:注意:宽度(本例中为4)必须是常量。

module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );
    assign out = in[sel*4+:4];
endmodule

3.1.3、Arithmetic Circuits

1、Half adder

abcoutsum
0000
0101
1001
1110
module top_module( 
    input a, b,
    output cout, sum );
    assign cout = a & b;
    assign sum = a&~b|~a&b;
endmodule

2、Full adder

法一:

module top_module( 
    input a, b, cin,
    output cout, sum );
    assign cout = a&b|a&cin|b&cin;
    assign sum = a^b^cin;
endmodule

法二:

module top_module( 
    input a, b, cin,
    output cout, sum );
    wire [1:0] w1;
    assign w1 = a + b + cin; 
    assign sum = w1[0];
    assign cout = w1[1];  
endmodule


//也可以这样
module top_module( 
    input a, b, cin,
    output cout, sum );
    wire [1:0] w1;
    assign {cout , sum} = a  + b + cin;
endmodule

3、3-bit binary adder⭐

法一:生成循环块(generate -endgenerate )

知识点:后面cout将不会在给出,如(4-digital BCD adder这个题目)。你要自己创建一个容器来保存进位。

module top_module( 
    input [2:0] a, b,
    input cin,
    output [2:0] cout,
    output [2:0] sum );
    
    full_adder u0(a[0],b[0],cin,cout[0],sum[0]);
    genvar i;
    generate for(i = 1 ; i < $bits(sum) ; i++) begin:r_loop
        full_adder u1(a[i],b[i],cout[i-1] ,cout[i] ,sum[i]);
    end
    endgenerate
endmodule

module full_adder( 
    input a, b, cin,
    output cout, sum );
    assign cout = a&b|a&cin|b&cin;
    assign sum = a^b^cin;
endmodule

4、Adder

知识点:两个n位的无符号数相加必须用n+1的容器来存储他们的相加结果。

module top_module (
    input [3:0] x,
    input [3:0] y, 
    output [4:0] sum);
	assign sum = x + y;    
endmodule

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

6、100-bit binary adder

module top_module( 
    input [99:0] a, b,
    input cin,
    output cout,
    output [99:0] sum );
    assign  {cout, sum} = a + b + cin;
endmodule

7、4-digital BCD adder⭐

module top_module( 
    input [15:0] a, b,
    input cin,
    output cout,
    output [15:0] sum );
    wire [3:0] temp_cout;
    bcd_fadd u0(a[3:0] , b[3:0] , cin, temp_cout[0], sum[3:0]);
    genvar i;
    generate for( i = 1 ; i < 4 ; i++) begin:r_loop
        bcd_fadd u1(a[i*4+:4],b[i*4+:4],temp_cout[i-1],temp_cout[i],sum[i*4+:4]);
    end
    endgenerate
    assign cout = temp_cout[3];
endmodule

3.1.4、Karnaugh Map to Circuit

知识点:

  • 由卡诺图写出逻辑表达式
  • 逻辑表达式的化简

1、3-variable

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

2、4-variable

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out  ); 
    assign out = ~c&~b|~d&~a|c&d&a|c&d&b;
endmodule

3、4-variable

知识点:m代表1,d代表无关项x

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out  ); 
    assign out = a|c&~b;
endmodule

4、4-variable 

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out  ); 
    assign out = a^b^c^d;
endmodule

 5、Minimum SOP and POS

sop:sum of product 积之和 即化成最小项的形式,对应于卡诺图就是圈1即可
pos:product of sum 和之积 即化成最大项的形式,对应于卡诺图就是圈0后,整体取反

6、Karnuagh map

module top_module (
    input [4:1] x, 
    output f );
    assign f = x[3]&~x[1]|x[4]&x[2];      
endmodule

7、Karnuagh map

module top_module (
    input [4:1] x,
    output f
); 
    assign f = x[3]&~x[1]|x[3]&x[4]&x[2]|~x[4]&x[1]&~x[2]|~x[3]&~x[4]&~x[2];
endmodule

8、K-MAP implemented witj a multiplexer ⭐、

没看懂什么意思...

module top_module (
	input c,
	input d,
	output [3:0] mux_in
);
	// After knowing how to split the truth table into four columns,
	// the rest of this question involves implementing logic functions
	// using only multiplexers (no other gates).
	// I will use the conditional operator for each 2-to-1 mux: (s ? a : b)
	assign mux_in[0] = (c ? 1 : (d ? 1 : 0));	// 2 muxes: c|d
	assign mux_in[1] = 0;						// No muxes:  0
	assign mux_in[2] = d ? 0 : 1;				// 1 mux:    ~d
	assign mux_in[3] = c ? (d ? 1 : 0) : 0;		// 2 muxes: c&d
endmodule

 3.2、Sequential Logic

3.2.1、Latches and Flip-Flops

1、D flip-flop

知识点:D触发器(上升沿)

module top_module (
    input clk,    // Clocks are used in sequential circuits
    input d,
    output reg q );//
    always @(posedge clk) begin
        q <= d;
    end
    // Use a clocked always block
    //   copy d to q at every positive edge of clk
    //   Clocked always blocks should use non-blocking assignments

endmodule

2、D flip-flops

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 <= '0;
        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 , posedge areset) begin
        if(areset)
            q <= '0;
        else 
            q <= 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) begin
        if(~resetn)
            q = '0;
        else if(byteena == 2'b01) 
            q[7:0] <= d[7:0];
        else if(byteena == 2'b10) 
            q[15:8] <= d[15:8];
        else if(byteena == 2'b11) 
            q <= d;     
    end
endmodule

7、D latch

知识点:锁存器的实现(要点:考虑问题不周全就会出现锁存器,如if 没有else case没有default)

module top_module (
    input d, 
    input ena,
    output q);
    always @(ena) begin
        if(ena) q <= d;
    end
endmodule

8、DFF

 知识点:三角型代表上升沿

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

9、DFF

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

10、DFF+gate

module top_module (
    input clk,
    input in, 
    output out);
    always @(posedge clk) begin 
        out <= 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) begin
        Q <= r_in&L|q_in&~L;
    end
endmodule

12、Mux and DFF

module top_module (
    input clk,
    input w, R, E, L,
    output Q
);
    always @(posedge clk) begin
        Q <= (w&E|Q&~E)&~L|R&L;
    end
endmodule

13、DFFs and gates⭐

错误解答:z是组合逻辑,而不是时序逻辑。所以他不能放在always语句中

module top_module (
    input clk,
    input x,
    output z
); 
    reg q1,q2,q3;
    always @(posedge clk) begin
        q1 <= x^q1;
        q2 <= x&~q2;
        q3 <= x|~q3;
        z = ~(q1|q2|q3);
    end
endmodule

正确解答

法一:

module top_module (
    input clk,
    input x,
    output z
); 
    reg q1,q2,q3;
    always @(posedge clk) begin
        q1 <= x^q1;
        q2 <= x&~q2;
        q3 <= x|~q3;
    end
    assign z = ~(q1|q2|q3);
endmodule

 法二:

module top_module (
    input clk,
    input x,
    output z
); 
    reg q1,q2,q3;
    D_flip_flops u0(clk,x^q1,q1);
    D_flip_flops u1(clk,x&~q2,q2);
    D_flip_flops u2(clk,x|~q3,q3);
    assign z = ~(q1|q2|q3);
endmodule

module D_flip_flops (     
    input clk,
    input d,
    output q 
);
    always @(posedge clk) begin
        q <= d;
    end
endmodule

14、Create circuit from truth table

知识点:JK触发器

法一:利用if -else来做

module top_module (
    input clk,
    input j,
    input k,
    output Q); 
    always @(posedge clk) begin
        if(j == 0 && k==1)
            Q <= 0;
        else if (j == 1 && k==0)
            Q <= 1;
        else if (j == 1 && k==1)
            Q <= ~Q;
    end
endmodule

法二:利用case-endcase

module top_module (
    input clk,
    input j,
    input k,
    output Q); 
    always @(posedge clk) begin
        case({j,k})
            2'b01:Q <= 0;
            2'b10:Q <= 1;
            2'b11:Q <= ~Q;
        endcase
    end
endmodule

15、Detect an edge⭐

知识点:边沿检测器

in = 0in = 1
reg_in = 001
reg_in = 100

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] pedge
);
    reg [7:0] reg_in;
    always @(posedge clk) begin 
        reg_in <= in;            // Remember the state of the previous cycle
        pedge <= ~reg_in&in;    // A positive edge occurred if input was 0 and is now 1.
    end
endmodule

16、Detecg botj edges⭐

in = 0in = 1
reg_in = 001
reg_in = 110
module top_module (
    input clk,
    input [7:0] in,
    output [7:0] anyedge
);
    reg [7:0] reg_in;
    always @(posedge clk) begin 
        reg_in <= in;            
        anyedge <= ~reg_in&in|reg_in&~in;    
    end
endmodule

17、Edge capture register

in=0in=1
out'=0 reg=000
out'=0 reg=110
out'=1 reg=111
out'=1 reg=011

module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);
    reg [31:0] reg_in;
    always @(posedge clk) begin 
        reg_in <= in;
        if(reset) out <= '0;
        else out <= out|reg_in&~in;
    end
endmodule

18、Dual-edge triggered flip-flop ⭐

知识点:双边触发器

非法表达一:

always @(posedge clk,negedge clk)是一种非法的表达

非法表达二:

    always @(posedge clk) begin
        q <= d;
    end
    always @(negedge clk) begin
        q <= d;
    end

报错:

 解答:

module top_module (
    input clk,
    input d,
    output q
);
    reg q1,q2;
    always  @(posedge clk) begin
		q1 <= d^q2;
    end
    always  @(negedge clk) begin
		q2 <= d^q1;
    end
    assign q = q1^q2;
endmodule

    // After posedge clk, p changes to d^n. Thus q = (p^n) = (d^n^n) = d.
    // After negedge clk, n changes to p^n. Thus q = (p^n) = (p^p^n) = d.

3.2.2、Counter

1、Four-bit binary counter⭐

知识点:verilog中的加法,4'b1111 + 1 = 4'b0000

我:

module top_module (
    input clk,
    input reset,      // Synchronous active-high reset
    output [3:0] q);
    always @(posedge clk) begin
        if(reset) q <= '0;
        else begin
            if(q == 4'b1111) q <= 4'b0000;
            else q <= q + 1'b1;
        end
    end
endmodule

参考答案:

module top_module(
	input clk,
	input reset,
	output reg [3:0] q);
	
	always @(posedge clk)
		if (reset)
			q <= 0;
		else
			q <= q+1;		// Because q is 4 bits, it rolls over from 15 -> 0.
		// If you want a counter that counts a range different from 0 to (2^n)-1, 
		// then you need to add another rule to reset q to 0 when roll-over should occur.
	
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 <= '0;
        else begin
            if(q == 4'b1001) q <= 4'b0000;
            else q <= q + 1'b1;
        end
    end
endmodule

参考答案:

module top_module(
	input clk,
	input reset,
	output reg [3:0] q);
	
	always @(posedge clk)
		if (reset || q == 9)	// Count to 10 requires rolling over 9->0 instead of the more natural 15->0
			q <= 0;
		else
			q <= q+1;
	
endmodule

3、Decade counter again

module top_module (
    input clk,
    input reset,
    output [3:0] q);
    always @(posedge clk) begin 
        if(reset || q == 4'b1010)
            q<=4'b0001;
        else 
            q<=q+1;      
    end
endmodule

4、Slow decade counter⭐

module top_module (
    input clk,
    input slowena,
    input reset,
    output [3:0] q);
    always @(posedge clk)begin
        if(reset == 1)
        	q <= 0; 
        else if(slowena == 1)begin
            if(q==9) q <= 0; 
            else q <= q + 1; 
        end
    end
endmodule

5、Counter 1-12⭐

知识点:

  • load端---有此使能端说明此计数器有预置输入端,可预置输入计数起始值,即计数器可以不从0开始计数,load端使能就是要加载预置输入值;
  • 大功能器件如何阉割成小功能器件
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;
    assign c_load = reset| ((Q == 4'd12) && enable == 1'b1);
    assign c_d = c_load ? 4'd1 : 4'd0;
    count4 the_counter (clk, c_enable, c_load, c_d,Q/*, ... */ );
endmodule

6、Counter 1000⭐

知识点:q0 == 4'd9 在比较的时候会将4'd9转换为一个四位的二进制数。

module top_module (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
); //
    reg [3:0] q0,q1,q2;
    assign c_enable = {q0 == 4'd9 && q1 == 4'd9,q0 == 4'd9,1'b1};
    assign OneHertz = (q0 == 4'd9 && q1 == 4'd9 && q2 == 4'd9);
    bcdcount counter0 (clk, reset, c_enable[0],q0/*, ... */);
    bcdcount counter1 (clk, reset, c_enable[1],q1/*, ... */);
    bcdcount counter3 (clk, reset, c_enable[2],q2/*, ... */);
endmodule

7、4-digit decimal counter⭐

知识点:由单个bcd计数器构成更大的(1000)计数器

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);
    
    assign ena = {q[11:8]==4'd9&&q[7:4]==4'd9&&q[3:0]==4'd9,q[7:4]==4'd9&&q[3:0]==4'd9,q[3:0]==4'd9};
    
    bcd u0(clk,reset,1'b1,q[3:0]);
    bcd u1(clk,reset,ena[1],q[7:4]);
    bcd u2(clk,reset,ena[2],q[11:8]);   
    bcd u3(clk,reset,ena[3],q[15:12]);
endmodule

module bcd(
    input clk,
    input reset,
    input enable,
    output reg [3:0] q    
);
    always @(posedge clk) begin
        if(reset) q<='0;
        else if(enable) begin 
            if(q == 4'd9) q<='0;
            else q <= q+1;
        end
    end
endmodule
    

8、12-hour clock

(不会写)

3.2.3、Shift Registers

1、4-bit shift register

知识点:

  • 右移寄存器的实现
  • 移位运算符:a>>n或a<<n,a代表要进行移位的操作数,n代表要移动几位。这两种移动运算符都用0来填补移出的空位
  • 涉及到优先级问题的时候可以用if-else if 按照优先级对其进行排列。——很有用的技巧 
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
        if(areset) q <= '0;
        else 
            begin 
                if(load)
                    q<=data;
                else
                    begin
                        if(ena) q <= (q>>1);
                        else q<=q;
                    end
            end
    end
endmodule

参考答案:

module top_module(
	input clk,
	input areset,
	input load,
	input ena,
	input [3:0] data,
	output reg [3:0] q);
	
	// Asynchronous reset: Notice the sensitivity list.
	// The shift register has four modes:
	//   reset
	//   load
	//   enable shift
	//   idle -- preserve q (i.e., DFFs)
	always @(posedge clk, posedge areset) begin
		if (areset)		// reset
			q <= 0;
		else if (load)	// load
			q <= data;
		else if (ena)	// shift is enabled
			q <= q[3:1];	// Use vector part select to express a shift.
	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); 
    always @(posedge clk) begin 
        if(load) q<=data;
        else
            begin
                case(ena)
                    2'b01:q = {q[0],q[99:1]};
                    2'b10:q = {q[98:0],q[99]};
                endcase
            end
    end
endmodule

参考答案:

module top_module(
	input clk,
	input load,
	input [1:0] ena,
	input [99:0] data,
	output reg [99:0] q);
	
	// This rotator has 4 modes:
	//   load
	//   rotate left
	//   rotate right
	//   do nothing
	// I used vector part-select and concatenation to express a rotation.
	// Edge-sensitive always block: Use non-blocking assignments.
	always @(posedge clk) begin
		if (load)		// Load
			q <= data;
		else if (ena == 2'h1)	// Rotate right
			q <= {q[0], q[99:1]};
		else if (ena == 2'h2)	// Rotate left
			q <= {q[98:0], q[99]};
	end
endmodule

3、Left/right arithmetic shift by 1 or 8

知识点:算数左移动与算数右移

  • 算术右移(ASR)是将各位依次右移指定位数,然后在左侧用原符号位补齐
  • 逻辑右移(LSR)是将各位依次右移指定位数,然后补0
  • 算数左移等同于逻辑左移,都是补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) q<=data;
        else begin
            if(ena) begin
            	case(amount)
                	2'b00:q<={q[62:0],1'd0};
                	2'b01:q<={q[55:0],8'd0};
                    2'b10:q<={q[63],q[63:1]};
                    2'b11:q<={{8{q[63]}},q[63:8]};           
            	endcase
            end
        end                       
    end
endmodule

4、5-bits LFSR

法一:

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 5'h1
    output [4:0] q
); 
    always @(posedge clk) begin
        if(reset) q<=5'h1;
        else begin
            q[4] <= q[0]^0;
            q[3] <= q[4];
            q[2] <= q[3]^q[0];
            q[1] <= q[2];
            q[0] <= q[1];
        end
    end
endmodule

法二:

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 5'h1
    output [4:0] q
); 

    wire w1,w2,w3,w4,w5;
    always @(posedge clk)
        begin
            if (reset)
                q[0] = 1'b1;
            else
                q[0] = q[1];
        end

    D_flip ins2(q[2], q[1], clk, reset);
    D_flip ins3(q[0]^q[3], q[2], clk,reset);
    D_flip ins4(q[4], q[3], clk, reset);
    D_flip ins5(0^q[0], q[4], clk, reset);
    
endmodule


module D_flip(input D, output Q, input clk, input reset);
    always @(posedge clk)
        begin
            if(reset)
                Q <= 1'b0;
            else
            	Q <= D;
        end
endmodule

5、3-bit LFSR⭐

在这里犯了错误,位运算符也是有优先级的。

解答:

module top_module (
	input [2:0] SW,      // R
	input [1:0] KEY,     // L and clk
	output [2:0] LEDR);  // Q
    always @(posedge KEY[0]) begin
        LEDR[0] <= KEY[1]&SW[0]|~KEY[1]&LEDR[2];
        LEDR[1] <= KEY[1]&SW[1]|~KEY[1]&LEDR[0];
        LEDR[2] <= KEY[1]&SW[2]|~KEY[1]&(LEDR[1]^LEDR[2]); //如果把这个括号去掉则会报错,大家可以试一试
    end
endmodule

6、32-bit LFSR

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 begin
            q[31]<=q[0];
            q[30:22] <= q[31:23];
            q[21]<=q[0]^q[22];
            q[20:2]<=q[21:3];
            q[1]<=q[0]^q[2];
            q[0]<=q[0]^q[1];             
        end      
    end
endmodule

7、Shift register

法一:

知识点:自定义的模块名字不要与quartus ii自定义的元件名冲突,比如,你将下面代码中的d_f_f改成dff就会报错,我在这里卡了好久。。。

module top_module (
    input clk,
    input resetn,   // synchronous reset
    input in,
    output out);
    reg [3:1] q;
    d_f_f u3(.clk(clk),.resetn(resetn),.d(in),.q(q[3]));
    d_f_f u2(.clk(clk),.resetn(resetn),.d(q[3]),.q(q[2]));
    d_f_f u1(.clk(clk),.resetn(resetn),.d(q[2]),.q(q[1]));
    d_f_f u0(.clk(clk),.resetn(resetn),.d(q[1]),.q(out));
endmodule

module d_f_f(
    input clk,
	input resetn,
    input d,
    output q 
);
    always @(posedge clk) begin
        if(~resetn) q <= 1'b0;
        else q <= d;
    end
endmodule

法二:

module top_module (
    input clk,
    input resetn,   // synchronous reset
    input in,
    output reg out);
    reg [2:0] Q;
    always @(posedge clk)begin
        if(~resetn)begin
            {Q,out} <= 4'b0;
        end
        else begin
            Q[2] <= in;
            Q[1] <= Q[2];
            Q[0] <= Q[1];
            out <= Q[0];
        end
    end

endmodule

8、Shift register

知识点:如果输入和输出是一样的就没必要在定义一个另外的输入了,比如,module MUXDFF 中Q既是输入也是输出。

module top_module (
    input [3:0] SW,
    input [3:0] KEY,
    output [3:0] LEDR
); //

    MUXDFF u3(
        .clk(KEY[0]),
        .w(KEY[3]),
        .R(SW[3]),
        .E(KEY[1]),
        .L(KEY[2]),
        .Q(LEDR[3])
    );
    MUXDFF u2(
        .clk(KEY[0]),
        .w(LEDR[3]),
        .R(SW[2]),
        .E(KEY[1]),
        .L(KEY[2]),
        .Q(LEDR[2])
    );
    MUXDFF u1(
        .clk(KEY[0]),
        .w(LEDR[2]),
        .R(SW[1]),
        .E(KEY[1]),
        .L(KEY[2]),
        .Q(LEDR[1])
    );
     MUXDFF u0(
        .clk(KEY[0]),
        .w(LEDR[1]),
        .R(SW[0]),
        .E(KEY[1]),
        .L(KEY[2]),
         .Q(LEDR[0])
    );
endmodule

module MUXDFF (
    input clk,
    input w, R, E, L,
    output Q
);
    always @(posedge clk) begin
        Q <= (w&E|Q&~E)&~L|R&L;
    end
endmodule

9、3-input LUT

module top_module (
    input clk,
    input enable,
    input S,
    input A, B, C,
    output Z ); 
    
    reg[7:0] Q;
    
    always@(posedge clk) begin
        if(enable) 
            Q <= {Q[6:0],S};
        else
            Q<=Q;
    end
    
    assign Z = Q[{A,B,C}];
 
endmodule

3.2.4、More Circuits

1、Rule 90

核心:邻居之间异或

module top_module(
    input clk,
    input load,
    input [511:0] data,
    output [511:0] q ); 

    
    always @ (posedge clk)
        begin
            if (load)
                q <= data;
            else
                begin
                    q <= q[511:1] ^ {q[510:0], 1'b0} ;
                end
        end
endmodule

2、Rule 110

module top_module(
    input clk,
    input load,
    input [511:0] data,
    output [511:0] q
); 
    always @(posedge clk) begin
        if(load) q<=data;
        else q <= (q[511:0]^{q[510:0],1'b0})|{~q[511:1] &{q[510:0],1'b0}};  
    end
endmodule

3、Conway's Game of Life 16×16

3.2.5、Finite State Machines

四部曲:

  • 确定有几种状态状态
  • 状态转换逻辑(next_state更新)
  • state更新
  • 输出逻辑

1、Simple FSM 1(asynchronous reset)

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)
            A: next_state = in? A:B;
            B: next_state = in? B:A;
        endcase
    end

    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 == ...);
    assign out = (state == B);

endmodule

2、Simple FSM 1(synchronous reset)

// 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;
    //present_state跟新
    always @(posedge clk) begin
        if(reset)
            present_state <= B;
        else
            present_state <= next_state;        
    end
    //next_state跟新
    always @(*) begin
        case(present_state)
            A:next_state = (in ? A : B);
            B:next_state = (in ? B : A);  
        endcase 
    end
    // out跟新
    assign out = (present_state == B);
endmodule

3、Simple FSM 2(asynchronous reset)

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;

    //next_state跟新(与激励有关)
    always @(*) begin
        case(state)
            OFF:next_state = (j?ON:OFF);
            ON:next_state = (k?OFF:ON);
        endcase
    end   
	//state跟新
    always @(posedge clk, posedge areset) begin
        if(areset) state<=OFF;
		else state <= next_state;
    end
    //out跟新
    assign out = (state == ON);
endmodule

4、Simple FSM 2(synchronous reset)

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
        case(state)
            OFF:next_state <= (j?ON:OFF);
            ON:next_state <= (k?OFF:ON);
        endcase  
    end
    always @(posedge clk) begin
        if(reset) state <= OFF;
        else state <= next_state;
    end
    assign out = (state == ON);
endmodule

5、Simple state transition 3

module top_module(
    input in,
    input [1:0] state,
    output [1:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    always @(*) begin 
        case(state) 
            A:next_state <= (in?B:A);
            B:next_state <= (in?B:C);
            C:next_state <= (in?D:A);
            D:next_state <= (in?B:C);
        endcase
    end
    assign out = (state==D);
endmodule

6、Simple one-hot state transitions 3⭐

知识点:观察规律很重要

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] == 1);

endmodule

7、Simple FSM 3(asynchronous reset)

module top_module(
    input clk,
    input in,
    input areset,
    output out); //
    
    parameter A=0, B=1, C=2, D=3;
    reg [1:0] state , next_state;//只有四种状态2^2=4
    // State transition logic
    always @(*) begin 
        case(state) 
            A:next_state <= (in?B:A);
            B:next_state <= (in?B:C);
            C:next_state <= (in?D:A);
            D:next_state <= (in?B:C);
        endcase 
    end

    // State flip-flops with asynchronous reset
    always @(posedge clk,posedge areset) begin
        if(areset) state <= A;
        else state <= next_state;
    end
   
    // Output logic
    assign out = (state == D);

endmodule

8、Simple FSM 3(synchronous reset)

module top_module(
    input clk,
    input in,
    input reset,
    output out); //
    
    parameter A=0, B=1, C=2, D=3;
    reg [1:0] state , next_state;
    always @(*) begin 
        case(state) 
            A:next_state <= (in?B:A);
            B:next_state <= (in?B:C);
            C:next_state <= (in?D:A);
            D:next_state <= (in?B:C);
        endcase 
    end
    always @(posedge clk) begin
        if(reset) state <= A;
        else state <= next_state;
    end
    assign out = (state == D);

endmodule

9、Design a Moore FSM

module top_module (
    input clk,
    input reset,
    input [3:1] s,
    output fr3,
    output fr2,
    output fr1,
    output dfr
); 
    parameter A = 0,B1= 1, B2= 2 ,C1 = 3,C2 =4 ,D = 5;
    reg [2:0] state , nstate;
    
    always @(*) begin
        case(state)
            A:begin
                case(s)
                    3'b111:nstate=A;
                    3'b011:nstate=B1;
                    3'b001:nstate=C1;
                    3'b000:nstate=D; 
                endcase
            end
            B1:begin
                case(s)
                    3'b111:nstate=A;
                    3'b011:nstate=B1;
                    3'b001:nstate=C1;
                    3'b000:nstate=D;
                endcase
            end
            B2:begin
                case(s)
                    3'b111:nstate=A;
                    3'b011:nstate=B2;
                    3'b001:nstate=C1;
                    3'b000:nstate=D;
                endcase
            end
            C1:begin
                case(s)
                    3'b111:nstate=A;
                    3'b011:nstate=B2;
                    3'b001:nstate=C1;
                    3'b000:nstate=D;
                endcase
            end
            C2:begin
                case(s)
                    3'b111:nstate=A;
                    3'b011:nstate=B2;
                    3'b001:nstate=C2;
                    3'b000:nstate=D;
                endcase
            end
            D:begin
                case(s)
                    3'b111:nstate=A;
                    3'b011:nstate=B2;
                    3'b001:nstate=C2;
                    3'b000:nstate=D;
                endcase
            end    
        endcase
    end
    
    always @(posedge clk) begin
        if(reset)  state <= D;
        else state <= nstate;
    end
    
    always@(*)begin
        case(state)
            D: {fr3,fr2,fr1,dfr} = 4'b1111;
            C1: {fr3,fr2,fr1,dfr} = 4'b0111;
            C2: {fr3,fr2,fr1,dfr} = 4'b0110;
            B1: {fr3,fr2,fr1,dfr} = 4'b0011;
            B2: {fr3,fr2,fr1,dfr} = 4'b0010;
            A: {fr3,fr2,fr1,dfr} = 4'b0000;
            default: {fr3, fr2, fr1, dfr} = 'x;
        endcase
    end

    
    

endmodule

10、Lemmings1

知识点:next_state跟新的时候一定要把所以情况考虑到,不然会出现意外错误,如下:看似逻辑没问题,但是运行通不过

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    output walk_left,
    output walk_right); //  

    parameter LEFT=0, RIGHT=1;//2^1 = 2
    reg state, next_state;  

    always @(*) begin
        if(state == LEFT&&bump_left)
            next_state <= RIGHT;
        else if(state==RIGHT && bump_right)
            next_state <= LEFT;
    end

    always @(posedge clk, posedge areset) begin
        if(areset) state = LEFT;
        else state <= next_state;
    end
    
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);

endmodule

答案:

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    output walk_left,
    output walk_right); //  

    parameter LEFT=0, RIGHT=1;//2^1 = 2
    reg state, next_state;  

    always @(*) begin
        case(state)
            LEFT: begin
                if(bump_left) next_state = RIGHT;
                else next_state = LEFT;
            end
            RIGHT: begin
                if(bump_right) next_state = LEFT;
                else next_state = RIGHT;
            end
            default: begin
               next_state = LEFT; 
            end
        endcase       
    end

    always @(posedge clk, posedge areset) begin
        if(areset) state = LEFT;
        else state <= next_state;
    end
    
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);

endmodule

11、Lemmings2⭐

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    output walk_left,
    output walk_right,
    output aaah ); 
    parameter LEFT = 0, RIGHT = 1 , F_L = 2 , F_R = 3;
    reg [1:0] state , next_state;
    //next_state更新
    always @(*) begin
        case(state)
            LEFT:next_state <= ground?(bump_left?RIGHT:LEFT):F_L;
            RIGHT:next_state<= ground?(bump_right?LEFT:RIGHT):F_R;
            F_L:next_state<=ground?LEFT:F_L;
            F_R:next_state<=ground?RIGHT:F_R;
        endcase
    end
    
    //state更新
    always @(posedge clk,posedge areset) begin
        if(areset) state <= LEFT;
        else state<=next_state;
    end
    
    //out更新
    assign walk_left = (state==LEFT);
    assign walk_right = (state==RIGHT);
    assign aaah = (state == F_L ||state ==F_R);
        
endmodule

12、Lemmings 3

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output walk_left,
    output walk_right,
    output aaah,
    output digging ); 
    
    parameter R = 3'b000, L = 3'b001, F_R = 3'b010, F_L = 3'b011, D_R = 3'b100 , D_L = 3'b101;
    reg [2:0] state , next_state;
    
    always @(*) begin
        case(state)
            R:next_state <= ground?(dig?D_R:(bump_right?L:R)):F_R;
            L:next_state <= ground?(dig?D_L:(bump_left?R:L)):F_L;
            F_R:next_state <= ground?(R):F_R;
            F_L:next_state <= ground?(L):F_L;
            D_R:next_state <= ground?D_R:F_R;
            D_L:next_state <= ground?D_L:F_L;
        endcase
    end
    
    always @(posedge clk , posedge areset) begin
        if(areset) state <= L;
        else state <= next_state;
    end
	// 输出更新
    assign walk_left = (state == L);
    assign walk_right = (state == R);
    assign aaah = (state == F_R || state == F_L);
    assign digging = (state == D_R || state == D_L);
endmodule

13、Lemmings4⭐

知识点:寄存器的计数一定是对next_state的统计。

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output walk_left,
    output walk_right,
    output aaah,
    output digging ); 
    
// states definition
	parameter L=0,R=1,L_G=2,R_G=3,L_D=4,R_D=5,S=6;
    reg [2:0] current_state, next_state;
// states transmission    
    always@(posedge clk or posedge areset) begin
        if(areset) begin
            current_state <= L;
        end
        else begin
            current_state <= next_state;
        end
    end
// counting for splatter state       
    reg [6:0] cout;
    always@(posedge clk or posedge areset) begin
        if(areset) begin
            cout <= 5'd0;
        end
        else if( (next_state == L_G) || (next_state == R_G) ) begin
            cout <= cout + 1'b1;
        end
        else begin
            cout <= 5'd0;
        end
    end
// next_state judgement            
    always@(*) begin
        case(current_state)
            L: next_state = ~ground ? L_G : ( dig ? L_D : (bump_left ? R : L) );
            R: next_state = ~ground ? R_G : ( dig ? R_D : (bump_right ? L : R) );
            L_G: next_state = ground ? ( cout > 5'd20 ? S : L ) : L_G;
            R_G: next_state = ground ? ( cout > 5'd20 ? S : R ) : R_G;
            L_D: next_state = ~ground ? L_G : L_D;
            R_D: next_state = ~ground ? R_G : R_D;
            S: next_state = S;
        endcase
    end     
// output logic
    assign walk_left = (current_state == L);
    assign walk_right = (current_state == R);
    assign aaah = ((current_state == L_G) || (current_state == R_G));
    assign digging = ((current_state == L_D) || (current_state == R_D));

endmodule

13、PS/2 packet parser

one-hot编码:利用其只有一位是1来简化操作。

module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);
    assign next_state[0] = state[0]&~in|state[1]&~in|state[2]&~in|state[3]&~in|state[4]&~in|state[7]&~in|state[8]&~in|state[9]&~in;
    assign next_state[1] = state[0]&in|state[8]&in|state[9]&in;
    assign next_state[2] = state[1]&in;
    assign next_state[3] = state[2]&in;
    assign next_state[4] = state[3]&in;
    assign next_state[5] = state[4]&in;
    assign next_state[6] = state[5]&in;
    assign next_state[7] = state[6]&in|state[7]&in;
    assign next_state[8] = state[5]&~in;
    assign next_state[9] = state[6]&~in;

    
    assign out1 = state[8]|state[9];
    assign out2 = state[7]|state[9];
        

endmodule

14、PS/2 packet parser⭐

不太懂题目意思,照着hint中的状态图写的

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
	
    parameter A = 0 , B  = 1, C  = 2, D = 3;
    reg [1:0] state , next_state; 
    // State transition logic (combinational)
    always @(*) begin
        case(state)
            A:next_state<=in[3]?B:A;
            B:next_state<=C;
            C:next_state<=D;
            D:next_state <= in[3]?B:A;
        endcase
    end

    // State flip-flops (sequential)
    always @(posedge clk) begin
        if(reset) state <= A;
        else state <= next_state;
         
    end
 
    // Output logic
    assign done = (state == D);

endmodule

15、PS/2 packet parser and datapath⭐

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output [23:0] out_bytes,
    output done); //

    // FSM from fsm_ps2
        parameter A = 0 , B  = 1, C  = 2, D = 3;
    reg [1:0] state , next_state; 
    // State transition logic (combinational)
    always @(*) begin
        case(state)
            A:next_state<=in[3]?B:A;
            B:next_state<=C;
            C:next_state<=D;
            D:next_state <= in[3]?B:A;
        endcase
    end
    // State flip-flops (sequential)
    always @(posedge clk) begin
        if(reset) state <= A;
        else state <= next_state;    
    end
    // Output logic
    assign done = (state == D);

    // New: Datapath to store incoming bytes.
    reg [23:0] out_reg;
    always @(posedge clk) begin
        if(reset) out_reg <= 24'b0;
        else begin
            case(next_state)
                B:out_reg[23:16] <= in[7:0];
                C:out_reg[15:8] <= in[7:0];
                D:out_reg[7:0] <= in[7:0];
            endcase
        end    
    end
    assign out_bytes = done ? out_reg : 24'b0;
endmodule

16、Serial receiver]

参考链接

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    parameter [3:0] IDLE  = 4'd0;
    parameter [3:0] START = 4'd1;
    parameter [3:0] BIT1  = 4'd2;
    parameter [3:0] BIT2  = 4'd3;
    parameter [3:0] BIT3  = 4'd4;
    parameter [3:0] BIT4  = 4'd5;
    parameter [3:0] BIT5  = 4'd6;
    parameter [3:0] BIT6  = 4'd7;
    parameter [3:0] BIT7  = 4'd8;
    parameter [3:0] BIT8  = 4'd9;
    parameter [3:0] STOP  = 4'd10;
    parameter [3:0] ERROR  = 4'd11;
    reg [3:0] state,nstate;
    
    always @(posedge clk)begin
        if(reset)begin
            state <= IDLE;
        end
        else begin
           state <= nstate; 
        end
    end
    
    always @(*)begin
       nstate = IDLE;
        case(state)
            IDLE: nstate = in? IDLE:START;
            START:nstate = BIT1;
            BIT1: nstate = BIT2;
            BIT2: nstate = BIT3;
            BIT3: nstate = BIT4;
            BIT4: nstate = BIT5;
            BIT5: nstate = BIT6;
            BIT6: nstate = BIT7;
            BIT7: nstate = BIT8;
            BIT8: nstate = in? STOP:ERROR;
            STOP: nstate = in? IDLE:START;
            ERROR: nstate = in? IDLE:ERROR;
            default: nstate = IDLE;
        endcase
    end
    
    assign done = (state == STOP);
endmodule

17、Serial receiver and datapath⭐

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //
    // Use FSM from Fsm_serial
    parameter [3:0] IDLE  = 4'd0;
    parameter [3:0] START = 4'd1;
    parameter [3:0] BIT1  = 4'd2;
    parameter [3:0] BIT2  = 4'd3;
    parameter [3:0] BIT3  = 4'd4;
    parameter [3:0] BIT4  = 4'd5;
    parameter [3:0] BIT5  = 4'd6;
    parameter [3:0] BIT6  = 4'd7;
    parameter [3:0] BIT7  = 4'd8;
    parameter [3:0] BIT8  = 4'd9;
    parameter [3:0] STOP  = 4'd10;
    parameter [3:0] ERROR  = 4'd11;
    reg [3:0] state,nstate;
    always @(posedge clk)begin
        if(reset)begin
            state <= IDLE;
        end
        else begin
           state <= nstate; 
        end
    end
    always @(*)begin
       nstate = IDLE;
        case(state)
            IDLE: nstate = in? IDLE:START;
            START:nstate = BIT1;
            BIT1: nstate = BIT2;
            BIT2: nstate = BIT3;
            BIT3: nstate = BIT4;
            BIT4: nstate = BIT5;
            BIT5: nstate = BIT6;
            BIT6: nstate = BIT7;
            BIT7: nstate = BIT8;
            BIT8: nstate = in? STOP:ERROR;
            STOP: nstate = in? IDLE:START;
            ERROR: nstate = in? IDLE:ERROR;
            default: nstate = IDLE;
        endcase
    end
    assign done = (state == STOP);
    
    // New: Datapath to latch input bits.
    reg [7:0] data_r;
    always @(posedge clk)begin
        case(nstate)
            BIT1: data_r <= {in,data_r[7:1]};
            BIT2: data_r <= {in,data_r[7:1]};
            BIT3: data_r <= {in,data_r[7:1]};
            BIT4: data_r <= {in,data_r[7:1]};
            BIT5: data_r <= {in,data_r[7:1]};
            BIT6: data_r <= {in,data_r[7:1]};
            BIT7: data_r <= {in,data_r[7:1]};
            BIT8: data_r <= {in,data_r[7:1]}; 
        endcase
    end
    

    assign out_byte = (state == STOP)? data_r:0;
    

endmodule

18、Serial receiver with parity checking

19、Sequence recognition

20、Q8:Design a Mealy FSM

知识点:

  • Moore型状态机:下一状态只由当前状态决定,即次态=f(现状,输入),输出=f(现状);
  • mealy状态机,下一状态不但与当前状态有关,还与当前输入值有关,即次态=f(现状,输入),输出=f(现状,输入);

题解参考链接

法一:利用了四种状态没有满足题目要求

module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z ); 
    parameter IDLE = 0, BIT1 = 1,BIT2 = 2,BIT3 = 3;
    reg [1:0] state , next_state;
    
    always @(*) begin 
        case(state)
            IDLE:next_state<=x?BIT1:IDLE;
            BIT1:next_state<=x?BIT1:BIT2;
            BIT2:next_state<=x?BIT3:IDLE;   
            BIT3:next_state<=x?BIT1:BIT2;
        endcase
    end
    
    always @(posedge clk, negedge aresetn) begin
        if(~aresetn) state <= 0;
        else state <= next_state;
    end
    assign z = ((state == BIT2) && (x == 1))? 1'b1:1'b0;
endmodule

法二:只用三种状态

module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z ); 
    parameter IDLE = 0, BIT1 = 1,BIT2 = 2;
    reg [1:0] state , next_state;
    
    always @(*) begin 
        case(state)
            IDLE:next_state = x?BIT1:IDLE;
            BIT1:next_state = x?BIT1:BIT2;
            BIT2:next_state = x?BIT1:IDLE;   
        endcase
    end
    
    always @(posedge clk, negedge aresetn) begin
        if(~aresetn) state <= 0;
        else state <= next_state;
    end
    assign z = ((state == BIT2) && (x == 1))? 1'b1:1'b0;
endmodule

21、Q5a:Serial two's complementer (Moore FSM)

22、Q5a:Serial two's complementer (Mealy FSM)

23、Q3a:FSM⭐⭐(很有代表性)

知识点:如果不用计数器,那么要用16种状态才能将所有状态描述完。用计数器来代替重复的工作。

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
    parameter A = 0, B  = 1;
    reg  state,nstate;
    
    always @(posedge clk) begin
        if(reset) state <= A;
        else state <= nstate;
    end
    
    always @(*) begin
        case(state)
            A:nstate = s?B:A;
            B:nstate = B;
        endcase
    end
    
    reg [1:0] clk_cnt , w_cnt;
    // 时钟计数
    always @(posedge clk) begin
        if(reset) clk_cnt <= 0; 
        else if(state == B) begin
            if (clk_cnt==2'd2)
                clk_cnt <= 0;
        	else 
                clk_cnt <= clk_cnt+1'b1;
        end
        else clk_cnt<=0;
    end
    
    
    //w计数
    always @(posedge clk) begin
        if (reset) w_cnt = 0;
        else if(nstate == B) begin
            if(clk_cnt == 2'd0) w_cnt <= w;
            else if(w) w_cnt <= w_cnt + 1;         
        end
    end
    
    assign z=(state==B&&clk_cnt==2'd0&&w_cnt==2'd2);


endmodule

24、Q3b:FSM

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input x,
    output z
);
    parameter s0 = 3'b000,s1 = 3'b001,s2 = 3'b010,s3 = 3'b011,s4 = 3'b100;
    reg [2:0] state , nstate;
    
    always @(posedge clk) begin
        if(reset) state <= s0;
        else state <= nstate;
    end
    
    always @(*) begin
        case(state)
            s0:nstate = x?s1:s0;
            s1:nstate = x?s4:s1;
            s2:nstate = x?s1:s2;
            s3:nstate = x?s2:s1;
            s4:nstate = x?s4:s3;
        endcase
    end
    
    assign z = (state == s3|| state == s4);
endmodule

25、Q3c:FSM logic

module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    parameter s0 = 3'b000,s1 = 3'b001,s2 = 3'b010,s3 = 3'b011,s4 = 3'b100;
    reg [2:0] nstate;
        
    // nstate由x与y决定
    always @(*) begin
        case(y)
            s0:nstate = x?s1:s0;
            s1:nstate = x?s4:s1;
            s2:nstate = x?s1:s2;
            s3:nstate = x?s2:s1;
            s4:nstate = x?s4:s3;
        endcase
    end
    
    assign Y0 = nstate[0];
    assign z = (y == s3|| y == s4);
    
endmodule

26、Q6b:FSM next-state logic

module top_module (
    input [3:1] y,
    input w,
    output Y2);
    
    parameter s0 = 3'b000 , s1 = 3'b001 , s2 = 3'b010 , s3 = 3'b011 , s4 = 3'b100 , s5 = 3'b101;
    reg [3:1] nstate;
    
    always @(*) begin
        case(y)
            s0:nstate = w?s0:s1;
            s1:nstate = w?s3:s2;
            s2:nstate = w?s3:s4;
            s3:nstate = w?s0:s5;
            s4:nstate = w?s3:s4;
            s5:nstate = w?s3:s2;       
        endcase
    end
    
    assign Y2 = nstate[2];
    
    
endmodule

27、Q6c:FSM one-hot next-state logic

one-hot可以简化为组合逻辑

module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);
    
    
    reg [6:1] nstate = '0;
    
    assign nstate[1] = (y[1]|y[4])&w;
    assign nstate[2] = y[1]&~w;
    assign nstate[3] = y[2]&~w|(y[6]&~w);
    assign nstate[4] = w&(y[2]|y[3]|y[5]|y[6]);
    assign nstate[5] = ~w&y[5]|(y[3]&~w);
    assign nstate[6] = y[4]&~w;
    
    assign Y2 = nstate[2];
    assign Y4 = nstate[4];

endmodule

28、Q6:FSM

module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);
    parameter A = 0 ,B = 1,C = 2,D = 3,E = 4,F = 5;
    reg [2:0] state ,nstate;
    
    always @(posedge clk) begin
        if(reset) state <= A;
        else state <= nstate;
    end
    
    always @(*) begin
        case(state)
            A:nstate<=w?A:B;
            B:nstate<=w?D:C;
            C:nstate<=w?D:E;
            D:nstate<=w?A:F;
            E:nstate<=w?D:E;
            F:nstate<=w?D:C;           
        endcase
    end
    assign z = (state==E||state == F);
endmodule

29、Q2a:FSM

module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);
    parameter A = 0 ,B = 1,C = 2,D = 3,E = 4,F = 5;
    reg [2:0] state ,nstate;
    
    always @(posedge clk) begin
        if(reset) state <= A;
        else state <= nstate;
    end
    
    always @(*) begin
        case(state)
            A:nstate<=w?B:A;
            B:nstate<=w?C:D;
            C:nstate<=w?E:D;
            D:nstate<=w?F:A;
            E:nstate<=w?E:D;
            F:nstate<=w?C:D;           
        endcase
    end
    assign z = (state==E||state == F);
endmodule

30、Q2b:One-hot FSM equations

module top_module (
    input [5:0] y,
    input w,
    output Y1,
    output Y3
);
    reg [5:0] nstate = '0;
    
    assign nstate[0] = y[3]&~w|y[0]&~w;
    assign nstate[1] = y[0]&w;
    assign nstate[2] = y[1]&w|y[5]&w;
    assign nstate[3] = y[1]&~w|y[2]&~w|y[4]&~w|y[5]&~w;
    assign nstate[4] = y[4]&w|y[2]&w;
    assign nstate[5] = y[3]&w;
    
    assign Y1 = nstate[1];
    assign Y3 = nstate[3];
    
    

endmodule

31、Q2a:FSM⭐

在这里犯了个错误:

parameter A = 1, B= 2, C= 3, D = 4;

reg [1:0] state ,nstate;

此时寄存器只有两位,无法保存‘4’这个大数字,最终会报错。

module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input [3:1] r,   // request
    output [3:1] g   // grant
); 
    parameter A = 0, B= 1, C= 2, D = 3;
    reg [1:0] state ,nstate;
    
    always @(posedge clk) begin
        if(~resetn) state<=A;
        else state<=nstate;
    end
    
    always @(*) begin

        case(state)
            A:begin
                if(~r[1]&~r[2]&~r[3]) nstate = A;
                else if(r[1]) nstate = B;
                else if(~r[1]&r[2]) nstate = C;
                else if(~r[1]&~r[2]&r[3]) nstate = D;
            end
            B:begin
            if(r[1]) nstate = B;
            else if(~r[1]) nstate = A;
            end
            C:begin
            if(r[2]) nstate = C;
            else if(~r[2]) nstate = A;
            end
            D:begin
           	if(r[3]) nstate = D;
            else if (~r[3]) nstate = A;
            end
            default:nstate = A;
        endcase        
    end
    
    assign g[3] = (state == D);
    assign g[2] = (state == C);
    assign g[1] = (state == B);
endmodule

32、Q2b:Another FSM

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值