Ver código fonte

FPGA: rework shared memory access

Maximilian Rehkopf 12 anos atrás
pai
commit
f3a67ab5aa

+ 5 - 9
verilog/sd2snes/address.v

@@ -23,16 +23,14 @@ module address(
   input [2:0] MAPPER,       // MCU detected mapper
   input [23:0] SNES_ADDR,   // requested address from SNES
   input SNES_CS,            // "CART" pin from SNES (active low)
-  output [22:0] ROM_ADDR,   // Address to request from SRAM0
+  output [23:0] ROM_ADDR,   // Address to request from SRAM0
   output ROM_SEL,           // enable SRAM0 (active low)
   input MCU_OVR,            // enable MCU master mode (active low)
-  input MODE,               // MCU(1) or SNES(0) ("bus phase")
   output IS_SAVERAM,        // address/CS mapped as SRAM?
   output IS_ROM,            // address mapped as ROM?
   output IS_WRITABLE,       // address somehow mapped as writable area?
   input [23:0] MCU_ADDR,    // allow address to be set externally
   input ADDR_WRITE,
-  output ROM_ADDR0,
   input [23:0] SAVERAM_MASK,
   input [23:0] ROM_MASK,
   input use_msu,
@@ -54,7 +52,7 @@ parameter [2:0]
 
 wire [1:0] SRAM_BANK;
 
-wire [23:0] SRAM_ADDR_FULL;
+wire [23:0] SRAM_SNES_ADDR;
 
 /* currently supported mappers:
    Index     Mapper
@@ -101,6 +99,7 @@ assign IS_SAVERAM = SAVERAM_MASK[0]
                       : 1'b0));
 
 
+/* BS-X has 4 MBits of extra RAM that can be mapped to various places */
 assign IS_WRITABLE = IS_SAVERAM
                      |((MAPPER == 3'b011)
                        ?((bsx_regs[3] && SNES_ADDR[23:20]==4'b0110)
@@ -123,8 +122,7 @@ assign IS_WRITABLE = IS_SAVERAM
     8   1=map BSX cartridge ROM @80-9f:8000-ffff
 */
 
-assign SRAM_ADDR_FULL = (MODE) ? MCU_ADDR
-                        :((MAPPER == 3'b000)
+assign SRAM_SNES_ADDR = ((MAPPER == 3'b000)
                           ?(IS_SAVERAM
                             ? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000)
                                             & SAVERAM_MASK)
@@ -188,12 +186,10 @@ assign SRAM_ADDR_FULL = (MODE) ? MCU_ADDR
                             )
                            : 24'b0);
 
-assign ROM_ADDR = SRAM_ADDR_FULL[23:1];
+assign ROM_ADDR = SRAM_SNES_ADDR;
 
 assign ROM_SEL = 1'b0; // (MODE) ? CS_ARRAY[SRAM_BANK] : IS_SAVERAM ? 4'b1000 : CS_ARRAY[SRAM_BANK];
 
-assign ROM_ADDR0 = SRAM_ADDR_FULL[0];
-
 assign msu_enable_w = featurebits[FEAT_MSU1] & (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfff8) == 16'h2000));
 reg [7:0] msu_enable_r;
 initial msu_enable_r = 8'b00000000;

+ 3 - 2
verilog/sd2snes/data.v

@@ -22,6 +22,7 @@ module data(
   input CLK,
   input SNES_READ,
   input SNES_WRITE,
+  input ROM_WE,
   input MCU_READ,
   input MCU_WRITE,
   inout [7:0] SNES_DATA,
@@ -80,7 +81,7 @@ assign MCU_OUT_DATA = !MCU_OVR ? (FROM_ROM_BYTE)
 assign ROM_DATA[7:0] = ROM_ADDR0
                        ?(!MCU_OVR ? (!MCU_WRITE ? MCU_IN_DATA : 8'bZ)
                                   : (MODE ? (!MCU_WRITE ? MCU_IN_MEM : 8'bZ)
-                                          : (!SNES_WRITE ? SNES_IN_MEM : 8'bZ)
+                                          : (!ROM_WE ? SNES_IN_MEM : 8'bZ)
                                     )
                         )
                        :8'bZ;
@@ -88,7 +89,7 @@ assign ROM_DATA[7:0] = ROM_ADDR0
 assign ROM_DATA[15:8] = ROM_ADDR0 ? 8'bZ
                         :(!MCU_OVR ? (!MCU_WRITE ? MCU_IN_DATA : 8'bZ)
                                    : (MODE ? (!MCU_WRITE ? MCU_IN_MEM : 8'bZ)
-                                           : (!SNES_WRITE ? SNES_IN_MEM : 8'bZ)
+                                           : (!ROM_WE ? SNES_IN_MEM : 8'bZ)
                                      )
                          );
 

+ 1 - 1
verilog/sd2snes/dcm.v

@@ -37,7 +37,7 @@ module my_dcm (
       .CLKFX_DIVIDE(1),   // Can be any integer from 1 to 32
       .CLKFX_MULTIPLY(4), // Can be any integer from 2 to 32
       .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
-      .CLKIN_PERIOD(43.478),  // Specify period of input clock
+      .CLKIN_PERIOD(41.667),  // Specify period of input clock
       .CLKOUT_PHASE_SHIFT("NONE"), // Specify phase shift of NONE, FIXED or VARIABLE
       .CLK_FEEDBACK("NONE"),  // Specify clock feedback of NONE, 1X or 2X
       .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or

+ 5 - 1
verilog/sd2snes/main.ucf

@@ -76,6 +76,10 @@ NET "MCU_OVR" LOC = P92;
 NET "MCU_OVR" IOSTANDARD = LVCMOS33;
 NET "MCU_OVR" DRIVE = 8;
 
+NET "MCU_RDY" LOC = P83;
+NET "MCU_RDY" IOSTANDARD = LVCMOS33;
+NET "MCU_RDY" DRIVE = 8;
+
 
 NET "ROM_ADDR[0]" LOC = P166;
 
@@ -517,4 +521,4 @@ NET "SD_DAT[2]" IOSTANDARD = LVCMOS33;
 NET "SD_DAT[3]" IOSTANDARD = LVCMOS33;
 
 NET "SNES_SYSCLK" LOC = P180;
-NET "SNES_SYSCLK" IOSTANDARD = LVCMOS33;
+NET "SNES_SYSCLK" IOSTANDARD = LVCMOS33;

+ 235 - 197
verilog/sd2snes/main.v

@@ -59,7 +59,8 @@ module main(
   input SPI_SS,
   inout SPI_SCK,
   input MCU_OVR,
-
+  output MCU_RDY,
+  
   output DAC_MCLK,
   output DAC_LRCK,
   output DAC_SDOUT,
@@ -67,14 +68,12 @@ module main(
   /* SD signals */
   input [3:0] SD_DAT,
   inout SD_CMD,
-  inout SD_CLK
+  inout SD_CLK,
 
   /* debug */
-  ,
   output p113_out
 );
 wire dspx_dp_enable;
-assign p113_out = dspx_dp_enable;
 
 wire [7:0] spi_cmd_data;
 wire [7:0] spi_param_data;
@@ -84,8 +83,6 @@ wire [2:0] spi_bit_cnt;
 wire [23:0] MCU_ADDR;
 wire [7:0] mcu_data_in;
 wire [7:0] mcu_data_out;
-wire [7:0] MCU_IN_DATA;
-wire [7:0] MCU_OUT_DATA;
 wire [3:0] MAPPER;
 wire [23:0] SAVERAM_MASK;
 wire [23:0] ROM_MASK;
@@ -132,6 +129,11 @@ wire [10:0] dspx_dat_addr;
 wire dspx_dat_we;
 
 wire [7:0] featurebits;
+
+wire [23:0] MAPPED_SNES_ADDR;
+wire ROM_ADDR0;
+wire [22:0] MAPPED_SNES_ADDR2 = MAPPED_SNES_ADDR[23:1];
+
 //wire SD_DMA_EN; //SPI_DMA_CTRL;
 
 sd_dma snes_sd_dma(
@@ -265,6 +267,9 @@ upd77c25 snes_dspx (
   .DP_ADDR(SNES_ADDR[10:0])
 );
 
+reg [7:0] MCU_DINr;
+wire [7:0] MCU_DOUT;
+
 mcu_cmd snes_mcu_cmd(
   .clk(CLK2),
   .snes_sysclk(SNES_SYSCLK),
@@ -274,10 +279,10 @@ mcu_cmd snes_mcu_cmd(
   .param_data(spi_param_data),
   .mcu_mapper(MAPPER),
   .mcu_sram_size(SRAM_SIZE),
-  .mcu_read(MCU_READ),
+//  .mcu_read(MCU_READ),
   .mcu_write(MCU_WRITE),
-  .mcu_data_in(MCU_OUT_DATA),
-  .mcu_data_out(MCU_IN_DATA),
+  .mcu_data_in(MCU_DINr),
+  .mcu_data_out(MCU_DOUT),
   .spi_byte_cnt(spi_byte_cnt),
   .spi_bit_cnt(spi_bit_cnt),
   .spi_data_out(spi_input_data),
@@ -324,7 +329,10 @@ mcu_cmd snes_mcu_cmd(
   .dspx_dat_addr_out(dspx_dat_addr),
   .dspx_dat_we_out(dspx_dat_we),
   .dspx_reset_out(dspx_reset),
-  .featurebits_out(featurebits)
+  .featurebits_out(featurebits),
+  .mcu_rrq(MCU_RRQ),
+  .mcu_wrq(MCU_WRQ),
+  .mcu_rq_rdy(MCU_RDY)
 );
 
 // dcm1: dfs 4x
@@ -338,37 +346,27 @@ my_dcm snes_dcm(
 
 assign DCM_RST=0;
 
-wire SNES_RW;
-reg [1:0] SNES_READr;
-reg [1:0] SNES_WRITEr;
-reg [1:0] SNES_CSr;
-reg [5:0] SNES_CPU_CLKr;
+reg [5:0] SNES_READr;
+reg [5:0] SNES_WRITEr;
+reg [12:0] SNES_CPU_CLKr;
 reg [5:0] SNES_RWr;
 reg [23:0] SNES_ADDRr;
-reg [23:0] SNES_ADDR_PREVr;
-reg [3:0] SNES_ADDRCHGr;
 
-wire SNES_READs = (SNES_READr == 2'b11);
-wire SNES_WRITEs = (SNES_WRITEr == 2'b11);
-wire SNES_CSs = (SNES_CSr == 2'b11);
-wire SNES_CPU_CLKs = SNES_CPU_CLK; // (SNES_CPU_CLKr == 2'b11);
-wire SNES_RW_start = (SNES_RWr == 6'b111110); // falling edge marks beginning of cycle
-wire SNES_cycle_start = (SNES_CPU_CLKr == 6'b000011);
-wire SNES_ADDRCHG = (SNES_ADDRr != SNES_ADDR_PREVr);
-wire SNES_addr_start = (SNES_ADDRCHGr[0] == 1'b1);
+wire SNES_RW = (SNES_READ & SNES_WRITE);
 
-assign SNES_RW = (SNES_READ & SNES_WRITE);
+wire SNES_RW_start = (SNES_RWr == 6'b111110); // falling edge marks beginning of cycle
+wire SNES_RD_start = (SNES_READr == 6'b111110);
+wire SNES_WR_start = (SNES_WRITEr == 6'b111110);
+wire SNES_cycle_start = (SNES_CPU_CLKr[5:0] == 6'b000001);
+wire SNES_cycle_end = (SNES_CPU_CLKr[5:0] == 6'b111110);
 
 always @(posedge CLK2) begin
-  SNES_READr <= {SNES_READr[0], SNES_READ};
-  SNES_WRITEr <= {SNES_WRITEr[0], SNES_WRITE};
-  SNES_CSr <= {SNES_CSr[0], SNES_CS};
-  SNES_CPU_CLKr <= {SNES_CPU_CLKr[4:0], SNES_CPU_CLK};
+  SNES_READr <= {SNES_READr[4:0], SNES_READ};
+  SNES_WRITEr <= {SNES_WRITEr[4:0], SNES_WRITE};
+  SNES_CPU_CLKr <= {SNES_CPU_CLKr[11:0], SNES_CPU_CLK};
   SNES_RWr <= {SNES_RWr[4:0], SNES_RW};
 end
 
-reg ADDR_WRITE;
-
 wire ROM_SEL;
 
 address snes_addr(
@@ -377,15 +375,13 @@ address snes_addr(
   .featurebits(featurebits),
   .SNES_ADDR(SNES_ADDR), // requested address from SNES
   .SNES_CS(SNES_CS),     // "CART" pin from SNES (active low)
-  .ROM_ADDR(ROM_ADDR),   // Address to request from SRAM (active low)
+  .ROM_ADDR(MAPPED_SNES_ADDR),   // Address to request from SRAM (active low)
   .ROM_SEL(ROM_SEL),     // which SRAM unit to access
   .MCU_OVR(MCU_OVR),     // enable MCU mode (active low)
-  .MODE(MODE),           // MCU(1) or SNES(0) ("bus phase")
   .IS_SAVERAM(IS_SAVERAM),
   .IS_ROM(IS_ROM),
   .IS_WRITABLE(IS_WRITABLE),
   .MCU_ADDR(MCU_ADDR),
-  .ROM_ADDR0(ROM_ADDR0),
   .SAVERAM_MASK(SAVERAM_MASK),
   .ROM_MASK(ROM_MASK),
   //MSU-1
@@ -407,73 +403,40 @@ wire SNES_WRITE_CYCLEw;
 wire MCU_READ_CYCLEw;
 wire MCU_WRITE_CYCLEw;
 
-data snes_data(
-  .CLK(CLK2),
-  .SNES_READ(SNES_READ),
-  .SNES_WRITE(SNES_WRITE),
-  .MCU_READ(MCU_READ),
-  .MCU_WRITE(MCU_WRITE),
-  .SNES_DATA(SNES_DATA),
-  .ROM_DATA(ROM_DATA),
-  .MODE(MODE),
-  .SNES_DATA_TO_MEM(SNES_DATA_TO_MEM),
-  .MCU_DATA_TO_MEM(MCU_DATA_TO_MEM),
-  .ROM_DATA_TO_SNES_MEM(ROM_DATA_TO_SNES_MEM),
-  .ROM_DATA_TO_MCU_MEM(ROM_DATA_TO_MCU_MEM),
-  .MCU_OVR(MCU_OVR),
-  .MCU_IN_DATA(MCU_IN_DATA),
-  .MCU_OUT_DATA(MCU_OUT_DATA),
-  .ROM_ADDR0(ROM_ADDR0),
-  .MSU_DATA_IN(MSU_SNES_DATA_IN),
-  .MSU_DATA_OUT(MSU_SNES_DATA_OUT),
-  .BSX_DATA_IN(BSX_SNES_DATA_IN),
-  .BSX_DATA_OUT(BSX_SNES_DATA_OUT),
-  .SRTC_DATA_IN(SRTC_SNES_DATA_IN),
-  .SRTC_DATA_OUT(SRTC_SNES_DATA_OUT),
-  .DSPX_DATA_IN(DSPX_SNES_DATA_IN),
-  .DSPX_DATA_OUT(DSPX_SNES_DATA_OUT),
-  .msu_enable(msu_enable),
-  .bsx_data_ovr(bsx_data_ovr),
-  .srtc_enable(srtc_enable),
-  .dspx_enable(dspx_enable),
-  .dspx_dp_enable(dspx_dp_enable)
-);
-
 parameter MODE_SNES = 1'b0;
 parameter MODE_MCU = 1'b1;
 
-parameter STATE_0    = 14'b00000000000001;
-parameter STATE_1    = 14'b00000000000010;
-parameter STATE_2    = 14'b00000000000100;
-parameter STATE_3    = 14'b00000000001000;
-parameter STATE_4    = 14'b00000000010000;
-parameter STATE_5    = 14'b00000000100000;
-parameter STATE_6    = 14'b00000001000000;
-parameter STATE_7    = 14'b00000010000000;
-parameter STATE_8    = 14'b00000100000000;
-parameter STATE_9    = 14'b00001000000000;
-parameter STATE_10   = 14'b00010000000000;
-parameter STATE_11   = 14'b00100000000000;
-parameter STATE_12   = 14'b01000000000000;
-parameter STATE_IDLE = 14'b10000000000000;
-
-reg [13:0] STATE;
+parameter ST_IDLE         = 18'b000000000000000001;
+parameter ST_SNES_RD_ADDR = 18'b000000000000000010;
+parameter ST_SNES_RD_WAIT = 18'b000000000000000100;
+parameter ST_SNES_RD_END  = 18'b000000000000001000;
+parameter ST_SNES_WR_ADDR = 18'b000000000000010000;
+parameter ST_SNES_WR_WAIT1= 18'b000000000000100000;
+parameter ST_SNES_WR_DATA = 18'b000000000001000000;
+parameter ST_SNES_WR_WAIT2= 18'b000000000010000000;
+parameter ST_SNES_WR_END  = 18'b000000000100000000;
+parameter ST_MCU_RD_ADDR  = 18'b000000001000000000;
+parameter ST_MCU_RD_WAIT  = 18'b000000010000000000;
+parameter ST_MCU_RD_WAIT2 = 18'b000000100000000000;
+parameter ST_MCU_RD_END   = 18'b000001000000000000;
+parameter ST_MCU_WR_ADDR  = 18'b000010000000000000;
+parameter ST_MCU_WR_WAIT  = 18'b000100000000000000;
+parameter ST_MCU_WR_WAIT2 = 18'b001000000000000000;
+parameter ST_MCU_WR_END   = 18'b010000000000000000;
+
+parameter ROM_RD_WAIT = 4'h4;
+parameter ROM_RD_WAIT_MCU = 4'h5;
+parameter ROM_WR_WAIT1 = 4'h2;
+parameter ROM_WR_WAIT2 = 4'h3;
+parameter ROM_WR_WAIT_MCU = 4'h6;
+
+reg [17:0] STATE;
 reg [3:0] STATEIDX;
 
 reg [1:0] CYCLE_RESET;
 reg ROM_WE_MASK;
 reg ROM_OE_MASK;
 
-reg [13:0] ROM_WE_ARRAY [3:0];
-reg [13:0] ROM_OE_ARRAY [3:0];
-
-reg [13:0] SNES_DATA_TO_MEM_ARRAY[1:0];
-reg [13:0] MCU_DATA_TO_MEM_ARRAY[1:0];
-reg [13:0] ROM_DATA_TO_SNES_MEM_ARRAY[1:0];
-reg [13:0] ROM_DATA_TO_MCU_MEM_ARRAY[1:0];
-
-reg [13:0] MODE_ARRAY;
-
 reg SNES_READ_CYCLE;
 reg SNES_WRITE_CYCLE;
 reg MCU_READ_CYCLE;
@@ -489,11 +452,9 @@ reg [3:0] MAPPER_BUF;
 reg SNES_DATABUS_OE_BUF;
 reg SNES_DATABUS_DIR_BUF;
 
-assign MODE = !MCU_OVR ? MODE_MCU : MODE_ARRAY[STATEIDX];
-
 initial begin
    CYCLE_RESET = 2'b0;
-   STATE = STATE_IDLE;
+   STATE = ST_IDLE;
    STATEIDX = 13;
    ROM_WE_MASK = 1'b1;
    ROM_OE_MASK = 1'b1;
@@ -501,132 +462,215 @@ initial begin
    SNES_WRITE_CYCLE = 1'b1;
    MCU_READ_CYCLE = 1'b1;
    MCU_WRITE_CYCLE = 1'b1;
-   MODE_ARRAY = 14'b0_000000_1111111;
+end
 
-   ROM_WE_ARRAY[2'b00] = 14'b1_000000_0000000;
-   ROM_WE_ARRAY[2'b01] = 14'b1_000000_1111111;
-   ROM_WE_ARRAY[2'b10] = 14'b1_111111_0000000;
-   ROM_WE_ARRAY[2'b11] = 14'b1_111111_1111111;
+// falling edge of SNES /RD or /WR marks the beginning of a new cycle
+// SNES READ or WRITE always starts @posedge CLK !!
+// CPU cycle can be 6, 8 or 12 CLKIN cycles so we must satisfy
+// the minimum of 6 SNES cycles to get everything done.
+// we have 24 internal cycles to work with. (CLKIN * 4)
 
-   ROM_OE_ARRAY[2'b00] = 14'b1_111111_1111111;
-   ROM_OE_ARRAY[2'b01] = 14'b1_111111_0000000;
-   ROM_OE_ARRAY[2'b10] = 14'b0_000000_1111111;
-   ROM_OE_ARRAY[2'b11] = 14'b0_000000_0000000;
+assign DSPX_SNES_DATA_IN = SNES_DATA;
+assign SRTC_SNES_DATA_IN = SNES_DATA;
+assign MSU_SNES_DATA_IN = SNES_DATA;
+assign BSX_SNES_DATA_IN = SNES_DATA;
+
+reg [7:0] SNES_DINr;
+reg [7:0] ROM_DOUTr;
+
+assign SNES_DATA = (!SNES_READ) ? (srtc_enable ? SRTC_SNES_DATA_OUT
+                                  :dspx_enable ? DSPX_SNES_DATA_OUT
+											 :dspx_dp_enable ? DSPX_SNES_DATA_OUT
+											 :msu_enable ? MSU_SNES_DATA_OUT
+											 :bsx_data_ovr ? BSX_SNES_DATA_OUT
+                                  :SNES_DINr /*(ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8])*/) : 8'bZ;
+
+reg [3:0] ST_MEM_DELAYr;
+reg MCU_RD_PENDr;
+reg MCU_WR_PENDr;
+reg [23:0] ROM_ADDRr;
+reg NEED_SNES_ADDRr;
+always @(posedge CLK2) begin
+  if(SNES_cycle_end) NEED_SNES_ADDRr <= 1'b1;
+  else if(STATE & (ST_SNES_RD_END | ST_SNES_WR_END)) NEED_SNES_ADDRr <= 1'b0;
+end
 
-   SNES_DATA_TO_MEM_ARRAY[1'b0] = 14'b0_000100_0000000;  // SNES write
-   SNES_DATA_TO_MEM_ARRAY[1'b1] = 14'b0_000000_0000000;  // SNES read
+wire ASSERT_SNES_ADDR = SNES_CPU_CLK & NEED_SNES_ADDRr;
 
-   MCU_DATA_TO_MEM_ARRAY[1'b0] = 14'b1_111111_1111111;  // MCU write
-   MCU_DATA_TO_MEM_ARRAY[1'b1] = 14'b0_000000_0000000;  // MCU read
+assign ROM_ADDR  = (!MCU_OVR) ? MCU_ADDR[23:1] : (ASSERT_SNES_ADDR) ? MAPPED_SNES_ADDR[23:1] : ROM_ADDRr[23:1];
+assign ROM_ADDR0 = (!MCU_OVR) ? MCU_ADDR[0] : (ASSERT_SNES_ADDR) ? MAPPED_SNES_ADDR[0] : ROM_ADDRr[0];
 
-   ROM_DATA_TO_SNES_MEM_ARRAY[1'b0] = 14'b0_000000_0000000;  // SNES write
-   ROM_DATA_TO_SNES_MEM_ARRAY[1'b1] = 14'b0_000010_0000000;  // SNES read
+reg ROM_WEr;
+initial ROM_WEr = 1'b1;
 
-   ROM_DATA_TO_MCU_MEM_ARRAY[1'b0] = 14'b0_000000_0000000;  // MCU write
-   ROM_DATA_TO_MCU_MEM_ARRAY[1'b1] = 14'b0_000000_0000001;  // MCU read
+reg RQ_MCU_RDYr;
+initial RQ_MCU_RDYr = 1'b1;
+assign MCU_RDY = RQ_MCU_RDYr;
 
+always @(posedge CLK2) begin
+  if(MCU_RRQ) begin
+    MCU_RD_PENDr <= 1'b1;
+	 RQ_MCU_RDYr <= 1'b0;
+  end else if(MCU_WRQ) begin
+    MCU_WR_PENDr <= 1'b1;
+	 RQ_MCU_RDYr <= 1'b0;
+  end else if(STATE & (ST_MCU_RD_END | ST_MCU_WR_END)) begin
+    MCU_RD_PENDr <= 1'b0;
+	 MCU_WR_PENDr <= 1'b0;
+	 RQ_MCU_RDYr <= 1'b1;
+  end
 end
 
-// falling edge of SNES /RD or /WR marks the beginning of a new cycle
-// SNES READ or WRITE always starts @posedge CLK !!
-// CPU cycle can be 6, 8 or 12 CLKIN cycles so we must satisfy
-// the minimum of 6 SNES cycles to get everything done.
-// we have 24 internal cycles to work with. (CLKIN * 4)
-
+reg [23:0] SNES_ADDRsr[1:0];
 always @(posedge CLK2) begin
-  CYCLE_RESET <= {CYCLE_RESET[0], SNES_cycle_start};
+  SNES_ADDRsr[0] <= SNES_ADDR;
+  SNES_ADDRsr[1] <= SNES_ADDRsr[0];
 end
+wire SNES_ADDRchg = (SNES_ADDRsr[0] != SNES_ADDRsr[1]);
 
-reg[7:0] STATECNT;
-initial STATECNT = 0;
+reg snes_wr_cycle;
 
 always @(posedge CLK2) begin
-  MCU_READ_CYCLE <= MCU_READ;
-  MCU_WRITE_CYCLE <= MCU_WRITE;
-  if (SNES_cycle_start) begin
-    SNES_READ_CYCLE <= SNES_READ;
-    SNES_WRITE_CYCLE <= SNES_WRITE;
-    STATE <= STATE_0;
-    STATEIDX <= 12;
-    STATECNT <= 0;
+  if(SNES_cycle_start) begin
+    STATE <= ST_SNES_RD_ADDR;
+  end else if(SNES_WR_start) begin
+    STATE <= ST_SNES_WR_ADDR;
   end else begin
-    STATECNT <= STATECNT + 1;
-    case (STATE)
-      STATE_0: begin
-        SNES_WRITE_CYCLE <= SNES_WRITE;
-        STATE <= STATE_1; STATEIDX <= 11;
-      end
-      STATE_1: begin
-        STATE <= STATE_2; STATEIDX <= 10;
-      end
-      STATE_2: begin
-        STATE <= STATE_3; STATEIDX <= 9;
-      end
-      STATE_3: begin
-        STATE <= STATE_4; STATEIDX <= 8;
-      end
-      STATE_4: begin
-        STATE <= STATE_5; STATEIDX <= 7;
-      end
-      STATE_5: begin
-        STATE <= STATE_6; STATEIDX <= 6;
-      end
-      STATE_6: begin
-        STATE <= STATE_7; STATEIDX <= 5;
+    case(STATE)
+	   ST_IDLE: begin
+		  ROM_ADDRr <= MAPPED_SNES_ADDR;
+		  if(MCU_RD_PENDr) STATE <= ST_MCU_RD_ADDR;
+		  else if(MCU_WR_PENDr) STATE <= ST_MCU_WR_ADDR;
+        else STATE <= ST_IDLE;
+		end
+		ST_SNES_RD_ADDR: begin
+		  STATE <= ST_SNES_RD_WAIT;
+		  ST_MEM_DELAYr <= ROM_RD_WAIT;
+		end
+		ST_SNES_RD_WAIT: begin
+		  ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+		  if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_RD_END;
+		  else STATE <= ST_SNES_RD_WAIT;
+		  if(ROM_ADDR0) SNES_DINr <= ROM_DATA[7:0];
+		  else SNES_DINr <= ROM_DATA[15:8];
+		end
+		ST_SNES_RD_END: begin
+		  STATE <= ST_IDLE;
+		  if(ROM_ADDR0) SNES_DINr <= ROM_DATA[7:0];
+		  else SNES_DINr <= ROM_DATA[15:8];
+		end
+      ST_SNES_WR_ADDR: begin
+        ROM_WEr <= (!IS_FLASHWR & !IS_WRITABLE);
+        snes_wr_cycle <= 1'b1;
+		  STATE <= ST_SNES_WR_WAIT1;
+		  ST_MEM_DELAYr <= ROM_WR_WAIT1;
+		end
+		ST_SNES_WR_WAIT1: begin
+		  ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+		  if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_WR_DATA;
+		  else STATE <= ST_SNES_WR_WAIT1;
+		end
+		ST_SNES_WR_DATA: begin
+        ROM_DOUTr <= SNES_DATA;
+		  ST_MEM_DELAYr <= ROM_WR_WAIT2;
+		  STATE <= ST_SNES_WR_WAIT2;
+		end
+      ST_SNES_WR_WAIT2: begin
+		  ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+		  if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_WR_END;
+		  else STATE <= ST_SNES_WR_WAIT2;
+		end
+		ST_SNES_WR_END: begin
+		  STATE <= ST_IDLE;
+		  ROM_WEr <= 1'b1;
+		  snes_wr_cycle <= 1'b0;
+		end
+		ST_MCU_RD_ADDR: begin
+		  ROM_ADDRr <= MCU_ADDR;
+		  STATE <= ST_MCU_RD_WAIT;
+		  ST_MEM_DELAYr <= ROM_RD_WAIT_MCU;
+		end
+		ST_MCU_RD_WAIT: begin
+		  ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+		  if(ST_MEM_DELAYr == 4'h0) begin
+		    STATE <= ST_MCU_RD_WAIT2;
+			 ST_MEM_DELAYr <= 4'h2;
+		  end
+		  else STATE <= ST_MCU_RD_WAIT;
+		  if(ROM_ADDR0) MCU_DINr <= ROM_DATA[7:0];
+		  else MCU_DINr <= ROM_DATA[15:8];
       end
-      STATE_7: begin
-        STATE <= STATE_8; STATEIDX <= 4;
+		ST_MCU_RD_WAIT2: begin
+		  ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+		  if(ST_MEM_DELAYr == 4'h0) begin
+		    STATE <= ST_MCU_RD_END;
+		  end else STATE <= ST_MCU_RD_WAIT2;
+		end
+		ST_MCU_RD_END: begin
+		  STATE <= ST_IDLE;
+		end
+		ST_MCU_WR_ADDR: begin
+		  ROM_ADDRr <= MCU_ADDR;
+		  STATE <= ST_MCU_WR_WAIT;
+		  ST_MEM_DELAYr <= ROM_WR_WAIT_MCU;
+		  ROM_DOUTr <= MCU_DOUT;
+		  ROM_WEr <= 1'b0;
+		end
+		ST_MCU_WR_WAIT: begin
+		  ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+		  if(ST_MEM_DELAYr == 4'h0) begin
+          ROM_WEr <= 1'b1;
+		    STATE <= ST_MCU_WR_WAIT2;
+			 ST_MEM_DELAYr <= 4'h2;
+		  end
+		  else STATE <= ST_MCU_WR_WAIT;
       end
-      STATE_8: begin
-        STATE <= STATE_9; STATEIDX <= 3;
-      end
-      STATE_9: begin
-        STATE <= STATE_10; STATEIDX <= 2;
-      end
-      STATE_10: begin
-        STATE <= STATE_11; STATEIDX <= 1;
-      end
-      STATE_11: begin
-        STATE <= STATE_12; STATEIDX <= 0;
-      end
-      STATE_12: begin
-        STATE <= STATE_IDLE; STATEIDX <= 13;
-      end
-      STATE_IDLE: begin
-        STATE <= STATE_IDLE; STATEIDX <= 13;
-      end
-      default: begin
-        STATE <= STATE_IDLE; STATEIDX <= 13;
-      end
-    endcase
+		ST_MCU_WR_WAIT2: begin
+		  ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+		  if(ST_MEM_DELAYr == 4'h0) begin
+		    STATE <= ST_MCU_WR_END;
+        end else STATE <= ST_MCU_WR_WAIT2;
+		end
+		ST_MCU_WR_END: begin
+		  STATE <= ST_IDLE;
+		end
+
+	 endcase
   end
 end
 
+// wire MCU_RRQ;
+// wire MCU_WRQ;
+// reg ROM_OEr;
+assign ROM_DATA[7:0] = ROM_ADDR0
+                       ?(!MCU_OVR ? (!MCU_WRITE ? MCU_DOUT : 8'bZ)
+                                  : (!ROM_WE ? ROM_DOUTr : 8'bZ)
+                        )
+                       :8'bZ;
+
+assign ROM_DATA[15:8] = ROM_ADDR0 ? 8'bZ
+                        :(!MCU_OVR ? (!MCU_WRITE ? MCU_DOUT : 8'bZ)
+                                  : (!ROM_WE ? ROM_DOUTr : 8'bZ)
+                         );
+                         
 // When in MCU mode, enable SRAM_WE according to MCU programming
 // else enable SRAM_WE according to state&cycle
 assign ROM_WE = !MCU_OVR
                 ?MCU_WRITE
-                :((!IS_FLASHWR & !IS_WRITABLE & !MODE)
-                  | ROM_WE_ARRAY[{SNES_WRITE_CYCLE, MCU_WRITE_CYCLE}][STATEIDX]);
+                :ROM_WEr | (ASSERT_SNES_ADDR & ~snes_wr_cycle); /* & !MODE)
+                  | ROM_WE_ARRAY[{SNES_WRITE_CYCLE, MCU_WRITE_CYCLE}][STATEIDX])*/
 
 // When in MCU mode, enable SRAM_OE whenever not writing
 // else enable SRAM_OE according to state&cycle
-assign ROM_OE = !MCU_OVR
-                ?MCU_READ
-                :ROM_OE_ARRAY[{SNES_WRITE_CYCLE, MCU_WRITE_CYCLE}][STATEIDX];
+assign ROM_OE = 1'b0; //!MCU_OVR
+                //?MCU_READ
+                //:ROM_OE_ARRAY[{SNES_WRITE_CYCLE, MCU_WRITE_CYCLE}][STATEIDX];
 
 assign ROM_CE = 1'b0; // !MCU_OVR ? (MCU_READ & MCU_WRITE) : ROM_SEL;
 
 assign ROM_BHE = !ROM_WE ? ROM_ADDR0 : 1'b0;
 assign ROM_BLE = !ROM_WE ? !ROM_ADDR0 : 1'b0;
 
-//assign SRAM_BHE = SRAM_ADDR0;
-//assign SRAM_BLE = ~SRAM_ADDR0;
-
-// dumb version
-//assign SRAM_OE = !MCU_ENA ? MCU_READ : SNES_READs;
-//assign SRAM_WE = !MCU_ENA ? MCU_WRITE : 1'b1;
-
 //assign SNES_DATABUS_OE = (!IS_SAVERAM & SNES_CS) | (SNES_READ & SNES_WRITE);
 assign SNES_DATABUS_OE = (dspx_enable | dspx_dp_enable) ? 1'b0 :
                          msu_enable ? 1'b0 :
@@ -639,15 +683,9 @@ assign SNES_DATABUS_OE = (dspx_enable | dspx_dp_enable) ? 1'b0 :
 
 assign SNES_DATABUS_DIR = !SNES_READ ? 1'b1 : 1'b0;
 
-assign SNES_DATA_TO_MEM = SNES_DATA_TO_MEM_ARRAY[SNES_WRITE_CYCLE][STATEIDX];
-assign MCU_DATA_TO_MEM = MCU_DATA_TO_MEM_ARRAY[MCU_WRITE_CYCLE][STATEIDX];
-
-assign ROM_DATA_TO_SNES_MEM = ROM_DATA_TO_SNES_MEM_ARRAY[SNES_WRITE_CYCLE][STATEIDX];
-assign ROM_DATA_TO_MCU_MEM = ROM_DATA_TO_MCU_MEM_ARRAY[MCU_WRITE_CYCLE][STATEIDX];
-
-assign SNES_READ_CYCLEw = SNES_READ_CYCLE;
-assign SNES_WRITE_CYCLEw = SNES_WRITE_CYCLE;
 assign IRQ_DIR = 1'b0;
 assign SNES_IRQ = 1'bZ;
 
+assign p113_out = ROM_WE;
+
 endmodule

+ 95 - 74
verilog/sd2snes/mcu_cmd.v

@@ -26,8 +26,10 @@ module mcu_cmd(
   input [7:0] param_data,
   output [3:0] mcu_mapper,
   output [3:0] mcu_sram_size,
-  output mcu_read,
+  output mcu_rrq,
   output mcu_write,
+  output mcu_wrq,
+  input mcu_rq_rdy,
   output [7:0] mcu_data_out,
   input [7:0] mcu_data_in,
   output [7:0] spi_data_out,
@@ -147,6 +149,7 @@ reg [31:0] SNES_SYSCLK_FREQ_BUF;
 reg [7:0] MCU_DATA_OUT_BUF;
 reg [7:0] MCU_DATA_IN_BUF;
 reg [1:0] mcu_nextaddr_buf;
+reg mcu_nextaddr_r;
 reg SD_DMA_NEXTADDRr;
 always @(posedge clk) SD_DMA_NEXTADDRr <= SD_DMA_NEXTADDR;
 
@@ -206,46 +209,12 @@ always @(posedge clk) begin
         SD_DMA_PARTIALr <= cmd_data[2];
       end
       4'h8: SD_DMA_TGTr <= 2'b00;
-      4'h9: SD_DMA_TGTr <= cmd_data[1:0];
+      4'h9: SD_DMA_TGTr <= cmd_data[1:0]; // not implemented
 //      4'hE:
 //      select memory unit
     endcase
   end else if (param_ready) begin
     casex (cmd_data[7:0])
-      8'h0x:
-        case (cmd_data[1:0])
-          2'b01: begin
-            case (spi_byte_cnt)
-              32'h2: begin
-                DAC_ADDR_OUT_BUF[10:8] <= param_data[2:0];
-                DAC_ADDR_OUT_BUF[7:0] <= 8'b0;
-              end
-              32'h3:
-                DAC_ADDR_OUT_BUF[7:0] <= param_data;
-            endcase
-          end
-          2'b10: begin
-            case (spi_byte_cnt)
-              32'h2: begin
-                MSU_ADDR_OUT_BUF[13:8] <= param_data[5:0];
-                MSU_ADDR_OUT_BUF[7:0] <= 8'b0;
-              end
-              32'h3:
-                MSU_ADDR_OUT_BUF[7:0] <= param_data;
-            endcase
-          end
-          default:
-            case (spi_byte_cnt)
-              32'h2: begin
-                ADDR_OUT_BUF[23:16] <= param_data;
-                ADDR_OUT_BUF[15:0] <= 16'b0;
-              end
-              32'h3:
-                ADDR_OUT_BUF[15:8] <= param_data;
-              32'h4:
-                ADDR_OUT_BUF[7:0] <= param_data;
-            endcase
-        endcase
       8'h1x:
         case (spi_byte_cnt)
           32'h2:
@@ -403,10 +372,46 @@ always @(posedge clk) begin
         featurebits_out <= param_data[7:0];
     endcase
   end
+end
 
-  if (SD_DMA_NEXTADDR | (mcu_nextaddr & (cmd_data[7:5] == 3'h4)
+always @(posedge clk) begin
+  if(param_ready && cmd_data[7:4] == 4'h0)  begin
+    case (cmd_data[1:0])
+	 2'b01: begin
+		case (spi_byte_cnt)
+		  32'h2: begin
+			 DAC_ADDR_OUT_BUF[10:8] <= param_data[2:0];
+			 DAC_ADDR_OUT_BUF[7:0] <= 8'b0;
+		  end
+		  32'h3:
+			 DAC_ADDR_OUT_BUF[7:0] <= param_data;
+		endcase
+	 end
+	 2'b10: begin
+		case (spi_byte_cnt)
+		  32'h2: begin
+			 MSU_ADDR_OUT_BUF[13:8] <= param_data[5:0];
+			 MSU_ADDR_OUT_BUF[7:0] <= 8'b0;
+		  end
+		  32'h3:
+			 MSU_ADDR_OUT_BUF[7:0] <= param_data;
+		endcase
+	 end
+	 default:
+		case (spi_byte_cnt)
+		  32'h2: begin
+			 ADDR_OUT_BUF[23:16] <= param_data;
+			 ADDR_OUT_BUF[15:0] <= 16'b0;
+		  end
+		  32'h3:
+			 ADDR_OUT_BUF[15:8] <= param_data;
+		  32'h4:
+			 ADDR_OUT_BUF[7:0] <= param_data;
+		endcase
+	 endcase
+  end else if (SD_DMA_NEXTADDR | (mcu_nextaddr & (cmd_data[7:5] == 3'h4)
                          && (cmd_data[3])
-                         && (spi_byte_cnt > (32'h1+cmd_data[4])))
+                         && (spi_byte_cnt >= (32'h1+cmd_data[4])))
      )
   begin
     case (SD_DMA_TGTr)
@@ -419,7 +424,9 @@ end
 
 // value fetch during last SPI bit
 always @(posedge clk) begin
-  if (spi_bit_cnt == 3'h7) begin
+  if (cmd_data[7:4] == 4'h8 && mcu_nextaddr_buf == 2'b01)
+    MCU_DATA_IN_BUF <= mcu_data_in;
+  else if (spi_bit_cnt == 3'h7) begin
     if (cmd_data[7:0] == 8'hF0)
       MCU_DATA_IN_BUF <= 8'hA5;
     else if (cmd_data[7:0] == 8'hF1)
@@ -464,60 +471,74 @@ always @(posedge clk) begin
       endcase
     else if (cmd_data[7:0] == 8'hFF)
       MCU_DATA_IN_BUF <= param_data;
-    else if (cmd_data[7:4] == 4'h8)
-      MCU_DATA_IN_BUF <= mcu_data_in;
-    else
-      MCU_DATA_IN_BUF <= cmd_data;
   end
 end
 
 // nextaddr pulse generation
 always @(posedge clk) begin
-  if (spi_bit_cnt == 3'h0)
-    mcu_nextaddr_buf <= {mcu_nextaddr_buf[0], 1'b1};
-  else
-    mcu_nextaddr_buf <= {mcu_nextaddr_buf[0], 1'b0};
+  mcu_nextaddr_buf <= {mcu_nextaddr_buf[0], mcu_rq_rdy};
 end
 
+parameter ST_RRQ = 4'b0001;
+parameter ST_WAIT = 4'b0010;
+parameter ST_NEXT = 4'b0100;
+parameter ST_IDLE = 4'b1000;
+
+reg [3:0] rrq_state;
+initial rrq_state = ST_IDLE;
+reg [2:0] rrq_wait;
+reg mcu_rrq_r;
+
+reg [3:0] wrq_state;
+initial wrq_state = ST_IDLE;
+reg [2:0] wrq_wait;
+reg mcu_wrq_r;
 
-// r/w pulse
 always @(posedge clk) begin
-  if ((spi_bit_cnt == 3'h1
-       || spi_bit_cnt == 3'h2
-       || spi_bit_cnt == 3'h3
-      )
-      & (cmd_data[7:4] == 4'h9)
-      & (spi_byte_cnt > 32'h1)
-     )
-    MCU_WRITE_BUF <= 1'b0;
-  else
-    MCU_WRITE_BUF <= 1'b1;
-
-// Read pulse is 3 spi cycles to ensure that the value
-// is ready in the 2nd cycle in MCU master mode
-  if ((spi_bit_cnt == 3'h5
-       || spi_bit_cnt == 3'h6
-       || spi_bit_cnt == 3'h7
-      )
-      & (cmd_data[7:4] == 4'h8)
-      & (spi_byte_cnt > 32'h0)
-     )
-    MCU_READ_BUF <= 1'b0;
-  else
-    MCU_READ_BUF <= 1'b1;
+  case(rrq_state)
+    ST_IDLE: begin
+	   mcu_nextaddr_r <= 1'b0;
+	   if((param_ready | cmd_ready) && cmd_data[7:4] == 4'h8) begin
+		  mcu_rrq_r <= 1'b1;
+		  rrq_state <= ST_RRQ;
+		end else
+		  rrq_state <= ST_IDLE;
+	 end
+	 ST_RRQ: begin
+	   mcu_rrq_r <= 1'b0;
+		rrq_state <= ST_IDLE;
+	 end
+  endcase
+end
+
+always @(posedge clk) begin
+  case(wrq_state)
+    ST_IDLE: begin
+	   mcu_nextaddr_r <= 1'b0;
+	   if(param_ready && cmd_data[7:4] == 4'h9) begin
+		  mcu_wrq_r <= 1'b1;
+		  wrq_state <= ST_RRQ;
+		end else
+		  wrq_state <= ST_IDLE;
+	 end
+	 ST_RRQ: begin
+	   mcu_wrq_r <= 1'b0;
+		wrq_state <= ST_IDLE;
+	 end
+  endcase
 end
 
 // trigger for nextaddr
 assign mcu_nextaddr = mcu_nextaddr_buf == 2'b01;
 
-assign mcu_read = MCU_READ_BUF;
-
+assign mcu_rrq = mcu_rrq_r;
+assign mcu_wrq = mcu_wrq_r;
 assign mcu_write = SD_DMA_STATUS
                    ?(SD_DMA_TGTr == 2'b00
                      ?SD_DMA_SRAM_WE
                      :1'b1
                     )
-                   : MCU_WRITE_BUF;
+                   : 1'b1;
 
 assign addr_out = ADDR_OUT_BUF;
 assign dac_addr_out = DAC_ADDR_OUT_BUF;