// --------------------------------------------------------------------
// Major Functions: 1-D Cellular Automaton on VGA
// --------------------------------------------------------------------
//
// Revision History :
// --------------------------------------------------------------------
// Bruce R Land, Cornell University, Oct 2009
// Improved top module written by Adam Shapiro Oct 2009
// --------------------------------------------------------------------

module DE2_TOP (
    // Clock Input
    input         TD_CLK27,    // 27 MHz
    input         CLOCK_50,    // 50 MHz
    input         EXT_CLOCK,   // External Clock
    // Push Button
    input  [3:0]  KEY,         // Pushbutton[3:0]
    // DPDT Switch
    input  [17:0] SW,          // Toggle Switch[17:0]
    // 7-SEG Display
    output [6:0]  HEX0,        // Seven Segment Digit 0
    output [6:0]  HEX1,        // Seven Segment Digit 1
    output [6:0]  HEX2,        // Seven Segment Digit 2
    output [6:0]  HEX3,        // Seven Segment Digit 3
    output [6:0]  HEX4,        // Seven Segment Digit 4
    output [6:0]  HEX5,        // Seven Segment Digit 5
    output [6:0]  HEX6,        // Seven Segment Digit 6
    output [6:0]  HEX7,        // Seven Segment Digit 7
    // LED
    output [8:0]  LEDG,        // LED Green[8:0]
    output [17:0] LEDR,        // LED Red[17:0]
    // UART
    output        UART_TXD,    // UART Transmitter
    input         UART_RXD,    // UART Receiver
    // IRDA
    output        IRDA_TXD,    // IRDA Transmitter
    input         IRDA_RXD,    // IRDA Receiver
    // SDRAM Interface
    inout  [15:0] DRAM_DQ,     // SDRAM Data bus 16 Bits
    output [11:0] DRAM_ADDR,   // SDRAM Address bus 12 Bits
    output        DRAM_LDQM,   // SDRAM Low-byte Data Mask 
    output        DRAM_UDQM,   // SDRAM High-byte Data Mask
    output        DRAM_WE_N,   // SDRAM Write Enable
    output        DRAM_CAS_N,  // SDRAM Column Address Strobe
    output        DRAM_RAS_N,  // SDRAM Row Address Strobe
    output        DRAM_CS_N,   // SDRAM Chip Select
    output        DRAM_BA_0,   // SDRAM Bank Address 0
    output        DRAM_BA_1,   // SDRAM Bank Address 0
    output        DRAM_CLK,    // SDRAM Clock
    output        DRAM_CKE,    // SDRAM Clock Enable
    // Flash Interface
    inout  [7:0]  FL_DQ,       // FLASH Data bus 8 Bits
    output [21:0] FL_ADDR,     // FLASH Address bus 22 Bits
    output        FL_WE_N,     // FLASH Write Enable
    output        FL_RST_N,    // FLASH Reset
    output        FL_OE_N,     // FLASH Output Enable
    output        FL_CE_N,     // FLASH Chip Enable
    // SRAM Interface
    inout  [15:0] SRAM_DQ,     // SRAM Data bus 16 Bits
    output [17:0] SRAM_ADDR,   // SRAM Address bus 18 Bits
    output        SRAM_UB_N,   // SRAM High-byte Data Mask 
    output        SRAM_LB_N,   // SRAM Low-byte Data Mask 
    output        SRAM_WE_N,   // SRAM Write Enable
    output        SRAM_CE_N,   // SRAM Chip Enable
    output        SRAM_OE_N,   // SRAM Output Enable
    // ISP1362 Interface
    inout  [15:0] OTG_DATA,    // ISP1362 Data bus 16 Bits
    output [1:0]  OTG_ADDR,    // ISP1362 Address 2 Bits
    output        OTG_CS_N,    // ISP1362 Chip Select
    output        OTG_RD_N,    // ISP1362 Write
    output        OTG_WR_N,    // ISP1362 Read
    output        OTG_RST_N,   // ISP1362 Reset
    output        OTG_FSPEED,  // USB Full Speed, 0 = Enable, Z = Disable
    output        OTG_LSPEED,  // USB Low Speed,  0 = Enable, Z = Disable
    input         OTG_INT0,    // ISP1362 Interrupt 0
    input         OTG_INT1,    // ISP1362 Interrupt 1
    input         OTG_DREQ0,   // ISP1362 DMA Request 0
    input         OTG_DREQ1,   // ISP1362 DMA Request 1
    output        OTG_DACK0_N, // ISP1362 DMA Acknowledge 0
    output        OTG_DACK1_N, // ISP1362 DMA Acknowledge 1
    // LCD Module 16X2
    inout  [7:0]  LCD_DATA,    // LCD Data bus 8 bits
    output        LCD_ON,      // LCD Power ON/OFF
    output        LCD_BLON,    // LCD Back Light ON/OFF
    output        LCD_RW,      // LCD Read/Write Select, 0 = Write, 1 = Read
    output        LCD_EN,      // LCD Enable
    output        LCD_RS,      // LCD Command/Data Select, 0 = Command, 1 = Data
    // SD Card Interface
    inout         SD_DAT,      // SD Card Data
    inout         SD_DAT3,     // SD Card Data 3
    inout         SD_CMD,      // SD Card Command Signal
    output        SD_CLK,      // SD Card Clock
    // I2C
    inout         I2C_SDAT,    // I2C Data
    output        I2C_SCLK,    // I2C Clock
    // PS2
    input         PS2_DAT,     // PS2 Data
    input         PS2_CLK,     // PS2 Clock
    // USB JTAG link
    input         TDI,         // CPLD -> FPGA (data in)
    input         TCK,         // CPLD -> FPGA (clk)
    input         TCS,         // CPLD -> FPGA (CS)
    output        TDO,         // FPGA -> CPLD (data out)
    // VGA
    output        VGA_CLK,     // VGA Clock
    output        VGA_HS,      // VGA H_SYNC
    output        VGA_VS,      // VGA V_SYNC
    output        VGA_BLANK,   // VGA BLANK
    output        VGA_SYNC,    // VGA SYNC
    output [9:0]  VGA_R,       // VGA Red[9:0]
    output [9:0]  VGA_G,       // VGA Green[9:0]
    output [9:0]  VGA_B,       // VGA Blue[9:0]
    // Ethernet Interface
    inout  [15:0] ENET_DATA,   // DM9000A DATA bus 16Bits
    output        ENET_CMD,    // DM9000A Command/Data Select, 0 = Command, 1 = Data
    output        ENET_CS_N,   // DM9000A Chip Select
    output        ENET_WR_N,   // DM9000A Write
    output        ENET_RD_N,   // DM9000A Read
    output        ENET_RST_N,  // DM9000A Reset
    input         ENET_INT,    // DM9000A Interrupt
    output        ENET_CLK,    // DM9000A Clock 25 MHz
    // Audio CODEC
    inout         AUD_ADCLRCK, // Audio CODEC ADC LR Clock
    input         AUD_ADCDAT,  // Audio CODEC ADC Data
    inout         AUD_DACLRCK, // Audio CODEC DAC LR Clock
    output        AUD_DACDAT,  // Audio CODEC DAC Data
    inout         AUD_BCLK,    // Audio CODEC Bit-Stream Clock
    output        AUD_XCK,     // Audio CODEC Chip Clock
    // TV Decoder
    input  [7:0]  TD_DATA,     // TV Decoder Data bus 8 bits
    input         TD_HS,       // TV Decoder H_SYNC
    input         TD_VS,       // TV Decoder V_SYNC
    output        TD_RESET_N,    // TV Decoder Reset
    // GPIO
    inout  [35:0] GPIO_0,      // GPIO Connection 0
    inout  [35:0] GPIO_1       // GPIO Connection 1
);

  //Turn off unused displays.
  /*assign HEX0 = 7'h7F;
  assign HEX1 = 7'h7F;
  assign HEX2 = 7'h7F;
  assign HEX3 = 7'h7F;*/
  //assign HEX4 = 7'h7F;
  assign HEX5 = 7'h7F;
  assign HEX6 = 7'h7F;
  assign HEX7 = 7'h7F;
  assign LEDR = 18'h0;
  assign LEDG = 9'h0;

  //Set all GPIO to tri-state.
  assign GPIO_0 = 36'hzzzzzzzzz;
  assign GPIO_1 = 36'hzzzzzzzzz;

  //Disable audio codec.
  //assign AUD_DACDAT = 1'b0;
  //assign AUD_XCK    = 1'b0;

  //Disable DRAM.
  assign DRAM_ADDR  = 12'h0;
  assign DRAM_BA_0  = 1'b0;
  assign DRAM_BA_1  = 1'b0;
  assign DRAM_CAS_N = 1'b1;
  assign DRAM_CKE   = 1'b0;
  assign DRAM_CLK   = 1'b0;
  assign DRAM_CS_N  = 1'b1;
  assign DRAM_DQ    = 16'hzzzz;
  assign DRAM_LDQM  = 1'b0;
  assign DRAM_RAS_N = 1'b1;
  assign DRAM_UDQM  = 1'b0;
  assign DRAM_WE_N  = 1'b1;

  //Disable Ethernet.
  assign ENET_CLK   = 1'b0;
  assign ENET_CS_N  = 1'b1;
  assign ENET_CMD   = 1'b0;
  assign ENET_DATA  = 16'hzzzz;
  assign ENET_RD_N  = 1'b1;
  assign ENET_RST_N = 1'b1;
  assign ENET_WR_N  = 1'b1;

  //Disable flash.
  assign FL_ADDR  = 22'h0;
  assign FL_CE_N  = 1'b1;
  assign FL_DQ    = 8'hzz;
  assign FL_OE_N  = 1'b1;
  assign FL_RST_N = 1'b1;
  assign FL_WE_N  = 1'b1;

  //Disable LCD.
  assign LCD_BLON = 1'b0;
  assign LCD_DATA = 8'hzz;
  assign LCD_EN   = 1'b0;
  assign LCD_ON   = 1'b0;
  assign LCD_RS   = 1'b0;
  assign LCD_RW   = 1'b0;

  //Disable OTG.
  assign OTG_ADDR    = 2'h0;
  assign OTG_CS_N    = 1'b1;
  assign OTG_DACK0_N = 1'b1;
  assign OTG_DACK1_N = 1'b1;
  assign OTG_FSPEED  = 1'b1;
  assign OTG_DATA    = 16'hzzzz;
  assign OTG_LSPEED  = 1'b1;
  assign OTG_RD_N    = 1'b1;
  assign OTG_RST_N   = 1'b1;
  assign OTG_WR_N    = 1'b1;

  //Disable SDRAM.
  assign SD_DAT = 1'bz;
  assign SD_CLK = 1'b0;

  //Disable SRAM.
  assign SRAM_ADDR = 18'h0;
  assign SRAM_CE_N = 1'b1;
  assign SRAM_DQ   = 16'hzzzz;
  assign SRAM_LB_N = 1'b1;
  assign SRAM_OE_N = 1'b1;
  assign SRAM_UB_N = 1'b1;
  assign SRAM_WE_N = 1'b1;

  //Disable all other peripherals.
  //assign I2C_SCLK = 1'b0;
  assign IRDA_TXD = 1'b0;
  //assign TD_RESET_N = 1'b0;
  assign TDO = 1'b0;
  assign UART_TXD = 1'b0;

