//
// Top level module for the FPGA on the MAX80 board by
// Per Mårtensson and H. Peter Anvin
//
// MAX80 v2
//

module `TOP
   (
    // Clock oscillator
    input	  clock_16, // 16 MHz
    input	  board_id, // This better match the firmware

    // ABC-bus
    inout	  abc_clk, // ABC-bus 3 MHz clock
    inout [15:0]  abc_a, // ABC address bus
    inout [7:0]   abc_d, // ABC data bus
    output	  abc_d_oe, // Data bus inout enable
    inout	  abc_rst_n, // ABC bus reset strobe
    inout	  abc_cs_n, // ABC card select strobe
    inout [4:0]   abc_out_n, // OUT, C1-C4 strobe
    inout [1:0]   abc_inp_n, // INP, STATUS strobe
    inout	  abc_xmemfl_n, // Memory read strobe
    inout	  abc_xmemw800_n, // Memory write strobe (ABC800)
    inout	  abc_xmemw80_n, // Memory write strobe (ABC80)
    inout	  abc_xinpstb_n, // I/O read strobe (ABC800)
    inout	  abc_xoutpstb_n, // I/O write strobe (ABC80)
    // The following are inverted versus the bus IF
    // the corresponding MOSFETs are installed
    inout	  abc_rdy_x, // RDY = WAIT#
    inout	  abc_resin_x, // System reset request
    inout	  abc_int80_x, // System INT request (ABC80)
    inout	  abc_int800_x, // System INT request (ABC800)
    inout	  abc_nmi_x, // System NMI request (ABC800)
    inout	  abc_xm_x, // System memory override (ABC800)
    // Host/device control
    output	  abc_host, // 1 = host, 0 = target

    // ABC-bus extension header
    // (Note: cannot use an array here because HC and HH are
    // input only.)
    inout	  exth_ha,
    inout	  exth_hb,
    input	  exth_hc,
    inout	  exth_hd,
    inout	  exth_he,
    inout	  exth_hf,
    inout	  exth_hg,
    input	  exth_hh,

    // SDRAM bus
    output	  sr_clk,
    output [1:0]  sr_ba, // Bank address
    output [12:0] sr_a, // Address within bank
    inout [15:0]  sr_dq, // Also known as D or IO
    output [1:0]  sr_dqm, // DQML and DQMH
    output	  sr_cs_n,
    output	  sr_we_n,
    output	  sr_cas_n,
    output	  sr_ras_n,

    // SD card
    input	  sd_cd_n,
    output	  sd_cs_n,
    output	  sd_clk,
    output	  sd_di,
    input	  sd_do,

    // SPI flash memory (also configuration)
    output	  flash_cs_n,
    output	  flash_sck,
    inout [1:0]   flash_io,

    // SPI bus (connected to ESP32 so can be bidirectional)
    inout	  spi_clk,
    inout	  spi_miso,
    inout	  spi_mosi,
    inout	  spi_cs_esp_n, // ESP32 IO10
    inout	  spi_cs_flash_n, // ESP32 IO01

    // Other ESP32 connections
    inout	  esp_io0, // ESP32 IO00
    inout	  esp_int, // ESP32 IO09

    // I2C bus (RTC and external)
    inout	  i2c_scl,
    inout	  i2c_sda,
    input	  rtc_32khz,
    input	  rtc_int_n,

    // LED (2 = D17/Y, 1 = D22/G, 0 = D23/B)
    output [2:0]  led,

    // USB
    inout	  usb_dp,
    inout	  usb_dn,
    output	  usb_pu,
    input	  usb_rx,

    // GPIO
    inout [5:0]   gpio,

    // HDMI
    output [2:0]  hdmi_d,
    output	  hdmi_clk,
    inout	  hdmi_scl,
    inout	  hdmi_sda,
    inout	  hdmi_hpd,

    // Unconnected pins with pullups, used for randomness
    inout [2:0]   rngio
    );

   // GPIO assignments for debug serial port:
   // gpio[0] - TxD
   // gpio[2] - RxD
   // gpio[4] - DTR#

   // Master PLL: 16 -> 336 MHz
   wire		  reset_plls;
   wire		  master_pll_locked;
   wire		  master_clk;

   pll2_16 pll2 (
		 .areset ( reset_plls ),
		 .locked ( master_pll_locked ),
		 .inclk0 ( clock_16 ),
		 .c0 ( master_clk )
		 );

   wire		  usb_clk;
   wire		  sys_clk;

   `MAIN #(.x_mosfet(6'b000000),
	   .fpga_ver(8'd2))
   `MAIN (
	  .master_clk             ( master_clk ),
	  .master_pll_locked	  ( master_pll_locked ),
	  .reset_plls             ( reset_plls ),
	  .board_id               ( board_id ),
	  .abc_clk                ( abc_clk ),
	  .abc_a                  ( abc_a ),
	  .abc_d                  ( abc_d ),
	  .abc_d_oe               ( abc_d_oe ),
	  .abc_rst_n              ( abc_rst_n ),
	  .abc_cs_n               ( abc_cs_n ),
	  .abc_out_n              ( abc_out_n ),
	  .abc_inp_n              ( abc_inp_n ),
	  .abc_xmemfl_n           ( abc_xmemfl_n ),
	  .abc_xmemw800_n         ( abc_xmemw800_n ),
	  .abc_xmemw80_n          ( abc_xmemw80_n ),
	  .abc_xinpstb_n          ( abc_xinpstb_n ),
	  .abc_xoutpstb_n         ( abc_xoutpstb_n ),
	  .abc_rdy_x              ( abc_rdy_x ),
	  .abc_resin_x            ( abc_resin_x ),
	  .abc_int80_x            ( abc_int80_x ),
	  .abc_int800_x           ( abc_int800_x ),
	  .abc_nmi_x              ( abc_nmi_x ),
	  .abc_xm_x               ( abc_xm_x ),
	  .abc_host               ( abc_host ),
	  .exth_ha                ( exth_ha ),
	  .exth_hb                ( exth_hb ),
	  .exth_hc                ( exth_hc ),
	  .exth_hd                ( exth_hd ),
	  .exth_he                ( exth_he ),
	  .exth_hf                ( exth_hf ),
	  .exth_hg                ( exth_hg ),
	  .exth_hh                ( exth_hh ),
	  .sr_clk                 ( sr_clk ),
	  .sr_ba                  ( sr_ba ),
	  .sr_a                   ( sr_a ),
	  .sr_dq                  ( sr_dq ),
	  .sr_dqm                 ( sr_dqm ),
	  .sr_cs_n                ( sr_cs_n ),
	  .sr_we_n                ( sr_we_n ),
	  .sr_cas_n               ( sr_cas_n ),
	  .sr_ras_n               ( sr_ras_n ),
	  .sd_cd_n		  ( 1'b0 ), // Needs rework on my board
	  .sd_cs_n                ( sd_cs_n ),
	  .sd_clk                 ( sd_clk ),
	  .sd_di                  ( sd_di ),
	  .sd_do		  ( sd_do ),
	  .tty_txd                ( gpio[0] ),
	  .tty_rxd                ( gpio[2] ),
	  .tty_rts                ( 1'b0 ),
	  .tty_cts                (  ),
	  .tty_dtr                ( gpio[4] ),
	  .flash_cs_n             ( flash_cs_n ),
	  .flash_sck              ( flash_sck ),
	  .flash_io               ( flash_io ),
	  .spi_clk                ( spi_clk ),
	  .spi_miso               ( spi_miso ),
	  .spi_mosi               ( spi_mosi ),
	  .spi_cs_esp_n           ( spi_cs_esp_n ),
	  .spi_cs_flash_n         ( spi_cs_flash_n ),
	  .esp_io0                ( esp_io0 ),
	  .esp_int                ( esp_int ),
	  .i2c_scl                ( i2c_scl ),
	  .i2c_sda                ( i2c_sda ),
	  .rtc_32khz              ( rtc_32khz ),
	  .rtc_int_n              ( rtc_int_n ),
	  .led                    ( led ),
	  .usb_dp                 ( usb_dp ),
	  .usb_dn                 ( usb_dn ),
	  .usb_rx                 ( usb_rx ),
	  .usb_rx_ok              ( 1'b1 ),
	  .usb_pu		  ( usb_pu ),
	  .hdmi_d                 ( hdmi_d ),
	  .hdmi_clk               ( hdmi_clk ),
	  .hdmi_scl               ( hdmi_scl ),
	  .hdmi_sda               ( hdmi_sda ),
	  .hdmi_hpd               ( hdmi_hpd ),
	  .rngio                  ( rngio ),

	  .sys_clk		  ( sys_clk ),
	  .usb_clk		  ( usb_clk )
	  );

   // sys_clk and usb_clk to GPIO
   clk_buf sys_clk_buf ( .clk ( sys_clk ), .pin ( gpio[1] ) );
   clk_buf usb_clk_buf ( .clk ( usb_clk ), .pin ( gpio[3] ) );

   // 4 Hz test signal on gpio[5], derived from sys_clk (84 MHz)
   reg [23:0]	  ctr_8hz;
   reg		  test_4hz;

   always @(posedge sys_clk)
     begin
	if (ctr_8hz >= 24'd10_500_000)
	  begin
	     ctr_8hz <= 24'd1;
	     test_4hz <= ~test_4hz;
	  end
	else
	  begin
	     ctr_8hz <= ctr_8hz + 1'b1;
	  end
     end // always @ (posedge sys_clk)

   assign gpio[5] = test_4hz;

endmodule // v2
