diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..6a5628b
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,15 @@
+variables:
+ GIT_SUBMODULE_STRATEGY: recursive
+
+stages:
+ - build
+
+build hw:
+ stage: build
+ tags:
+ - efinity
+ - linux
+ script:
+ - source init_env.sh
+ - make hw
+
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..07a7976
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "hw/super6502_fpga/src/sub/rtl-common"]
+ path = hw/super6502_fpga/src/sub/rtl-common
+ url = ../rtl-common.git
+[submodule "hw/super6502_fpga/src/sub/axi_crossbar"]
+ path = hw/super6502_fpga/src/sub/axi_crossbar
+ url = ../axi_crossbar.git
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7b9cb5d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+all: hw
+
+.PHONY: hw
+hw:
+ $(MAKE) -C hw
+
+.PHONY: clean
+clean:
+ $(MAKE) -C hw $@
\ No newline at end of file
diff --git a/hw/Makefile b/hw/Makefile
new file mode 100644
index 0000000..cacf66e
--- /dev/null
+++ b/hw/Makefile
@@ -0,0 +1,6 @@
+all:
+ $(MAKE) -C super6502_fpga
+
+.PHONY: clean
+clean:
+ $(MAKE) -C super6502_fpga $@
\ No newline at end of file
diff --git a/hw/super6502_fpga/.gitignore b/hw/super6502_fpga/.gitignore
new file mode 100644
index 0000000..0af698c
--- /dev/null
+++ b/hw/super6502_fpga/.gitignore
@@ -0,0 +1,3 @@
+outflow
+work_*
+.lock
diff --git a/hw/super6502_fpga/Makefile b/hw/super6502_fpga/Makefile
new file mode 100644
index 0000000..8b16685
--- /dev/null
+++ b/hw/super6502_fpga/Makefile
@@ -0,0 +1,15 @@
+SUPER6502_FPGA_SOURCES=$(shell cat sources.list)
+
+SUPER6502_FPGA_BITSTREAM=outflow/super6502_fpga.hex
+
+SUPER6502_FPGA_PROJECT=super6502_fpga.xml
+
+all: $(SUPER6502_FPGA_BITSTREAM)
+
+$(SUPER6502_FPGA_BITSTREAM): $(SUPER6502_FPGA_SOURCES) $(SUPER6502_FPGA_PROJECT)
+ efx_run.py $(SUPER6502_FPGA_PROJECT)
+
+.PHONY: clean
+clean:
+ rm -rf work_*
+ rm -rf outflow
\ No newline at end of file
diff --git a/hw/super6502_fpga/addr_map.mem b/hw/super6502_fpga/addr_map.mem
new file mode 100644
index 0000000..3d631b3
--- /dev/null
+++ b/hw/super6502_fpga/addr_map.mem
@@ -0,0 +1,5 @@
+@00000000
+00000000
+000001ff
+0000ff00
+0000ffff
\ No newline at end of file
diff --git a/hw/super6502_fpga/constraints/constraints.sdc b/hw/super6502_fpga/constraints/constraints.sdc
new file mode 100644
index 0000000..f294bb2
--- /dev/null
+++ b/hw/super6502_fpga/constraints/constraints.sdc
@@ -0,0 +1,5 @@
+create_clock -period 5.00 i_sdrclk
+create_clock -period 5.00 i_tACclk
+create_clock -period 10.00 i_sysclk
+
+create_generated_clock -source i_sysclk -divide_by 50 clk_cpu
diff --git a/hw/super6502_fpga/init_hex.mem b/hw/super6502_fpga/init_hex.mem
new file mode 100644
index 0000000..b6697d2
--- /dev/null
+++ b/hw/super6502_fpga/init_hex.mem
@@ -0,0 +1,65 @@
+@00000000
+8d00a9
+200cd02
+801a03d0
+fe80f5
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+ff000000
+ff00ff00
diff --git a/hw/super6502_fpga/sources.list b/hw/super6502_fpga/sources.list
new file mode 100644
index 0000000..e717faa
--- /dev/null
+++ b/hw/super6502_fpga/sources.list
@@ -0,0 +1,14 @@
+src/rtl/super_6502_fpga.sv
+src/sub/axi_crossbar/src/rtl/axi_crossbar.sv
+src/sub/axi_crossbar/src/rtl/axi_master.sv
+src/sub/axi_crossbar/src/rtl/axi_slave.sv
+src/sub/axi_crossbar/src/rtl/rr_scheduler.sv
+src/sub/axi_crossbar/src/rtl/slave_addr_decoder.sv
+src/sub/cpu_wrapper/cpu_wrapper.sv
+src/sub/rtl-common/src/rtl/async_fifo.sv
+src/sub/rtl-common/src/rtl/axi4_lite_ram.sv
+src/sub/rtl-common/src/rtl/axi4_lite_rom.sv
+src/sub/rtl-common/src/rtl/ff_cdc.sv
+src/sub/rtl-common/src/rtl/shallow_async_fifo.sv
+src/sub/rtl-common/src/rtl/sync_fifo.sv
+
diff --git a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv
new file mode 100644
index 0000000..62429b3
--- /dev/null
+++ b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv
@@ -0,0 +1,257 @@
+module super6502_fpga(
+ input logic i_sysclk, // Controller Clock (100MHz)
+ input logic i_sdrclk, // t_su and t_wd clock (200MHz)
+ input logic i_tACclk, // t_ac clock (200MHz)
+ input clk_cpu,
+
+ input button_reset,
+
+ input pll_cpu_locked,
+ output logic pll_cpu_reset,
+
+ input i_pll_locked,
+ output logic o_pll_reset,
+
+ input [7:0] i_cpu0_data_from_cpu,
+ input i_cpu0_sync,
+ input i_cpu0_rwb,
+ input logic [15:0] i_cpu0_addr,
+ output logic [7:0] o_cpu0_data_from_dut,
+ output logic [7:0] o_cpu0_data_oe,
+ output logic o_cpu0_irqb,
+ output logic o_cpu0_nmib,
+ output logic o_cpu0_rdy,
+ output logic o_cpu0_reset,
+ output logic o_clk_phi2
+);
+
+
+localparam ADDR_WIDTH = 32;
+localparam DATA_WIDTH = 32;
+
+assign pll_cpu_reset = '1;
+assign o_pll_reset = '1;
+
+assign o_cpu0_nmib = '1;
+
+assign o_clk_phi2 = clk_cpu;
+
+assign o_cpu0_data_oe = {8{i_cpu0_rwb}};
+
+
+logic master_reset;
+
+assign master_reset = button_reset;
+
+logic cpu0_AWVALID;
+logic cpu0_AWREADY;
+logic [ADDR_WIDTH-1:0] cpu0_AWADDR;
+logic cpu0_WVALID;
+logic cpu0_WREADY;
+logic [DATA_WIDTH-1:0] cpu0_WDATA;
+logic [DATA_WIDTH/8-1:0] cpu0_WSTRB;
+logic cpu0_BVALID;
+logic cpu0_BREADY;
+logic [1:0] cpu0_BRESP;
+logic cpu0_ARVALID;
+logic cpu0_ARREADY;
+logic [ADDR_WIDTH-1:0] cpu0_ARADDR;
+logic cpu0_RVALID;
+logic cpu0_RREADY;
+logic [DATA_WIDTH-1:0] cpu0_RDATA;
+logic [1:0] cpu0_RRESP;
+
+
+logic ram_awvalid;
+logic ram_awready;
+logic [ADDR_WIDTH-1:0] ram_awaddr;
+logic ram_wvalid;
+logic ram_wready;
+logic [DATA_WIDTH-1:0] ram_wdata;
+logic [DATA_WIDTH/8-1:0] ram_wstrb;
+logic ram_bvalid;
+logic ram_bready;
+logic [1:0] ram_bresp;
+logic ram_arvalid;
+logic ram_arready;
+logic [ADDR_WIDTH-1:0] ram_araddr;
+logic ram_rvalid;
+logic ram_rready;
+logic [DATA_WIDTH-1:0] ram_rdata;
+logic [1:0] ram_rresp;
+
+logic rom_awvalid;
+logic rom_awready;
+logic [ADDR_WIDTH-1:0] rom_awaddr;
+logic rom_wvalid;
+logic rom_wready;
+logic [DATA_WIDTH-1:0] rom_wdata;
+logic [DATA_WIDTH/8-1:0] rom_wstrb;
+logic rom_bvalid;
+logic rom_bready;
+logic [1:0] rom_bresp;
+logic rom_arvalid;
+logic rom_arready;
+logic [ADDR_WIDTH-1:0] rom_araddr;
+logic rom_rvalid;
+logic rom_rready;
+logic [DATA_WIDTH-1:0] rom_rdata;
+logic [1:0] rom_rresp;
+
+
+cpu_wrapper u_cpu_wrapper_0(
+ .i_clk_cpu (clk_cpu),
+ .i_clk_100 (i_sysclk),
+ .i_rst (~master_reset),
+
+ .o_cpu_rst (o_cpu0_reset),
+ .o_cpu_rdy (o_cpu0_rdy),
+ .o_cpu_be (),
+ .o_cpu_irqb (o_cpu0_irqb),
+ .o_cpu_nmib (),
+ .o_cpu_sob (),
+
+ .i_cpu_rwb (i_cpu0_rwb),
+ .i_cpu_sync (i_cpu0_sync),
+ .i_cpu_vpb ('0),
+ .i_cpu_mlb ('0),
+
+ .i_cpu_addr (i_cpu0_addr),
+ .i_cpu_data (i_cpu0_data_from_cpu),
+ .o_cpu_data (o_cpu0_data_from_dut),
+
+ .o_AWVALID (cpu0_AWVALID),
+ .i_AWREADY (cpu0_AWREADY),
+ .o_AWADDR (cpu0_AWADDR),
+ .o_WVALID (cpu0_WVALID),
+ .i_WREADY (cpu0_WREADY),
+ .o_WDATA (cpu0_WDATA),
+ .o_WSTRB (cpu0_WSTRB),
+ .i_BVALID (cpu0_BVALID),
+ .o_BREADY (cpu0_BREADY),
+ .i_BRESP (cpu0_BRESP),
+ .o_ARVALID (cpu0_ARVALID),
+ .i_ARREADY (cpu0_ARREADY),
+ .o_ARADDR (cpu0_ARADDR),
+ .i_RVALID (cpu0_RVALID),
+ .o_RREADY (cpu0_RREADY),
+ .i_RDATA (cpu0_RDATA),
+ .i_RRESP (cpu0_RRESP),
+
+ .i_irq('0),
+ .i_nmi('0)
+);
+
+
+axi_crossbar #(
+ .N_INITIATORS(1),
+ .N_TARGETS(2)
+) u_crossbar (
+ .clk(i_sysclk),
+ .rst(~master_reset),
+
+ .ini_araddr ({cpu0_ARADDR }),
+ .ini_arvalid ({cpu0_ARVALID }),
+ .ini_arready ({cpu0_ARREADY }),
+ .ini_rdata ({cpu0_RDATA }),
+ .ini_rresp ({cpu0_RRESP }),
+ .ini_rvalid ({cpu0_RVALID }),
+ .ini_rready ({cpu0_RREADY }),
+ .ini_awaddr ({cpu0_AWADDR }),
+ .ini_awready ({cpu0_AWREADY }),
+ .ini_awvalid ({cpu0_AWVALID }),
+ .ini_wvalid ({cpu0_WVALID }),
+ .ini_wready ({cpu0_WREADY }),
+ .ini_wdata ({cpu0_WDATA }),
+ .ini_wstrb ({cpu0_WSTRB }),
+ .ini_bresp ({cpu0_BRESP }),
+ .ini_bvalid ({cpu0_BVALID }),
+ .ini_bready ({cpu0_BREADY }),
+
+ .tgt_araddr ({ram_araddr, rom_araddr }),
+ .tgt_arvalid ({ram_arvalid, rom_arvalid }),
+ .tgt_arready ({ram_arready, rom_arready }),
+ .tgt_rdata ({ram_rdata, rom_rdata }),
+ .tgt_rresp ({ram_rresp, rom_rresp }),
+ .tgt_rvalid ({ram_rvalid, rom_rvalid }),
+ .tgt_rready ({ram_rready, rom_rready }),
+ .tgt_awaddr ({ram_awaddr, rom_awaddr }),
+ .tgt_awvalid ({ram_awvalid, rom_awvalid }),
+ .tgt_awready ({ram_awready, rom_awready }),
+ .tgt_wdata ({ram_wdata, rom_wdata }),
+ .tgt_wvalid ({ram_wvalid, rom_wvalid }),
+ .tgt_wready ({ram_wready, rom_wready }),
+ .tgt_wstrb ({ram_wstrb, rom_wstrb }),
+ .tgt_bresp ({ram_bresp, rom_bresp }),
+ .tgt_bvalid ({ram_bvalid, rom_bvalid }),
+ .tgt_bready ({ram_bready, rom_bready })
+);
+
+axi4_lite_rom #(
+ .ROM_SIZE(8),
+ .ROM_INIT_FILE("init_hex.mem")
+) u_rom (
+ .i_clk(i_sysclk),
+ .i_rst(~master_reset),
+
+ .o_AWREADY(rom_awready),
+ .o_WREADY(rom_wready),
+
+ .o_BVALID(rom_bvalid),
+ .i_BREADY(rom_bready),
+ .o_BRESP(rom_bresp),
+
+ .i_ARVALID(rom_arvalid),
+ .o_ARREADY(rom_arready),
+ .i_ARADDR(rom_araddr),
+ .i_ARPROT('0),
+
+ .o_RVALID(rom_rvalid),
+ .i_RREADY(rom_rready),
+ .o_RDATA(rom_rdata),
+ .o_RRESP(rom_rresp),
+
+ .i_AWVALID(rom_awvalid),
+ .i_AWADDR(rom_awaddr),
+ .i_AWPROT('0),
+
+ .i_WVALID(rom_wvalid),
+ .i_WDATA(rom_wdata),
+ .i_WSTRB(rom_wstrb)
+);
+
+axi4_lite_ram #(
+ .RAM_SIZE(9)
+) u_ram(
+ .i_clk(i_sysclk),
+ .i_rst(~master_reset),
+
+ .o_AWREADY(ram_awready),
+ .o_WREADY(ram_wready),
+
+ .o_BVALID(ram_bvalid),
+ .i_BREADY(ram_bready),
+ .o_BRESP(ram_bresp),
+
+ .i_ARVALID(ram_arvalid),
+ .o_ARREADY(ram_arready),
+ .i_ARADDR(ram_araddr),
+ .i_ARPROT('0),
+
+ .o_RVALID(ram_rvalid),
+ .i_RREADY(ram_rready),
+ .o_RDATA(ram_rdata),
+ .o_RRESP(ram_rresp),
+
+ .i_AWVALID(ram_awvalid),
+ .i_AWADDR(ram_awaddr),
+ .i_AWPROT('0),
+
+ .i_WVALID(ram_wvalid),
+ .i_WDATA(ram_wdata),
+ .i_WSTRB(ram_wstrb)
+);
+
+
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/axi_crossbar b/hw/super6502_fpga/src/sub/axi_crossbar
new file mode 160000
index 0000000..5c61f56
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/axi_crossbar
@@ -0,0 +1 @@
+Subproject commit 5c61f56e7b66853abe2a079745d1cf010bd18175
diff --git a/hw/super6502_fpga/src/sub/cpu_wrapper/cpu_wrapper.sv b/hw/super6502_fpga/src/sub/cpu_wrapper/cpu_wrapper.sv
new file mode 100644
index 0000000..b0a20fd
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/cpu_wrapper/cpu_wrapper.sv
@@ -0,0 +1,391 @@
+module cpu_wrapper #(
+ parameter ADDR_WIDTH = 32,
+ parameter DATA_WIDTH = 32
+)(
+ /* Clocks and Reset */
+ input logic i_clk_cpu,
+ input logic i_clk_100,
+ input logic i_rst,
+
+ /* CPU Control Signals */
+ output logic o_cpu_rst,
+ output logic o_cpu_rdy,
+ output logic o_cpu_be,
+ output logic o_cpu_irqb,
+ output logic o_cpu_nmib,
+ output logic o_cpu_sob,
+
+ /* CPU Status Signals */
+ input logic i_cpu_rwb,
+ input logic i_cpu_sync,
+ input logic i_cpu_vpb,
+ input logic i_cpu_mlb,
+
+ /* CPU Address and Data */
+ input logic [15:0] i_cpu_addr,
+ input logic [7:0] i_cpu_data,
+ output logic [7:0] o_cpu_data,
+
+ /* AXI4-Lite signals */
+ output logic o_AWVALID,
+ input logic i_AWREADY,
+ output logic [ADDR_WIDTH-1:0] o_AWADDR,
+ output logic [2:0] o_AWPROT,
+
+ output logic o_WVALID,
+ input logic i_WREADY,
+ output logic [DATA_WIDTH-1:0] o_WDATA,
+ output logic [DATA_WIDTH/8-1:0] o_WSTRB,
+
+ input logic i_BVALID,
+ output logic o_BREADY,
+ input logic [1:0] i_BRESP,
+
+ output logic o_ARVALID,
+ input logic i_ARREADY,
+ output logic [ADDR_WIDTH-1:0] o_ARADDR,
+ output logic [2:0] o_ARPROT,
+
+ input logic i_RVALID,
+ output logic o_RREADY,
+ input logic [DATA_WIDTH-1:0] i_RDATA,
+ input logic [1:0] i_RRESP,
+
+ /* interrupt signals */
+ input logic i_irq,
+ input logic i_nmi
+);
+
+typedef enum logic [3:0] {
+ RESET,
+ IDLE,
+ ADDR_CONTROL,
+ READ_VALID,
+ READ_DATA,
+ WRITE_VALID,
+ GET_WRITE_DATA,
+ WRITE_DATA,
+ STALL
+} state_t;
+
+state_t state, state_next;
+
+logic w_status_empty;
+logic w_status_r_en;
+
+logic r_rwb, r_sync, r_vpb, r_mlb;
+logic r_rwb_next, r_sync_next, r_vpb_next, r_mlb_next;
+
+logic [15:0] r_addr, r_addr_next;
+
+logic w_write_data_en;
+logic [7:0] r_write_data, r_write_data_next;
+logic w_write_data_empty;
+
+logic [2:0] counter;
+logic w_reset;
+
+always @(posedge i_clk_cpu) begin
+ if (i_rst) begin
+ counter <= '1;
+ end else if (counter) begin
+ counter <= counter - 3'd1;
+ end
+end
+
+assign w_reset = |counter;
+
+ff_cdc #(
+ .RESET_VAL(0)
+) u_cpu_rst_cdc (
+ .rst(i_rst),
+ .clk(i_clk_cpu),
+ .data_a(~w_reset),
+ .data_b(o_cpu_rst)
+);
+
+ff_cdc u_cpu_irq_cdc (
+ .rst(i_rst),
+ .clk(i_clk_cpu),
+ .data_a(~i_irq),
+ .data_b(o_cpu_irqb)
+);
+
+ff_cdc u_cpu_nmi_cdc (
+ .rst(i_rst),
+ .clk(i_clk_cpu),
+ .data_a(~i_nmi),
+ .data_b(o_cpu_nmib)
+);
+
+// This fifo says it has a bug with back to back writes, but maybe that
+// is only for fast -> slow? this is slow -> fast.
+// async_fifo #(
+// .WIDTH(20),
+// .A_SIZE(3)
+// ) u_status_addr_fifo (
+// .i_rst_a(o_cpu_rst),
+// .i_clk_a(i_clk_cpu),
+// .i_rst_b(i_rst),
+// .i_clk_b(i_clk_100),
+// .w_en('1), // investigate this
+// .i_data({i_cpu_rwb, i_cpu_sync, i_cpu_vpb, i_cpu_mlb, i_cpu_addr}),
+// .o_full(),
+// .r_en(w_status_r_en),
+// .o_data({r_rwb_next, r_sync_next, r_vpb_next, r_mlb_next, r_addr_next}),
+// .o_empty(w_status_empty)
+// );
+
+
+logic [1:0] flag;
+
+assign w_status_empty = ~flag[0];
+
+assign r_rwb_next = i_cpu_rwb;
+assign r_sync_next = i_cpu_sync;
+assign r_vpb_next = i_cpu_vpb;
+assign r_mlb_next = i_cpu_mlb;
+assign r_addr_next = i_cpu_addr;
+
+always @(posedge i_clk_100 or posedge i_rst) begin
+ if (i_rst) begin
+ flag <= '0;
+ end else begin
+ if (i_clk_cpu) begin
+ if (flag == '0) begin
+ flag <= 2'h1;
+ end else if (flag == 2'h1) begin
+ flag <= 2'h2;
+ end
+ end else begin
+ flag <= '0;
+ end
+ end
+end
+
+// // This uses inverted clock, remember in sdc?
+// async_fifo #(
+// .WIDTH(8),
+// .A_SIZE(3)
+// ) u_write_data_fifo (
+// .i_rst_a(o_cpu_rst),
+// .i_clk_a(~i_clk_cpu),
+// .i_rst_b(i_rst),
+// .i_clk_b(i_clk_100),
+// .w_en('1),
+// .i_data(i_cpu_data),
+// .o_full(),
+// .r_en(w_write_data_en),
+// .o_data(r_write_data_next),
+// .o_empty(w_write_data_empty)
+// );
+
+
+// Really bad double flop bus
+always @(negedge i_clk_cpu) begin
+ r_write_data_next <= i_cpu_data;
+end
+
+
+logic [1:0] flag2;
+
+assign w_write_data_empty = ~flag2[0];
+
+always @(posedge i_clk_100 or posedge i_rst) begin
+ if (i_rst) begin
+ flag2 <= '0;
+ end else begin
+ if (~i_clk_cpu) begin
+ if (flag2 == '0) begin
+ flag2 <= 2'h1;
+ end else if (flag2 == 2'h1) begin
+ flag2 <= 2'h2;
+ end
+ end else begin
+ flag2 <= '0;
+ end
+ end
+end
+
+localparam MAX_DELAY = 4;
+
+logic [7:0] cycle_counter;
+logic too_late;
+
+logic [2:0] rdy_dly;
+logic potential_rdy;
+logic did_delay, did_delay_next;
+
+assign potential_rdy = |rdy_dly;
+
+assign too_late = cycle_counter > MAX_DELAY ? 1 : 0;
+
+always_ff @(posedge i_clk_100 or posedge i_rst) begin
+ if (i_rst) begin
+ cycle_counter <= '0;
+ rdy_dly <= '0;
+ end else begin
+ if (i_clk_cpu) begin
+ cycle_counter <= cycle_counter + 1;
+ end else begin
+ cycle_counter <= '0;
+ end
+
+ rdy_dly <= {rdy_dly[1:0], too_late};
+ end
+end
+
+logic [7:0] read_data, read_data_next;
+assign o_cpu_data = read_data;
+
+always_comb begin
+ state_next = state;
+
+ // Set defaults
+ o_AWVALID = '0;
+ o_AWADDR = '0;
+ o_AWPROT = '0;
+ o_WVALID = '0;
+ o_WDATA = '0;
+ o_WSTRB = '0;
+ o_BREADY = '0;
+ o_ARVALID = '0;
+ o_ARADDR = '0;
+ o_ARPROT = '0;
+ o_RREADY = '0;
+
+ o_cpu_rdy = '1;
+
+ read_data_next = read_data;
+ did_delay_next = did_delay;
+
+ case (state)
+ RESET: begin
+ // Is this a CDC violation?
+ if (i_cpu_addr == 16'hFFFC) begin
+ state_next = IDLE;
+ end
+ end
+
+ IDLE: begin
+ if (~w_status_empty) begin
+ state_next = ADDR_CONTROL;
+ end
+
+ did_delay_next = '0;
+ end
+
+ ADDR_CONTROL: begin
+ if (r_rwb) begin
+ state_next = READ_VALID;
+ end else begin
+ state_next = WRITE_VALID;
+ end
+ end
+
+ READ_VALID: begin
+ o_ARVALID = '1;
+ // $display("%x %x %x", o_ARVALID, i_ARREADY, o_ARVALID & i_ARREADY);
+
+ if (o_ARVALID & i_ARREADY) begin
+ // $display("AHHHHHH");
+ state_next = READ_DATA;
+ // $display("next state: %x", state_next);
+ end
+
+ o_ARADDR = {r_addr[15:2], 2'b0};
+ end
+
+ READ_DATA: begin
+ if (potential_rdy) begin
+ state_next = READ_DATA;
+ o_cpu_rdy = ~potential_rdy;
+ did_delay_next = '1;
+ end
+
+ if (i_RVALID) begin
+ if (did_delay || potential_rdy) begin
+ state_next = STALL;
+ end else begin
+ state_next = IDLE;
+ end
+ read_data_next = i_RDATA[8*r_addr[1:0] +: 8];
+ end
+
+ o_RREADY = '1;
+ end
+
+ WRITE_VALID: begin
+ if (~w_write_data_empty) begin
+ state_next = WRITE_DATA;
+ end
+ end
+
+ GET_WRITE_DATA: begin
+ $error("GET_WRITE_DATA not implemented");
+ state_next = IDLE;
+ end
+
+ WRITE_DATA: begin
+ o_AWVALID = '1;
+ o_AWADDR = {r_addr[15:2], 2'b0};
+ o_WVALID = '1;
+ o_WSTRB = 4'b1 << r_addr[1:0];
+ o_WDATA = r_write_data << 8*r_addr[1:0];
+
+ o_BREADY = '1;
+ if (i_BVALID) begin
+ state_next = IDLE;
+ end
+ end
+
+ STALL: begin
+ // kind of dumb
+ if (cycle_counter == 1) begin
+ state_next = IDLE;
+ end
+
+ o_cpu_rdy = ~potential_rdy;
+ end
+
+ default: begin
+ // $error("Invalid state");
+ state_next = IDLE;
+ end
+
+ endcase
+end
+
+always_ff @(posedge i_clk_100 or posedge i_rst) begin
+ if (i_rst) begin
+ r_rwb <= '1; // start as 1 to indicate read.
+ r_sync <= '0;
+ r_vpb <= '0;
+ r_mlb <= '0;
+ r_addr <= '0;
+ read_data <= '0;
+ r_write_data <= '0;
+ did_delay <= '0;
+
+ state <= RESET;
+ end else begin
+ if (~w_status_empty) begin
+ w_status_r_en <= '1;
+ r_rwb <= r_rwb_next;
+ r_sync <= r_sync_next;
+ r_vpb <= r_vpb_next;
+ r_mlb <= r_mlb_next;
+ r_addr <= r_addr_next;
+ end else begin
+ w_status_r_en <= '0;
+ end
+
+ read_data <= read_data_next;
+ state <= state_next;
+ did_delay <= did_delay_next;
+
+ r_write_data <= r_write_data_next;
+ end
+end
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/rtl-common b/hw/super6502_fpga/src/sub/rtl-common
new file mode 160000
index 0000000..170285d
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/rtl-common
@@ -0,0 +1 @@
+Subproject commit 170285d7abf968dbe9cb6f3d919039bc117eef60
diff --git a/hw/super6502_fpga/super6502_fpga.peri.xml b/hw/super6502_fpga/super6502_fpga.peri.xml
new file mode 100644
index 0000000..a664a30
--- /dev/null
+++ b/hw/super6502_fpga/super6502_fpga.peri.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hw/super6502_fpga/super6502_fpga.xml b/hw/super6502_fpga/super6502_fpga.xml
new file mode 100644
index 0000000..71190d7
--- /dev/null
+++ b/hw/super6502_fpga/super6502_fpga.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file