wire  VGA_CTRL_CLK;
wire  AUD_CTRL_CLK;
wire  DLY_RST;

assign  TD_RESET_N  = 1'b1; //  Allow 27 MHz
assign  AUD_ADCLRCK = AUD_DACLRCK;
assign  AUD_XCK   = AUD_CTRL_CLK;

Reset_Delay r0 (.iCLK(CLOCK_50), .oRESET(DLY_RST));

VGA_Audio_PLL p1 ( 
  .areset(~DLY_RST),
  .inclk0(TD_CLK27),
  .c0(VGA_CTRL_CLK),
  .c1(AUD_CTRL_CLK),
  .c2(VGA_CLK)  
);

wire [9:0]  mVGA_R;           //memory output to VGA
wire [9:0]  mVGA_G;
wire [9:0]  mVGA_B;
wire [18:0] mVGA_ADDR;        //video memory address
wire [8:0]  Coord_X, Coord_Y;
wire [17:0] mem_word_env;         //current data from m4k to VGA
reg  [17:0] disp_word;         // registered data from m4k to VGA

VGA_Controller u1 ( 
  //  Host Side
  .iCursor_RGB_EN(4'b0111),
  .oAddress(mVGA_ADDR),
  .oCoord_X({Coord_X,t1}),
  .oCoord_Y({Coord_Y,t2}),
  .iRed(mVGA_R),
  .iGreen(mVGA_G),
  .iBlue(mVGA_B),
  //  VGA Side
  .oVGA_R(VGA_R),
  .oVGA_G(VGA_G),
  .oVGA_B(VGA_B),
  .oVGA_H_SYNC(VGA_HS),
  .oVGA_V_SYNC(VGA_VS),
  .oVGA_SYNC(VGA_SYNC),
  .oVGA_BLANK(VGA_BLANK),
  //  Control Signal
  .iCLK(VGA_CTRL_CLK),
  .iRST_N(DLY_RST)  
);

wire calc_clock, reset, halt, move;
assign calc_clock = CLOCK_50;
assign reset = SW[17];
assign halt = SW[16];
assign move = SW[15];

reg         envr_wren;
wire [8:0]  envr_x, envr_y;
reg  [8:0]  Cursor_X, Cursor_Y, box_coord_x, box_coord_y;
wire [16:0] envr_addr;
wire [17:0] envr_read, envr_data;
assign envr_addr = (reset || halt || valid) ? 
    {box_coord_x, box_coord_y[7:0]} : {envr_x, envr_y[7:0]};

reg [3:0] water, vegetation, temperature, terrain;
reg [1:0] env_state;
assign envr_data[3:0] = water;
assign envr_data[7:4] = vegetation;
assign envr_data[11:8] = temperature;
assign envr_data[15:12] = terrain;
assign envr_data[17:16] = env_state;
hexDisp Wat  (.in(water),       .out(HEX3));
hexDisp Veg  (.in(vegetation),  .out(HEX2));
hexDisp Temp (.in(temperature), .out(HEX1));
hexDisp Terr (.in(terrain),     .out(HEX0));
hexDisp tsec (.in(state), .out(HEX4));

wire isCursor;
wire [8:0] box_size;
assign box_size = 9'd1 << ({7'd0, SW[8:7]} << 1);
assign isCursor = halt && 
                  (((Cursor_X - Coord_X == box_size) && ((Cursor_Y - Coord_Y < box_size + 9'd1) || (Coord_Y - Cursor_Y < box_size + 9'd1)))
                || ((Coord_X - Cursor_X == box_size) && ((Cursor_Y - Coord_Y < box_size + 9'd1) || (Coord_Y - Cursor_Y < box_size + 9'd1)))
                || ((Cursor_Y - Coord_Y == box_size) && ((Cursor_X - Coord_X < box_size + 9'd1) || (Coord_X - Cursor_X < box_size + 9'd1)))
                || ((Coord_Y - Cursor_Y == box_size) && ((Cursor_X - Coord_X < box_size + 9'd1) || (Coord_X - Cursor_X < box_size + 9'd1))))
                ? 1'd1 : 1'd0;

