mercredi 25 novembre 2020

How to use Counters to generate a random number ranging 2 to 12 using VHDL

I was going through Digital Systems Design Using VHDL (Second Edition) by Charles H. Roth, Jr. and Lizy Kurian John where I came across Section 5.2.2 A Dice Game. In order to understand it better I tried implementing the codes given.

I was able to successfully implement the first part of the problem wherein the Dice Sum have been hardcoded like this:

type arr is array(0 to 11) of integer;
constant Sumarray:arr := (4, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12);

Here is the complete implementation:

design.vhd

--Behavioral Model for Dice Game
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

entity DiceGame is
port(Rb, Reset, CLK: in bit;
     Sum: in integer range 2 to 12;
     Roll, Win, Lose: out bit);
end DiceGame;

architecture DiceBehave of DiceGame is

signal State, Nextstate: integer range 0 to 5;
signal Point: integer range 2 to 12;
signal Sp: bit;

begin
process(Rb, Reset, Sum, State)
begin
    Sp <= '0'; Roll <= '0'; Win <= '0'; Lose <= '0';
    case State is
    when 0 => if Rb = '1' then Nextstate <= 1; end if;
    when 1 =>
        if Rb = '1' then Roll <= '1';
        elsif Sum = 7 or Sum = 11 then Nextstate <= 2;
        elsif Sum = 2 or Sum = 3 or Sum = 12 then Nextstate <= 3;
        else Sp <= '1'; Nextstate <= 4;
        end if;
    when 2 => Win <= '1';
        if Reset = '1' then Nextstate <= 0; end if;
    when 3 => Lose <= '1';
        if Reset = '1' then Nextstate <= 0; end if;
    when 4 => if Rb = '1' then Nextstate <= 5; end if;
    when 5 =>
        if Rb = '1' then Roll <= '1';
        elsif Sum = Point then Nextstate <= 2;
        elsif Sum = 7 then Nextstate <= 3;
        else Nextstate <= 4;
        end if;
    end case;
end process;

process(CLK)
begin
    if CLK'event and CLK = '1' then
        State <= Nextstate;
    if Sp = '1' then Point <= Sum; end if;
    end if;
end process;

end DiceBehave;

--Test Module

entity GameTest is
port(Rb, Reset: out bit;
     Sum: out integer range 2 to 12;
     CLK: inout bit;
     Roll, Win, Lose: in bit);
end GameTest;

architecture dicetest of GameTest is

signal Tstate, Tnext: integer range 0 to 3;
signal Trig1: bit;
type arr is array(0 to 11) of integer;
constant Sumarray:arr := (4, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12);

begin

CLK <= not CLK after 20 ns;

    process(Roll, Win, Lose, Tstate)
    variable i: natural; -- i is initialized to 0
    begin
        case Tstate is
            when 0 => Rb <= '1'; -- wait for Roll
                Reset <= '0';
                if i >= 12 then Tnext <= 3;
                elsif Roll = '1' then
                Sum <= Sumarray(i);
                i := i + 1;
                Tnext <= 1;
                end if;
            when 1 => Rb <= '0'; Tnext <= 2;
            when 2 => Tnext <= 0;
                Trig1 <= not Trig1; -- toggle Trig1
                if (Win or Lose) = '1' then
                    Reset <= '1';
                end if;
            when 3 => null; -- Stop state
        end case;
    end process;

    process(CLK)
    begin
        if CLK = '1' and CLK'event then
            Tstate <= Tnext;
        end if;
    end process;

end dicetest;

testbench.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

entity tester is
end tester;

architecture test of tester is

component GameTest
port(Rb, Reset: out bit;
     Sum: out integer range 2 to 12;
     CLK: inout bit;
     Roll, Win, Lose: in bit);
end component;

component DiceGame
port(Rb, Reset, CLK: in bit;
     Sum: in integer range 2 to 12;
     Roll, Win, Lose: out bit);
end component;

signal rb1, reset1, clk1, roll1, win1, lose1: bit;
signal sum1: integer range 2 to 12;

begin

Dice: Dicegame port map (rb1, reset1, clk1, sum1, roll1, win1, lose1);
Dicetest: GameTest port map (rb1, reset1, sum1, clk1, roll1, win1, lose1);

end test;

The second part of the problem requires generating the Dice Sum using Counters. Here is the code snippet provided in the book.

Code - 1

entity Counter is
port(Clk, Roll: in bit;
     Sum: out integer range 2 to 12);
end Counter;

architecture Count of Counter is

signal Cnt1, Cnt2: integer range 1 to 6:= 1;

begin
process(Clk)
begin
    if Clk = '1' then
        if Roll = '1' then
            if Cnt1 = 6 then Cnt1 <= 1; else Cnt1 <= Cnt1 + 1; end if;
            if Cnt1 = 6 then
                if Cnt2 = 6 then Cnt2 <= 1; else Cnt2 <= Cnt2 + 1; end if;
            end if;
        end if;
     end if;
end process;

Sum <= Cnt1 + Cnt2;

end Count;

Code - 2

entity Game is
port(Rb, Reset, Clk: in bit;
     Win, Lose: out bit);
end Game;

architecture Play1 of Game is
component Counter
port(Clk, Roll: in bit;
    Sum: out integer range 2 to 12);
end component;

component DiceGame
port(Rb, Reset, CLK: in bit;
     Sum: in integer range 2 to 12;
     Roll, Win, Lose: out bit);
end component;

signal roll1: bit;
signal sum1: integer range 2 to 12;

begin
Dice: Dicegame port map (Rb, Reset, Clk, sum1, roll1, Win, Lose);
Count: Counter port map (Clk, roll1, sum1);
end Play1;

I understand that Code-1 describes the working of Counter. But I am unable to figure out how to incorporate Code-2 in design.vhd and what necessary changes need to be made in test module of design.vhd

If anyone can guide me it would be really helpful. Thanks in advance.




Aucun commentaire:

Enregistrer un commentaire