Verilog JK触发器状态图实现的错误输出

Verilog JK触发器状态图实现的错误输出,verilog,iverilog,Verilog,Iverilog,我试图在verilog中实现一个简单的JK触发器FSM。然而,我发现输出'q'和'q_not'对于多个时间瞬间是错误的。我在下面介绍代码和输出。谁能告诉我密码有什么问题吗。特别是我想知道这个实现有什么问题,即使有其他方法来实现JK触发器 JK触发器模块及测试台 `timescale 1ns/100ps module jk_ff(j, k, clk, reset, q, q_not); input j, k, clk, reset; output reg q, q_not; reg pre

我试图在verilog中实现一个简单的JK触发器FSM。然而,我发现输出'q'和'q_not'对于多个时间瞬间是错误的。我在下面介绍代码和输出。谁能告诉我密码有什么问题吗。特别是我想知道这个实现有什么问题,即使有其他方法来实现JK触发器

JK触发器模块及测试台

`timescale 1ns/100ps

module jk_ff(j, k, clk, reset, q, q_not);

input j, k, clk, reset;

output reg q, q_not;

reg present_state, next_state;

parameter state_a = 1'b0;
parameter state_b = 1'b1;

always @ (present_state or j or k)
begin:comb_logic

 next_state = state_a;
 //next_state = 0;

 case(present_state)

  state_a: begin
   if (j == 1'b0 && k == 1'b0) begin
     next_state = state_a;
     end
   else if (j == 1'b0 && k == 1'b1) begin
     next_state = state_a;
     end
   else if (j == 1'b1 && k == 1'b0) begin
     next_state = state_b;
     end
   else if (j == 1'b1 && k == 1'b1) begin
     next_state = state_b;
     end
   end

  state_b: begin
   if (j == 1'b0 && k == 1'b0) begin
     next_state =  state_b;
   end
   else if (j == 1'b0 && k == 1'b1) begin
     next_state = state_a;
   end
   else if (j == 1'b1 && k == 1'b0) begin
     next_state = state_b;
   end
   else if (j == 1'b1 && k == 1'b1) begin
     next_state = state_a;
   end
  end
  default: next_state = state_a;
 endcase 
end

always @ (posedge clk or reset)
begin: seq_logic

if (reset) begin
 q <= 1'b0;
 q_not <= 1'b1;
 present_state <= state_a;
 end
 else begin
 present_state <= next_state;

 case(present_state)

   state_a: begin
    q <= 1'b0;
    q_not <= 1'b1;
   end
   state_b: begin
    q <= 1'b1;
    q_not <= 1'b0;
   end
   default: present_state <= state_a;

  endcase
  end
 end

endmodule

//testbench

module jk_ff_tb;

reg j, k, clk, reset;

wire q, q_not;

jk_ff DUT(.j(j), .k(k), .clk(clk), .reset(reset), .q(q), .q_not(q_not));

initial begin
clk =0;
forever #5 clk = !clk;
end

initial begin
 $monitor("j = %b, k = %b, q = %b, q_not = %b", j, k, q, q_not);
 $dumpfile("jk_ff_wave.vcd");
 $dumpvars;
 reset = 1;
 j=1'b0;
 k=1'b1;
#10 reset = 0;

 #15 j=1'b1;
 #15 k=1'b0;
 #15 j=1'b0;
 #15 k=1'b1;
 #15 j=1'b1;
 #15 k=1'b1;


 #10 $finish;  

end

endmodule

这里有各种各样的问题:

  • seq_logic
    中,您使用阻塞赋值赋值
    当前_状态
    ,下一个语句是
    case(当前_状态)
    。这将测试
    当前状态的旧值,这不是您想要的
  • 您的“梳状逻辑”进程对
    当前状态
    敏感,但您的
    序列逻辑
    进程在上升时钟边缘上发生变化
    当前状态
    。乍一看,这似乎是正确的做法,但事实并非如此——把它拉出来。按照你写这篇文章的方式,
    comb_逻辑
    应该只对
    J
    K
  • 这两个都足以得到正确的结果,但是对于JK重新启动来说,这太复杂了,把所有东西都放在一个时钟进程中,转储下一个逻辑进程,只需要使用JK加载、设置或切换的行为。您还应该将当前时间添加到
    $monitor