Verilog导线设置为X而不是1

时间:2015-11-30 19:52:13

标签: verilog

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

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

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

statemonitor模块:

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按钮的debouncer:

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张牌来测试游戏的初始设置:

enter image description here

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

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

3 个答案:

答案 0 :(得分:1)

注意:这不是问题。有关详细信息,请参阅其他答案/评论。

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

答案 1 :(得分:1)

你必须记住,verilog中的信号代表物理电路。我们将某些值设置为有线信号作为驱动程序。信号不允许有多个驱动器,因为这可能导致短路(一个驱动器希望将Vdd放在导线上,而另一个驱动器将其连接到地)。

在您的情况下,控制器和播放器都指定它们输出到plhand,这使它们都成为驱动程序。因此,当玩家想要将1写入plhand时,控制器仍在编写0,这会导致冲突。您应该收到错误或警告信号有多个驱动程序,这会让您知道您正在获得此行为。

简而言之,您可以根据需要在多个模块之间传递线路,但只有其中一个模块可以输出。因此,请考虑将curPlHandoutput更改为input

答案 2 :(得分:1)

一对夫妇如果问题:

拳击头。您正在混合ANSI和非ANSI标头样式。这是非法的语法。一些模拟器/合成器允许它,但这是不好的做法。我已经在这里更深入地回答了与标题相关的问题&#34; object <name> is not declared in verlog&#34;和&#34; Issue with parameters in Modelsim&#34;所以我只是总结一下;遵循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)未初始化。您可以将它们初始化为内联块或初始块,但建议在always块中重置它们。这样,您可以在不关闭设计的情况下恢复初始值。 FPGA具有有限数量的异步复位触发器,因此仅使用同步复位。 ASIC更喜欢使用异步复位触发器初始化所有值,并使用同步复位进行动态复位。例如:

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

plhanddlhandcontroller开始player开始。根据代码,它应该只在播放器中分配。 controller应向player发送重置信号,以将值设置回0。

我能够快速发现的最后一个问题是,以下代码推断出对级别敏感的锁存器并在两个单独的始终块中分配。锁存器不一定是坏的,但它们具有更高的毛刺变化,并且只应在特别要求时使用。变量在两个不同的始终块中分配的事实将是合成错误。我相信你可以安全地删除锁存代码。

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