【问题标题】:Verilog wires being set to X instead 1Verilog 线被设置为 X 而不是 1
【发布时间】:2015-11-30 19:52:13
【问题描述】:

我目前正在用 Verilog 编写一个包含多个模块的二十一点游戏,包括游戏逻辑和计分。我的项目的目标是通过 VGA 和 nexys3 FPGA 板在屏幕上显示二十一点游戏。在设置 VGA 之前,我需要确保我的游戏逻辑正常工作并正确设置玩家手和玩家得分。不幸的是,玩家的手没有正确设置,并且在应该是 1 的地方显示 X 值。下面是我所有的模块和代码,底部是我正在运行的模拟:

这是调用我其他模块的主模块。

module blackJack(
    input clk,
    input btnhit,   //deal card to player
     input btnpass, //stay for player/pass to dealer
    input btnreset, //reset game to 0 and redeal
     output Hsync,
    output Vsync,
    output reg [2:0] vgaRed,
    output reg [2:0] vgaGreen,
    output reg [1:0] vgaBlue
);

wire [7:0] plscore;
wire [7:0] dlscore;
wire [7:0] plhand;
wire [7:0] dlhand;
wire [2:0] state;
wire [7:0] plcard;
wire [7:0] dlcard;
wire plbust;
wire dlbust;
wire plbj;
wire dlbj;
wire plhit;
wire dlhit;
wire plwin;
wire pllose;
reg vgaclk;
wire trigger;

clock vclk(
    .clk(clk),
    .vgaclk(vgaclk)
);

wire hit;
debouncer hitD(
    .clk(clk),
    .button_in(btnhit),
    .button_out(hit)
    );

wire pass;
debouncer passD(
    .clk(clk),
    .button_in(btnpass),
    .button_out(pass)
    );

wire reset;
debouncer resetD(
    .clk(clk),
    .button_in(btnreset),
    .button_out(reset)
    );

controller cntrl(
     .clk(clk),
     .trigger(trigger),
     .state(state),
    .curPlHand(plhand),
    .curDlHand(dlhand),
     .dlhit(dlhit),
     .plhit(plhit),
     .plwin(plwin),
     .pllose(pllose),
    .plscore(plscore),
    .dlscore(dlscore)
);

randomGen gen(
    .clk(clk),
    .card1(plcard),
    .card2(dlcard)
);

player pl(
     .clk(clk),
    .addCard(plhit),
     .card(plcard),
    .hand(plhand)
    );

player dl(
     .clk(clk),
    .addCard(dlhit),
     .card(dlcard),
    .hand(dlhand)
    );

checkBust chkpl(
    .clk(clk),
   .handTotal(plhand),
   .bust(plbust),
   .blackJack(plbj)
);

checkBust chkdl(
    .clk(clk),
   .handTotal(dlhand),
   .bust(dlbust),
   .blackJack(dlbj)
);

stateMonitor sm(
    .clk(clk),
    .reset(reset),
    .hit(hit),
    .pass(pass),
    .plwin(plwin),
    .pllose(pllose),
    .state(state),
    .trigger(trigger)
);

endmodule

这是每个单独的模块。

module clock(
    input clk,
    output vgaclk
    );

reg vgaclk;
reg [31:0] out = 0;

always @ (posedge clk) begin
    if (out >= 3) begin
        out <= 0;
    end
    if (out == 3) begin
        vgaclk <= 1;
    end
    else begin
        vgaclk <= 0;
    end
    out <= out + 1;
end

endmodule

播放器模块:

module player(
     input clk,
    input addCard,
     input [7:0] card,
    output [7:0] hand
    );

reg [7:0] hand = 0;

always @(posedge clk) begin
    if (addCard == 1)
        hand <= hand + card;
end


endmodule

状态监控模块:

module stateMonitor(
    input clk,
     input reset,
     input hit,
     input pass,
     input plwin,
     input pllose,
     output [2:0] state,
    output trigger
    );

reg [2:0] currentState = 3'b000;
reg action = 1;

//modes
//000 = start of game.  score = 0 and no hand dealt
//001 = player dealt first card
//010 = player dealt second card
//011 = dealer dealt first card - wait for player to hit or pass
//100 = player hits
//101 = player passes -> dealer hits
//110 = payer wins
//111 = player loses