assign mVGA_R = (isCursor) ? 10'h3ff : 
                  ((disp_word[17]) ? 10'd0 : 
                  {2'd0, disp_word[11:8], disp_word[15:12]});
assign mVGA_G = (isCursor) ? 10'd0 :
                  ((disp_word[17]) ? ((disp_word[16]) ? 10'd0 : 10'h3ff) : 
                  {2'd0, disp_word[11:8], disp_word[7:4]});
assign mVGA_B = (isCursor) ? 10'd0 : 
                  ((disp_word[17]) ? ((disp_word[16]) ? 10'h3ff : 10'd0) : 
                  {2'd0, disp_word[11:8], disp_word[3:0]});

environment_memory environment (
  .address_a (envr_addr) , 
  .address_b ({Coord_X[8:0],Coord_Y[7:0]}), // vga current address
  .clock_a (calc_clock),
  .clock_b (VGA_CTRL_CLK),
  .data_a (envr_data),
  .data_b (0),   // never write on port b
  .wren_a (envr_wren),
  .wren_b (0),   // never write on port b
  .q_a (envr_read),
  .q_b (mem_word_env) 
);

reg         curr_wren;
reg  [8:0]  curr_addr;
wire [64:0] curr_read;
wire [64:0] curr_data;
wire [8:0]  comp_addr;
wire [64:0] comp_read;

critter_memory critter_memory (
  .address_a (curr_addr), 
  .address_b (comp_addr),
  .clock_a (calc_clock),
  .clock_b (calc_clock),
  .data_a (curr_data),
  .data_b (0),   // never write on comparator
  .wren_a (curr_wren),
  .wren_b (0),   // never write on comparator
  .q_a (curr_read),
  .q_b (comp_read) 
);

reg control_enable;
wire valid;
wire child;

critter_control critter_controller (
  .clock(calc_clock),
  .reset(reset),
  .enable(control_enable),
  .val(valid),
  .comp_addr(comp_addr),
  .comp_gene(comp_read),
  .env_X(envr_x),
  .env_Y(envr_y),
  .env_param(envr_read),
  .gene_in(curr_read),
  .gene_out(curr_data),
  .child(child)
);

reg run_clk;
reg [31:0] counter;
reg [3:0]  counter_sec;
always @ (posedge CLOCK_50)
begin
  if(reset) begin
    counter <= 32'd0;
    counter_sec <= 4'd0;
  end
  else begin
    counter <= counter + 32'd1;
    if (counter == 32'd25000000) begin
      counter_sec <= counter_sec + 4'd1;
      counter <= 32'd0;
      run_clk <= !run_clk;
    end
  end
end

//state names
reg [3:0] state;
reg [8:0] temp;
parameter init  = 4'd0, rest  =4'd1,     pause   = 4'd12,
          calc  = 4'd2, write = 4'd13,   write_n = 4'd14, 
          done  = 4'd3, offspring = 4'd4,  
          key_0 = 4'd5, key_1 =4'd6,  
          key_2 = 4'd7, key_3 =4'd8,  
          cursor= 4'd9, env_param=4'd10,
          key_pause=4'd11;

always @ (posedge calc_clock) begin
  disp_word <= mem_word_env;  //register the m4k output for better timing on VGA
  //clear the screen
  if (reset) begin
    envr_wren <= 1'b1;
    box_coord_x <= Coord_X;
    box_coord_y <= Coord_Y;
    Cursor_X <= 9'd160;
    Cursor_Y <= 9'd120;
    water <= 4'd0;
    vegetation <= 4'd0;
    temperature <= 4'd0;
    terrain <= 4'd0;
    env_state <= 2'd0;
    curr_wren <= 1'd0;
    curr_addr <= 9'd0;
    control_enable <= 1'd0;
    state <= init;
  end
  //begin state machine 
  else begin
    case(state)
      init: //create random points on screen
      begin
        envr_wren <= 1'b0;
        if (halt) begin
          water <= 4'd0;
          vegetation <= 4'd0;
          temperature <= 4'd0;
          terrain <= 4'd0;
          state <= pause;
        end
        else if (run_clk) begin
          control_enable <= 1'b1;
          state <= calc;
        end
      end

      rest:
      begin
        if (!run_clk)
          state <= init;
      end

      calc:
      begin
        curr_wren <= 1'b0;
        if (valid) begin
          state <= write;
          control_enable <= 1'b0;
        end
      end

      write:
      begin
        curr_wren <= 1'b1;
        water <= envr_read[3:0];
        vegetation <= envr_read[7:4];
        temperature <= envr_read[11:8];
        terrain <= envr_read[15:12];
        if (curr_read[0]) begin
          box_coord_x <= curr_read[11:3];
          box_coord_y <= curr_read[20:12];
          env_state <= 2'd0;
          envr_wren <= 1'b1;
        end
        if (curr_data[0])
          state <= write_n;
        else
          state <= done;
      end

      write_n:
      begin
        curr_wren <= 1'b0;
        box_coord_x <= curr_data[11:3];
        box_coord_y <= curr_data[20:12];
        env_state <= curr_data[1:0];
        envr_wren <= 1'b1;
        state <= done;
      end

      done:
      begin
        envr_wren <= 1'b0;
        curr_wren <= 1'b0;
        if (child) begin
          temp <= curr_addr;
          curr_addr <= 9'd0;
          state <= offspring;
        end
        else if (curr_addr == 9'd511) begin
          curr_addr <= 9'd0;
          state <= rest;
        end
        else begin
          curr_addr <= curr_addr + 9'd1;
          control_enable <= 1'b1;
          state <= calc;
        end
      end

      offspring:
      begin
        if (curr_read[0]) begin
          if (curr_addr == 9'd511) begin
            if (temp == 9'd511) begin
              curr_addr <= 9'd0;
              state <= rest;
            end
            else begin
              control_enable <= 1'b1;
              curr_addr <= temp;
              state <= calc;
            end
          end
          else begin
            curr_addr <= curr_addr + 9'd1;
          end
        end
        else begin
          curr_wren <= 1'b1;
          control_enable <= 1'b1;
          curr_addr <= temp;
          state <= calc;
        end
      end
          
      pause:  // determine what to do
      begin 
        envr_wren <= 1'b0;
        if(move && halt) begin
          if(~KEY[0]) begin
            state <= key_0;
          end
          else if (~KEY[1]) begin
            state <= key_1;
          end
          else if (~KEY[2]) begin
            state <= key_2;
          end
          else if (~KEY[3]) begin
            state <= key_3;
          end
        end
        else if (halt) begin
          if(~KEY[3] || ~KEY[2]) begin
            state <= env_param;
          end
          else if(~KEY[0]) begin
            box_coord_x <= (Cursor_X - 9'd1) - box_size;
            box_coord_y <= Cursor_Y - box_size;
            
            state <= cursor;
          end
        end
        else begin
          state <= init;
        end
      end

      key_0:  //move up
      begin
        case(SW[6:5])
        3'd0:
          if (Cursor_Y > 9'd1 + box_size) //5
            Cursor_Y <= Cursor_Y - 9'd1;
        3'd1:
          if (Cursor_Y > 9'd4 + box_size) //8
            Cursor_Y <= Cursor_Y - 9'd4;
        3'd2:
          if (Cursor_Y > 9'd16 + box_size) //20
            Cursor_Y <= Cursor_Y - 9'd16;
        3'd3:
          if (Cursor_Y > 9'd64 + box_size) //68
            Cursor_Y <= Cursor_Y - 9'd64;
        default:
          if (Cursor_Y > 9'd1 + box_size) //5
            Cursor_Y <= Cursor_Y - 9'd1;
        endcase
        state <= key_pause;
      end

      key_1: //move down
      begin
        case(SW[6:5])
        3'd0:
          if (Cursor_Y < 9'd238 - box_size) //237
            Cursor_Y <= Cursor_Y + 9'd1;
        3'd1:
          if (Cursor_Y < 9'd235 - box_size) //234
            Cursor_Y <= Cursor_Y + 9'd4;
        3'd2:
          if (Cursor_Y < 9'd223 - box_size) //222
            Cursor_Y <= Cursor_Y + 9'd16;
        3'd3:
          if (Cursor_Y < 9'd175 - box_size) //174
            Cursor_Y <= Cursor_Y + 9'd64;
        default:
          if (Cursor_Y < 9'd238 - box_size) //237
            Cursor_Y <= Cursor_Y + 9'd1;
        endcase
        state <= key_pause;
      end

      key_2:  //move right
      begin
        case(SW[6:5])
        3'd0:
          if (Cursor_X < 9'd318 - box_size) //317
            Cursor_X <= Cursor_X + 9'd1;
        3'd1:
          if (Cursor_X < 9'd315 - box_size) //314
            Cursor_X <= Cursor_X + 9'd4;
        3'd2:
          if (Cursor_X < 9'd301 - box_size) //302
            Cursor_X <= Cursor_X + 9'd16;
        3'd3:
          if (Cursor_X < 9'd254 - box_size) //254
            Cursor_X <= Cursor_X + 9'd64;
        default:
          if (Cursor_X < 9'd320 - box_size) //317
            Cursor_X <= Cursor_X + 9'd1;
        endcase
        state <= key_pause;
      end

      key_3:  //move left
      begin
        case(SW[6:5])
        3'd0:
          if (Cursor_X > 9'd3 + box_size)
            Cursor_X <= Cursor_X - 9'd1;
        3'd1:
          if (Cursor_X > 9'd6 + box_size)
            Cursor_X <= Cursor_X - 9'd4;
        3'd2:
          if (Cursor_X > 9'd18 + box_size)
            Cursor_X <= Cursor_X - 9'd16;
        3'd3:
          if (Cursor_X > 9'd66 + box_size)
            Cursor_X <= Cursor_X - 9'd64;
        default:
          if (Cursor_X > 9'd3 + box_size)
            Cursor_X <= Cursor_X - 9'd1;
        endcase
        state <= key_pause;
      end

      env_param:  // modify environment parameter
      begin
        if (~KEY[3]) begin
          terrain <= terrain + ((terrain < 4'hf) ? (4'd1 & {3'd0, SW[3]}) : 4'd0);
          vegetation <= vegetation + ((vegetation < 4'hf) ? (4'd1 & {3'd0, SW[2]}) : 4'd0);
          water <= water + ((water < 4'hf) ? (4'd1 & {3'd0, SW[1]}) : 4'd0);
          temperature <= temperature + ((temperature < 4'hf) ? (4'd1 & {3'd0, SW[0]}) : 4'd0);
        end
        else if (~KEY[2]) begin
          terrain <= terrain - ((terrain > 4'h0) ? (4'd1 & {3'd0, SW[3]}) : 4'd0);
          vegetation <= vegetation - ((vegetation > 4'h0) ? (4'd1 & {3'd0, SW[2]}) : 4'd0);
          water <= water - ((water > 4'h0) ? (4'd1 & {3'd0, SW[1]}) : 4'd0);
          temperature <= temperature - ((temperature > 4'h0) ? (4'd1 & {3'd0, SW[0]}) : 4'd0);
        end
        state <= key_pause;
      end

      cursor:  //write cursor location to memory
      begin
        envr_wren <= 1'b1;
        if (box_coord_x == (Cursor_X - 9'd1) + box_size) begin
          //bottom line, renew prev and pause
          if (box_coord_y == Cursor_Y + box_size[7:0])
            state <= key_pause;
          //not bottom line, renew prev and go to next line
          else begin
            box_coord_x <= (Cursor_X - 9'd1) - box_size;
            box_coord_y <= box_coord_y + 8'd1;
          end
        end
        //not right most pixel, go to next pixel
        else
          box_coord_x <= box_coord_x + 9'd1;
      end

      key_pause:
      begin
        if(~KEY[0] || ~KEY[1] || ~KEY[2] || ~KEY[3])
          state <= key_pause;
        else
          state <= pause;
      end
    
      default:
        state <= pause;

    endcase
  end
end
endmodule

module hexDisp (in, out);
  input[3:0] in;
  output[6:0] out;
  reg[6:0] out;
  always @ (*) begin
    case (in)
    4'd0:  begin out <= 7'b1000000; end
    4'd1:  begin out <= 7'b1111001; end
    4'd2:  begin out <= 7'b0100100; end
    4'd3:  begin out <= 7'b0110000; end
    4'd4:  begin out <= 7'b0011001; end
    4'd5:  begin out <= 7'b0010010; end
    4'd6:  begin out <= 7'b0000010; end
    4'd7:  begin out <= 7'b1111000; end
    4'd8:  begin out <= 7'b0000000; end
    4'd9:  begin out <= 7'b0011000; end
    4'd10: begin out <= 7'b0001000; end
    4'd11: begin out <= 7'b0000011; end
    4'd12: begin out <= 7'b1000110; end
    4'd13: begin out <= 7'b0100001; end
    4'd14: begin out <= 7'b0000100; end
    4'd15: begin out <= 7'b0001110; end
    endcase
  end
endmodule