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

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

大家好,我是讯享网,很高兴认识大家。

一、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'bzz:pos = 4'b101; 8'bz:pos = 4'b110; 8'b: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
0 0 0 0
0 1 0 0
1 1 0 1
1 0 1 0
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

a b cout sum
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 0
讯享网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 = 0 in = 1
reg_in = 0 0 1
reg_in = 1 0 0

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 = 0 in = 1
reg_in = 0 0 1
reg_in = 1 1 0
讯享网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=0 in=1
out'=0 reg=0 0 0
out'=0 reg=1 1 0
out'=1 reg=1 1 1
out'=1 reg=0 1 1

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

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

小讯
上一篇 2025-01-04 17:35
下一篇 2025-03-24 19:59

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/18177.html