always @ (posedge clk) begin

    if (currentState == 3'b000 && action == 0) begin
        currentState <= 3'b001;
        action <= 1;
    end
    else if (currentState == 2'b001 && action == 0) begin
        currentState <= 3'b010;
        action <= 1;

    end
    else if (currentState == 3'b010 && action == 0) begin
        currentState <= 3'b011;
        action <= 1;
    end
   else if (currentState == 3'b011 && action == 0) begin
        if (plwin == 1) begin
            currentState <= 3'b110;
            action <= 1;
        end 
        else if (hit == 1) begin
            currentState <= 3'b100;
            action <= 1;
        end
        else if (pass == 1) begin
            currentState <= 3'b101;
            action <= 1;
        end
        else if (reset == 1) begin
            currentState <= 3'b000;
            action <= 1;
        end
   end
   else if (currentState == 3'b100 && action == 0) begin
        if (plwin == 1) begin
            currentState <= 3'b110;
            action <= 1;
        end 
        else if (pllose == 1) begin
            currentState <= 3'b111;
            action <= 1;
        end
        else if (hit == 1) begin
            currentState <= 3'b100;
            action <= 1;
        end
        else if (pass == 1) begin
            currentState <= 3'b101;
            action <= 1;
        end
        else if (reset == 1) begin
            currentState <= 3'b000;
            action <= 1;
        end
   end
   else if (currentState == 3'b101 && action == 0) begin
        if (plwin == 1) begin
            currentState <= 3'b110;
            action <= 1;
        end 
        else if (pllose == 1) begin
            currentState <= 3'b111;
            action <= 1;
        end
        else if (reset == 1) begin
            currentState <= 3'b000;
            action <= 1;
        end
        else
            action <= 1;
    end
    else if (currentState == 3'b110 && action == 0) begin
        if (hit == 1)
            currentState <= 3'b000;
    end
    else if (currentState == 3'b111 && action == 0) begin
        if (hit == 1)
            currentState <= 3'b000;
    end
    else
        action <= 0;

end

assign state = currentState;
assign trigger = action;

endmodule

控制器模块:

module controller(
     input clk,
     input trigger,
     input reset,
     input plbust,
     input dlbust,
     input plbj,
     input [2:0] state,
    output [7:0] curPlHand,
    output [7:0] curDlHand,
     output dlhit,
     output plhit,
     output plwin,
     output pllose,
    output [7:0] plscore,
    output [7:0] dlscore
);

reg [7:0] curPlHand;
reg [7:0] curDlHand;
reg [7:0] plscore;
reg [7:0] dlscore;
//reg plbust;
//reg dlbust;
//reg plscore;
//reg dlscore;
reg plhit = 0;
reg dlhit = 0;
reg plwin = 0;
reg pllose = 0;

//modes
//000 = start of game.  score = 0 and no hand dealt
//001 = player dealt first card
//010 = player dealt second card
//011 = dealer dealt first card - wait for player to hit or pass
//100 = player hits
//101 = player passes -> dealer hits
//110 = payer wins
//111 = player loses

always @(*) begin
    if (plbust == 1)
        pllose <= 1;
    else if (plbj == 1)
        plwin <= 1;
    else if (dlbust == 1)
        plwin <= 1;
end

always @(posedge clk) begin
plhit <= 0;
dlhit <= 0;
    if (state == 3'b000 && trigger) begin
        curPlHand <= 8'b00000000;
        curDlHand <= 8'b00000000;
        if (reset == 1) begin
            plscore <= 8'b00000000;
            dlscore <= 8'b00000000;
        end 
    end
    else if (state == 3'b001 && trigger) begin
        plhit <= 1;
    end
    else if (state == 3'b010 && trigger) begin
        plhit <= 1;
    end
    else if (state == 3'b011 && trigger) begin
        if (plbj == 1)
            plwin <= 1;
        else
            dlhit <= 1;
    end
    else if (state == 3'b100 && trigger) begin
        if (plbust == 1)
            pllose <= 1;
        else if (plbj == 1) 
            plwin <= 1;
        else
            plhit <= 1;
    end
    else if (state == 3'b101 && trigger) begin
        if (dlbust == 1)
            plwin <= 1;
        else if (plbust == 1)
            pllose <= 1;
        else if (plbj == 1)
            plwin <= 1;
        else 
            dlhit <= 1;
    end
    /*else if (state == 3'b110) begin

    end
    else if (state == 3'b111) begin 

    end
    */
end

endmodule

随机卡片生成模块:

module randomGen (
    input clk,
    output card1,
    output card2
);

reg [7:0] card1;
reg [7:0] card2;

always @ (posedge clk) begin
    card1 <= ({$random} % 51 >> 2) + 1;
    card2 <= ({$random} % 51 >> 2) + 1;
end
endmodule

检查二十一点和破产模块:

module checkBust (
    input clk,
   input handTotal,
   output bust,
   output blackJack
);

wire [7:0] handTotal;
reg blackJack;
reg bust;

always @(posedge clk) begin
  if(handTotal == 8'd21) begin
    bust <= 0;
    blackJack <= 1;
  end
  else if(handTotal > 8'd21) begin
    bust <= 1;
    blackJack <= 0;
  end
  else begin
    bust <= 0;
    blackJack <= 0;
  end
end
endmodule

FPGA 按钮按下去抖动器:

module debouncer(
    input clk,
    input button_in,
    output button_out
    );

reg [1:0] button_buffer;
assign button_out = button_buffer[0];

always @(posedge clk or posedge button_in) begin
    if (button_in)
        button_buffer <= 2'b11;
    else
        button_buffer <= {1'b0, button_buffer[1]};
    end

endmodule

这是我目前正在运行的测试平台:

module testBlackjack;

    // Inputs
    reg clk;
    reg btnhit;
    reg btnpass;
    reg btnreset;

    // Instantiate the Unit Under Test (UUT)
    blackJack uut (
        .clk(clk), 
        .btnhit(btnhit), 
        .btnpass(btnpass), 
        .btnreset(btnreset)
    );

    initial begin
        // Initialize Inputs
        clk = 0;
        btnhit = 0;
        btnpass = 0;
        btnreset = 0;

        // Wait 100 ns for global reset to finish
        #1000;

        $finish;
    end

    always #20 clk = ~clk;

endmodule

这是我的模拟图像,它只是通过向玩家分配 2 张牌和向庄家分配 1 张牌来测试游戏的初始设置:

从模拟中可以看出,当 plhit = 1 时,卡片 6 被添加到玩家手中(这是玩家模块中的 addcard)。应该在 plhand 中显示的正确值应该是 00000110,但 1 是 X。

我遇到的问题是,当我尝试将一张牌添加到玩家的总手牌得分(8 位)中时,应该为 1 的位被设置为 X。我尝试将 plscore 重新设置为 reg并尝试了多个分配操作,但是我没有运气。任何帮助将不胜感激,如果有任何信息需要,我将很乐意快速回复。

【问题讨论】:

  • 当您尝试合成它时,请检查错误日志中是否有任何有关“闩锁”或其他此类问题的消息。
  • 我没有看到任何“闩锁”错误/警告消息。我收到的唯一警告是关于“不允许重新声明 ansi 端口 *****”的警告,其中 ***** 是我传入的许多变量。这些警告特别是在各个模块中,例如randomGen、播放器等,但不在主二十一点模块中
  • 根据iverilog(不幸的是,我现在没有安装Xilinx 工具),看起来你还没有声明card1card2 都是@ 中的向量987654335@,以及checkBust 中的handTotal 的相同问题。 (换句话说 - 在模块中你说reg [7:0] xyz,但在模块声明中你跳过[7:0])。
  • 好的,我也会调查一下。在以前的项目中,我对这种语法没有任何问题,但是如果它消除了警告,我相信它会帮助程序稳定。
  • 我收到了一些警告 - 这似乎是最相关的,但如果我有时间,我会稍后再尝试,看看我是否可以提供更多帮助。祝你好运!

标签: verilog


【解决方案1】:

如果有问题:

拳头。您正在混合 ANSI 和非 ANSI 标头样式。这是非法的语法。一些模拟器/合成器允许这样做,但这是不好的做法。我已经在这里“object <name> is not declared in verlog”和“Issue with parameters in Modelsim”更深入地回答了与标题相关的问题,所以我将总结一下;遵循 ANSI 或非 ANSI,不要在同一模块中混合标题样式。您可以对不同的模块使用不同的标题样式,但建议保持一致。我更喜欢ANSI风格。

例如:

module clock(
    input clk,
    output vgaclk
    );

reg vgaclk; // <-- this is mixing styles
...

module checkBust (
    input clk,
    input handTotal,
    output bust,
    output blackJack
);

wire [7:0] handTotal; // <-- these are mixing styles too
reg blackJack;
reg bust;
...

应该是:

module clock(
    input clk, reset,
    output reg vgaclk
    );
...

module checkBust (
    input clk,
    input [7:0] handTotal,
    output reg bust,
    output reg blackJack
);
...

某些信号(例如vgaclk)未初始化。您可以内联或初始化块初始化它们,但建议在始终块中重置它们。这样,您可以在不关闭设计电源的情况下恢复初始值。 FPGA 的异步复位触发器数量有限,因此只能使用同步复位。 ASIC 更喜欢使用异步复位触发器来初始化所有值并使用同步复位进行动态复位。示例:

always @(posedge clk) begin
    if (reset) begin
        hand <= 8'h0;
    end
    if (addCard == 1) begin
        hand <= hand + card;
    end
end

plhanddlhand 开始由 controllerplayer 驱动。根据代码,它应该只在播放器内分配。 controller 应该向player 发送复位信号以将值设置回0。

我能很快发现的最后一个问题是,下面的代码是推断级别敏感的锁存器,并分配在两个单独的 always 块中。闩锁不一定是坏的,但它们的毛刺变化更大,只有在特别需要时才应该使用。变量分配在两个不同的 always 块中的事实将是一个综合错误。我相信您可以放心地删除锁定代码。

always @(*) begin
    if (plbust == 1)
        pllose <= 1;
    else if (plbj == 1)
        plwin <= 1;
    else if (dlbust == 1)
        plwin <= 1;
end

【讨论】:

    【解决方案2】:

    您必须记住,verilog 中的信号代表物理电路。我们将给线路信号设置值的东西称为驱动程序。信号不允许有多个驱动器,因为这会导致短路(一个驱动器想要将 Vdd 放在电线上,而另一个将其接地)。

    在您的情况下,控制器和播放器都指定它们输出到plhand,这使得它们都成为驱动程序。所以当玩家想写一个1到一点plhand时,控制器还在写一个0,这会导致冲突。您应该收到错误或警告,表明信号有多个驱动程序,这会让您知道您遇到了这种行为。

    简而言之,您可以在任意数量的模块之间传递线路,但只有其中一个模块可以输出到它。因此,请考虑将 curPlHandoutput 更改为 input

    【讨论】:

    • 顺便说一句,如果您想要某种复位功能,最好在其自己的模块中复位每个信号,并将复位信号传递给它。
    【解决方案3】:

    注意:这不是问题。有关更多信息,请参阅其他答案/cmets。

    player 模块中,您没有为所有条件正确设置hand。具体来说:

    always @(posedge clk) begin
        if (addCard == 1)
            hand <= hand + card;
    end
    

    需要处理addCard != 1。所以试试:

    always @(posedge clk) begin
        if (addCard == 1)
            hand <= hand + card;
        else
            hand <= hand;
    end
    

    【讨论】:

    • 感谢您的回复。我已经做出了改变,但它仍然给我同样的问题。我不确定它是否是模块不处理案例的问题,但我觉得这可能是我在多个模块中使用 plhand 的问题。这会是问题吗,还是不一定有多少模块使用同一根电线?
    • 对于时钟信号,假设它们在未更改的情况下保持其值,因此您无需涵盖else 情况。
    • @wilcroft 我用 Verilog 已经有一段时间了(很遗憾),所以如果是这样的话,我的错。
    • @DavidScheibe - 如果您尝试从两个不同的模块(即,在模块 foo 和模块 bar 中设置 x[6] )。如果您在不同的模块中分配单独的位(即,在模块foo 中设置x[5] 和在模块bar 中设置x[6],专门),我认为这无关紧要。
    • @tonysdg 拥有它可能不会有什么坏处,但没有它不是问题。
    猜你喜欢
    • 2022-12-04
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多