当前位置:   article > 正文

3 Verilog入门篇之时序逻辑_状态转移表实现时序电路verilog

状态转移表实现时序电路verilog

VL21 根据状态转移表实现时序电路

描述

某同步时序电路转换表如下,请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。

电路的接口如下图所示。

输入描述:

      input                A   ,
      input                clk ,
      input                rst_n

输出描述:

output wire Y

题意整理

本题要求根据时序电路的状态表实现同步时序电路,要求使用D触发器。

题解主体

基础的时序电路设计,可采用列激励方程、输出方程,进而用D触发器和组合逻辑电路实现的方案。

由状态表可得出,电路共4个状态,所以使用2个寄存器来实现状态的寄存。两个寄存器的输出为Q1和Q0。

由状态转换表可列出激励方程如下:

Q_1^{n+1}=D1=Q_1^n ⊕Q_0^n·~A+Q_1^n⊙Q_0^n·A=Q_1^n ⊕Q_0^n⊕AQ1n+1​=D1=Q1n​⊕Q0n​⋅ A+Q1n​⊙Q0n​⋅A=Q1n​⊕Q0n​⊕A

Q_0^{n+1}=D0=~Q_0^nQ0n+1​=D0= Q0n​

输出方程如下:

Y=Q_1 ·Q_0Y=Q1​⋅Q0​

表中的Qn表示现态,Qn+1表示次态

根据激励方程和输出方程以及思路整理,关键电路如下:

将电路转换成Verilog代码描述如下:

  1. `timescale 1ns/1ns
  2. module seq_circuit(
  3. input A ,
  4. input clk ,
  5. input rst_n,
  6. output wire Y
  7. );
  8. reg Q1 ;
  9. reg Q0 ;
  10. always @(posedge clk or negedge rst_n)begin
  11. if(!rst_n)
  12. Q1 <= 1'b0;
  13. else
  14. Q1 <= Q1 ^ Q0 ^A;
  15. end
  16. always @(posedge clk or negedge rst_n)begin
  17. if(!rst_n)
  18. Q0 <= 1'b0;
  19. else
  20. Q0 <= ~Q0;
  21. end
  22. assign Y = Q1 & Q0;
  23. endmodule

答案2

可以看成是两个状态检测机,利用FSM实现

先拆分状态,有四个状态

  1. IDLE=2'b00;
  2. S1=2'b01;
  3. S2=2'b10;
  4. S3=2'b11;

利用两段式状态机

  1. 第一段描述状态跳变
  2. 第二段描述跳变条件
  3. 利用if 判断输入A,从而决定下一状态
    1. `timescale 1ns/1ns
    2. module seq_circuit(
    3. input A ,
    4. input clk ,
    5. input rst_n,
    6. output wire Y
    7. );
    8. parameter IDLE = 2'b00 ;
    9. parameter S1 = 2'b01 ;
    10. parameter S2 = 2'b10 ;
    11. parameter S3 = 2'b11 ;
    12. reg [1:0] CS ;
    13. reg [1:0] NS ;
    14. always@(posedge clk or negedge rst_n) begin
    15. if(!rst_n) begin
    16. CS <= IDLE ;
    17. end
    18. else
    19. CS <= NS ;
    20. end
    21. always@(* ) begin
    22. case(CS)
    23. IDLE: begin
    24. if(A==0) begin
    25. NS <= S1 ;
    26. end
    27. else begin
    28. NS <= S3 ;
    29. end
    30. end
    31. S1: begin
    32. if(A==0) begin
    33. NS <= S2 ;
    34. end
    35. else begin
    36. NS <= IDLE ;
    37. end
    38. end
    39. S2: begin
    40. if(A==0) begin
    41. NS <= S3 ;
    42. end
    43. else begin
    44. NS <= S1 ;
    45. end
    46. end
    47. S3: begin
    48. if(A==0) begin
    49. NS <= IDLE ;
    50. end
    51. else begin
    52. NS <= S2 ;
    53. end
    54. end
    55. endcase
    56. end
    57. assign Y=(CS==S3)?1:0;
    58. endmodule

VL22 根据状态转移图实现时序电路 

 描述

某同步时序电路的状态转换图如下,→上表示“C/Y”,圆圈内为现态,→指向次态。

请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。

电路的接口如下图所示,C是单bit数据输入端。 

输入描述:

   input                C   ,
   input                clk ,
   input                rst_n

输出描述:

      output   wire        Y 

题意整理

本题要求根据题目提供的状态转换图实现同步时序电路,要求使用D触发器。

题解主体

本题提供的是状态转换图,可采用状态机实现,也可采用列激励方程、输出方程,进而用D触发器和组合逻辑电路实现。本题解采用第二种方案实现。

由状态转换图可得出,电路共4个状态,所以使用2个寄存器来实现状态的寄存。两个寄存器的输出为Q1和Q0,两个寄存器的输入为D1和D0。可列出状态转换表如下:

由状态转换表可列出激励方程如下:

Q_1^{n+1}=D1=Q_1^n ·Q_0^n+Q_1^n·\bar{Q_0^n}·C+~\bar{Q_1^n}·Q_0^n·\bar{C}Q1n+1​=D1=Q1n​⋅Q0n​+Q1n​⋅Q0n​ˉ​⋅C+ Q1n​ˉ​⋅Q0n​⋅Cˉ

Q_0^{n+1}=D0=\bar{Q_1^n} ·Q_0^n+\bar{Q_1^n}·\bar{Q_0^n}·C+Q_1^n·Q_0^n·\bar{C}Q0n+1​=D0=Q1n​ˉ​⋅Q0n​+Q1n​ˉ​⋅Q0n​ˉ​⋅C+Q1n​⋅Q0n​⋅Cˉ

输出方程如下:

Y=C·Q_1+Q_1 ·Q_0Y=C⋅Q1​+Q1​⋅Q0​

根据激励方程和输出方程以及思路整理,关键电路如下:

将电路转换成Verilog代码描述如下:

  1. reg Q1 ;
  2. reg Q0 ;
  3. always @(posedge clk or negedge rst_n)begin
  4. if(!rst_n)
  5. Q1 <= 1'b0;
  6. else
  7. Q1 <= (Q1 & (Q0 | C)) | (~Q1 & Q0 & ~C);
  8. end
  9. always @(posedge clk or negedge rst_n)begin
  10. if(!rst_n)
  11. Q0 <= 1'b0;
  12. else
  13. Q0 <= (~Q1 & (Q0 | C)) | (Q1 & Q0 & ~C);
  14. end
  15. assign Y = (C & Q1) | (Q1 & Q0);

三段式FSM

  1. `timescale 1ns/1ns
  2. module seq_circuit(
  3. input C ,
  4. input clk ,
  5. input rst_n,
  6. output wire Y
  7. );
  8. reg [1:0] state, next_state;
  9. // state transition
  10. always @ (posedge clk or negedge rst_n) begin
  11. if (!rst_n) begin
  12. state <= 2'b00;
  13. end
  14. else begin
  15. state <= next_state;
  16. end
  17. end
  18. // next_state logic
  19. always @ (*) begin
  20. next_state = 2'b00;
  21. case (state)
  22. 2'b00: next_state = C ? 2'b01 : 2'b00;
  23. 2'b01: next_state = C ? 2'b01 : 2'b11;
  24. 2'b10: next_state = C ? 2'b10 : 2'b00;
  25. 2'b11: next_state = C ? 2'b10 : 2'b11;
  26. default: next_state = state;
  27. endcase
  28. end
  29. // output logic
  30. assign Y = (next_state == 2'b10) | (state == 2'b11);
  31. endmodule

 VL23 ROM的简单实现

描述

实现一个深度为8,位宽为4bit的ROM,数据初始化为0,2,4,6,8,10,12,14。可以通过输入地址addr,输出相应的数据data。

接口信号图如下:

      

输入描述:

clk:系统时钟

rst_n:异步复位信号,低电平有效

addr:8bit位宽的无符号数,输入到ROM的地址

输出描述:

data:4bit位宽的无符号数,从ROM中读出的数据

题解主体

       要实现ROM,首先要声明数据的存储空间,例如:[3:0] rom [7:0];变量名称rom之前的[3:0]表示每个数据具有多少位,指位宽;变量名称rom之后的[7:0]表示需要多少个数据,指深度,注意这里深度为8,应该是使用[7:0],而不是[2:0];

       声明存储变量之后,需要对rom进行初始化,写入数据,然后将输入地址作为rom的索引值,将索引值对应的数据输出。

可以按照如下的方式开辟存储空间,并进行数据初始化:

       reg [3:0] rom_data [7:0];

//保持ROM中的数据不变

       always @(posedge clk or negedge rst_n)

              if (!rst_n)                                          //对ROM中的数据进行初始化

                     begin

                            rom_data[0] <= 4'd0;

                            rom_data[1] <= 4'd2;

                            rom_data[2] <= 4'd4;

                            rom_data[3] <= 4'd6;         

                            rom_data[4] <= 4'd8;

                            rom_data[5] <= 4'd10;

                            rom_data[6] <= 4'd12;

                            rom_data[7] <= 4'd14;

                     end

              else

                     begin                                               //保持ROM中的数据不变

                            rom_data[0] <= 4'd0;

                            rom_data[1] <= 4'd2;

                            rom_data[2] <= 4'd4;

                            rom_data[3] <= 4'd6;         

                            rom_data[4] <= 4'd8;

                            rom_data[5] <= 4'd10;

                            rom_data[6] <= 4'd12;

                            rom_data[7] <= 4'd14;

                     end

初始化完成之后的rom的形式如下,内部存在地址和数据的对应关系,通过输入相应的地址,可以得到相应的输出数据。

      

       always @(posedge clk or negedge rst_n)

              if (!rst_n)

                     data <= 4'd0;

              else

                     data <= rom_data[addr];

只需要将地址作为rom的索引,即可得到相应的数据

  1. `timescale 1ns/1ns
  2. module rom(
  3. input clk,
  4. input rst_n,
  5. input [7:0]addr,
  6. output [3:0]data
  7. );
  8. reg [3:0] rom_data [7:0];
  9. assign data = rom_data[addr];
  10. //保持ROM中的数据不变
  11. always @(posedge clk or negedge rst_n)
  12. if (!rst_n)
  13. begin
  14. rom_data[0] <= 4'd0;
  15. rom_data[1] <= 4'd2;
  16. rom_data[2] <= 4'd4;
  17. rom_data[3] <= 4'd6;
  18. rom_data[4] <= 4'd8;
  19. rom_data[5] <= 4'd10;
  20. rom_data[6] <= 4'd12;
  21. rom_data[7] <= 4'd14;
  22. end
  23. else
  24. begin
  25. rom_data[0] <= rom_data[0];
  26. rom_data[1] <= rom_data[1];
  27. rom_data[2] <= rom_data[2];
  28. rom_data[3] <= rom_data[3];
  29. rom_data[4] <= rom_data[4];
  30. rom_data[5] <= rom_data[5];
  31. rom_data[6] <= rom_data[6];
  32. rom_data[7] <= rom_data[7];
  33. end
  34. endmodule

