You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Modelsim仿真Quartus生成的JK计数器输出始终未定义求助

计数器仿真输出始终未定义的问题解决

我在Quartus中以原理图形式创建了一个计数器,随后从该原理图生成了Verilog设计文件。能够在Modelsim中配置并运行仿真,但计数器的输出(Q0..Q3)始终处于未定义状态。我是Verilog和FPGA的新手,不过按照原理图逻辑,至少Q0应该在每个时钟周期变化才对。

计数器原理图

生成的Verilog设计代码

module jk_counter_full(
    clk,
    JKFF0,
    Q0,
    Q1,
    Q2,
    Q3,
    next
);

input wire  clk;
input wire  JKFF0;
output wire Q0;
output wire Q1;
output wire Q2;
output wire Q3;
output wire next;

reg in1;
wire    in2;
wire    in3;
wire    SYNTHESIZED_WIRE_8;
reg JKFF_inst2;
reg JKFF_inst4;
reg JKFF_inst6;

assign  Q1 = JKFF_inst2;
assign  Q2 = JKFF_inst4;
assign  Q3 = JKFF_inst6;
assign  SYNTHESIZED_WIRE_8 = 1;

always@(posedge clk)
begin
    in1 <= ~in1 & JKFF0 | in1 & ~JKFF0;
end

assign  in2 = in1 & JKFF_inst2;


always@(posedge clk)
begin
    JKFF_inst2 <= ~JKFF_inst2 & in1 | JKFF_inst2 & ~in1;
end

always@(posedge clk)
begin
    JKFF_inst4 <= ~JKFF_inst4 & in2 | JKFF_inst4 & ~in2;
end

assign  in3 = in2 & JKFF_inst4;

always@(posedge clk)
begin
    JKFF_inst6 <= ~JKFF_inst6 & in3 | JKFF_inst6 & ~in3;
end

assign  next = in3 & JKFF_inst6;

assign  Q0 = in1;

endmodule

测试文件代码

timescale 1 ps/ 1 ps
module jk_counter_full_vlg_tst();
reg JKFF0;
reg clk;                                               
wire Q0;
wire Q1;
wire Q2;
wire Q3;
wire next;                          

jk_counter_full i1 (  
    .JKFF0(JKFF0),
    .Q0(Q0),
    .Q1(Q1),
    .Q2(Q2),
    .Q3(Q3),
    .clk(clk),
    .next(next)
);

initial                                                
begin                                                                           
clk = 0;
JKFF0 = 1;                                                                    
end
                                                    
always
#1000  clk =  ! clk;                                                 
                                                    
endmodule

问题分析与解决

核心问题

设计中的所有寄存器(in1、JKFF_inst2、JKFF_inst4、JKFF_inst6)都没有设置初始值。在Verilog仿真中,未初始化的寄存器默认值为x(未定义状态),所有基于这些寄存器的运算结果也会是x,最终导致输出始终未定义。

修复方案

方案1:在设计模块中直接初始化寄存器

给每个寄存器添加初始赋值,硬件实现时FPGA会自动处理复位,仿真时则会从初始值开始运行:

module jk_counter_full(
    clk,
    JKFF0,
    Q0,
    Q1,
    Q2,
    Q3,
    next
);

input wire  clk;
input wire  JKFF0;
output wire Q0;
output wire Q1;
output wire Q2;
output wire Q3;
output wire next;

reg in1 = 1'b0;          // 初始化in1为0
wire    in2;
wire    in3;
wire    SYNTHESIZED_WIRE_8;
reg JKFF_inst2 = 1'b0;   // 初始化JKFF_inst2为0
reg JKFF_inst4 = 1'b0;   // 初始化JKFF_inst4为0
reg JKFF_inst6 = 1'b0;   // 初始化JKFF_inst6为0

// 其余代码保持不变...

方案2:在测试文件中初始化寄存器(不修改设计代码)

通过测试文件直接对设计内部的寄存器赋值,适合不想改动原设计的场景:

timescale 1 ps/ 1 ps
module jk_counter_full_vlg_tst();
reg JKFF0;
reg clk;                                               
wire Q0;
wire Q1;
wire Q2;
wire Q3;
wire next;                          

jk_counter_full i1 (  
    .JKFF0(JKFF0),
    .Q0(Q0),
    .Q1(Q1),
    .Q2(Q2),
    .Q3(Q3),
    .clk(clk),
    .next(next)
);

initial                                                
begin                                                                           
    clk = 0;
    JKFF0 = 1;
    // 初始化设计内部的寄存器
    i1.in1 = 1'b0;
    i1.JKFF_inst2 = 1'b0;
    i1.JKFF_inst4 = 1'b0;
    i1.JKFF_inst6 = 1'b0;
end
                                                    
always
    #1000  clk =  ! clk;                                                 
                                                    
endmodule

可选优化:简化触发器逻辑

原代码中JK触发器的逻辑可以简化,比如第一个触发器的代码可以替换为更直观的异或操作,效果完全一致:

always@(posedge clk)
begin
    in1 <= in1 ^ JKFF0; // 等价于原逻辑,更简洁
end

验证效果

修改后重新运行仿真,Q0会在每个时钟上升沿翻转,Q1会在Q0为1时翻转,以此类推,计数器就能正常工作了。


内容的提问来源于stack exchange,提问作者bibo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 01:14:53