Jump to content
  • 0

How do If statements work with counting?


theConfusedOne

Question

I'm still relatively new to Verilog and FPGA programming, so I've been struggling quite a bit with this one. The goal of the project here is to play a super basic game of 'blackjack' and I can't quite seem to get the system to work. As a note: The game goal is to get to 21, but a number reasonably high and close to 21 could still win the game based on what the Dealer has.

The first few if - else if statements are there to interpret the card input from switches on the basys3, and then decide how much to add to the count based on the 'card' input. The latter if - else statement is there to output either an 'H' or an 'S' to the 7-segment display in order to output whether the player should 'hit' and recieve another card, or if that person should 'stay' and just hold onto the cards they have. For some reason, the board only displays the 'H' value on the 7 segment display, and I have no way to find out if the count is actually incrementing in the program since I can't figure out how to test this outside of the board. Any assistance would be greatly appreciated. As a note: I have checked the constraints file, and everything looks correct. 

blackjack.v verilog file: 

module BlackJack(input clk, ace, four, five, six, eight, jack, reset, output clk_slow, reg A, B, C, D, E, F, G, H, wire segEn, segEnd);
 //slow clock code 
        parameter clkbit = 27;
        reg [clkbit:0] clk2 = 0;
        always@(posedge clk)
        begin
            clk2 <= clk2+1;
        end
        assign clk_slow = clk2[clkbit];


reg count = 0;
assign segEn = 0; // enable for the 7-segment display
assign segEnd = 1;

    always @(posedge clk_slow)
    begin
    if (count <= 10)  //states from start to 10 - card decisions made here
        begin
        if (ace)
            count <= count + 11; //adds 11
        else if (four)
            count <= count + 4;
        else if (five)
            count <= count + 5;
        else if (six)
            count <= count + 6;
        else if (eight)
            count <= count + 8;
        else if (jack)
            count <= count + 10;
        else
            count <= count;
        end
    else if (count <= 11) // states from 11 to 17
        begin
        if (ace) 
            count <= count + 1; //adds 1
        else if (four)
            count <= count + 4;
        else if (five)
            count <= count + 5;
        else if (six)
            count <= count + 6;
        else if (eight)
            count <= count + 8;
        else if (jack)
            count <= count + 10; 
        else
            count <= count;
        end
    else if (reset)
        begin
            count <= 0;
        end
    else
        begin
            count <= count; 
        end 
    
   if (count < 17)
    begin
       F <= 1'b0;
       B <= 1'b0;
       G <= 1'b0;
       E <= 1'b0;
       C <= 1'b0;
       A <= 1'b1;
       D <= 1'b1;
    end    
   else
    begin
        A <= 1'b0;
        F <= 1'b0;
        G <= 1'b0;
        C <= 1'b0;
        D <= 1'b0;
        B <= 1'b1;
        E <= 1'b1;
    end  
  end
  

 

Link to comment
Share on other sites

5 answers to this question

Recommended Posts

Hi,

you'll have a hard time learning RTL on hardware only. There are situations where you can't avoid it but then a problem that should take five minutes keeps you busy for half a day. Something to avoid...

Fortunately, your problem is easily handled in a simulator.

Use conditional blocks `ifdef MYSIM... `endif for example on the clock divider (don't want that in simulation, or at least with a smaller division ratio), and `define "MYSIM" in your simulation testbench.
You'll need some clock e.g.
reg clk = 0;
always begin #250 clk <= 1; #250 clk <= 0; end

and want it to stop eventually e.g.
initial #10000 $finish();

Put the testbench as far as possible into a separate e.g. sim.v file and `include the design that you want to use also on hardware.
A quick-and-dirty way is to define your "testvectors" in the testbench (see clock generation but controlling some registers that mimic your switches).

Setting up the testbench will require an hour of work the first time but that effort will pay back for itself within the next hour.

I'd recommend you get "iverilog" as simulator. It writes a .vcd file that you can open in "gtkwave". Use a .bat file (assuming Windows) to run the simulation, press shift-ctrl-R in gtkwave to reload.

This as a 10 line summary - you can read a lot more about simulation on the web but the above can get you quite far.

Link to comment
Share on other sites

8 hours ago, xc6lx45 said:

Hi,

you'll have a hard time learning RTL on hardware only. There are situations where you can't avoid it but then a problem that should take five minutes keeps you busy for half a day. Something to avoid...

Fortunately, your problem is easily handled in a simulator.

Use conditional blocks `ifdef MYSIM... `endif for example on the clock divider (don't want that in simulation, or at least with a smaller division ratio), and `define "MYSIM" in your simulation testbench.
You'll need some clock e.g.
reg clk = 0;
always begin #250 clk <= 1; #250 clk <= 0; end

and want it to stop eventually e.g.
initial #10000 $finish();

Put the testbench as far as possible into a separate e.g. sim.v file and `include the design that you want to use also on hardware.
A quick-and-dirty way is to define your "testvectors" in the testbench (see clock generation but controlling some registers that mimic your switches).

Setting up the testbench will require an hour of work the first time but that effort will pay back for itself within the next hour.

I'd recommend you get "iverilog" as simulator. It writes a .vcd file that you can open in "gtkwave". Use a .bat file (assuming Windows) to run the simulation, press shift-ctrl-R in gtkwave to reload.

This as a 10 line summary - you can read a lot more about simulation on the web but the above can get you quite far.

Thanks for the advice here! I will definitely do this for my next project, but unfortunately I don't have time to set up a simulation for this one. Could you tell what was wrong with the code just from the .v file? 

Link to comment
Share on other sites

Ok for those who may end up having the same issue as I have today, I came up with a solution which appears to work. I was initially setting the value for the count outside of a clock controlled cycle. implementing the following code before the first always statement sets an initial condition I suppose for the circuit 

initial @(posedge clk_slow)
    begin
    count = 0;
    end

And now the display is correctly outputting information. 

Link to comment
Share on other sites

@theConfusedOne,

Okay, that's ... a problem.  If that was your fix, then your tools are broken.  The correct method should be to declare, as you had done, "reg [15:0] count = 0;" or even to give it an initial value, as in "initial count = 0;".

Now, have you noticed that in the code shared above "count" is only one bit wide?  That would be a big issue.

I'm also concerned that you are using switches and/or buttons to set things.  These things can be notoriously difficult to get right in hardware, and I'd be very careful not to even touch hardware with these issues until I had not only simulated but also formally verified a design.  That way, I would know I can limit any actual hardware bugs down to a small set--primarily clock domain crossing and bouncing issues--both of which you will have when using either switches or buttons.  Consider as an example slide 7 from the Buttons lesson (#7) in this tutorial, showing that a one up counter can be made to walk backwards via an improperly handled button press.

As for @xc6lx45's recommendation to learn how to use iverilog, let me add that iverilog is as close to an industry standard simulator as you'll find for free.  It's a great tool.  In my experience with simulation, however, I've always been left to find bugs in hardware later--hence why I use and enjoy formal methods.  That said, @xc6lx45's point that, "you'll have a hard time learning RTL on hardware only. There are situations where you can't avoid it but then a problem that should take five minutes keeps you busy for half a day. Something to avoid..." is spot on, and cannot be foot-stomped enough.

Both iverilog and formal methods could be used to find the bug in the above code where you did not allocate enough bits to your counter.

Dan

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...