Волк-Коза-Капуста

Исходный текст на Verilog "Волк-Коза-Капуста" (второй вариант)

 

// WOLF-GOAT-CABBAGE
module game_wgc(
   
input wire reset,
    input wire clk
,
    input wire
[3:0]key,
    output reg
[3:0]state_out,
    output reg fail
,
    output reg win
)
;

parameter GOAT =0;
parameter CABBAGE =1;
parameter WOLF =2;
parameter MEN =3;

//fix new key states
reg[3:0]key_fixed;
always @(posedge clk or posedge reset)
begin

   
if(reset)
        key_fixed
<=4'b0000;

   
else
        key_fixed
<= key;
end

//detect key press event with simple filter with shift register
reg[3:0]key_was_pressed_sr;
always @(posedge clk or posedge reset)
begin

   
if(reset)
        key_was_pressed_sr
<=4'b0000;

   
else
        key_was_pressed_sr
<={ key_was_pressed_sr[2:0], (key_fixed !=4'b0000) };
end

wire key_was_pressed;
assign key_was_pressed =(key_was_pressed_sr==4'b0001);

//each bit for goat/cabbage/wolf/men
//0 mean initial river side
//1 mean target river side
reg[3:0]state;
always @(posedge clk or posedge reset)
begin

   
if(reset)
        state
<=4'b0000;

   
else
   
begin
       
if(key_was_pressed)
       
begin

           
if(win | fail)
                state
<=4'b0000;//restart game after win or fail

           
else
           
if(key_fixed[GOAT]& (state[GOAT]==state[MEN]) )
                state
<={~state[MEN],  state[WOLF],  state[CABBAGE],~state[GOAT]};//move GOAT if it is near men

           
else
           
if(key_fixed[CABBAGE]& (state[CABBAGE]==state[MEN]))
                state
<={~state[MEN],  state[WOLF],~state[CABBAGE],  state[GOAT]};//move CABBAGE if it is near men

           
else
           
if(key_fixed[WOLF]& (state[WOLF]==state[MEN]))
           
begin

                state
<={~state[MEN],~state[WOLF],  state[CABBAGE],  state[GOAT]};//move WOLF if it is near men
           
end
           
else
           
if(key_fixed[MEN])
                state
<={~state[MEN],  state[WOLF],  state[CABBAGE],  state[GOAT]};//men always can move

       
end
   
end
end

always @(state)
begin

    state_out
= state;
    win 
= (state==4'b1111);
    fail
= (state==4'b0111) || (state==4'b1000) || (state==4'b0011) || (state==4'b1100) || (state==4'b0101) || (state==4'b1010);
end

endmodule