VL24 边沿检测

描述

有一个缓慢变化的1bit信号a,编写一个程序检测a信号的上升沿给出指示信号rise,当a信号出现下降沿时给出指示信号down。
注:rise,down应为单脉冲信号,在相应边沿出现时的下一个时钟为高,之后恢复到0,一直到再一次出现相应的边沿。

输入描述:

clk:系统时钟信号

rst_n:异步复位信号,低电平有效

a:单比特信号,作为待检测的信号

输出描述:

rise:单比特信号,当输入信号a出现上升沿时为1,其余时刻为0

down:单比特信号,当输入信号a出现下降沿时为1,其余时刻为0

题意整理

       题目要求检测输入信号a的边沿,即当a信号的值从0跳变到1,视为出现上升沿,把指示信号rise拉高;当a信号的值从1跳变到0,视为出现下降沿,把指示信号down拉高。其余时刻两个指示信号因保持0。

题解主体

       检测信号a的边沿需要缓存信号前一时刻的值,例如记为a_tem。当前一时刻为0,这一时刻为1,说明信号出现上升沿,即 a&&!a_tem = 1; 当前一时刻为1,这一时刻为0,说明信号出现上升沿,即 !a&&a_tem = 1;

       输入信号:

              系统时钟,复位信号:clk,rst_n;

              待检测边沿的信号:a;

       输出信号:

              上升沿指示信号:rise

              下降沿指示信号:down

缓存a的数值

       always @(posedge clk or negedge rst_n)

              if (!rst_n)

                     a_tem <= 1'b0;

              else

                     a_tem <= a;

分别使用a&&!a_tem和!a&&a_tem作为判断条件,判断是否出现上升沿或者下降沿。

//检测边沿,给出相应的信号

       always @(posedge clk or negedge rst_n)

              if (!rst_n)

                     begin

                            rise <= 1'b0;

                            down <= 1'b0;

                     end

else if (!a_tem && a)   //当前一时刻a=0,当前时刻a=1,表示a出现一次上升沿

                     begin

                            rise <= 1'b1;

                            down <= 1'b0;

                     end

              else if     (a_tem && !a)//当前一时刻a=1,当前时刻a=0,表示a出现一次下降沿

                     begin

                            down <= 1'b1;

                            rise <= 1'b0;

                     end

              else

                     begin

                            down <= 1'b0;

                            rise <= 1'b0;

                     end

  1. `timescale 1ns/1ns
  2. module edge_detect(
  3. input clk,
  4. input rst_n,
  5. input a,
  6. output reg rise,
  7. output reg down
  8. );
  9. reg a_tem;
  10. //缓存a的数值
  11. always @(posedge clk or negedge rst_n)
  12. if (!rst_n)
  13. a_tem <= 1'b0;
  14. else
  15. a_tem <= a;
  16. //检测边沿,给出相应的信号
  17. always @(posedge clk or negedge rst_n)
  18. if (!rst_n)
  19. begin
  20. rise <= 1'b0;
  21. down <= 1'b0;
  22. end
  23. else if (!a_tem && a) //当前一时刻a=0,当前时刻a=1,表示a出现一次上升沿
  24. begin
  25. rise <= 1'b1;
  26. down <= 1'b0;
  27. end
  28. else if (a_tem && !a) //当前一时刻a=1,当前时刻a=0,表示a出现一次下降沿
  29. begin
  30. down <= 1'b1;
  31. rise <= 1'b0;
  32. end
  33. else
  34. begin
  35. down <= 1'b0;
  36. rise <= 1'b0;
  37. end
  38. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/603069
推荐阅读
相关标签
  

闽ICP备14008679号