module gd_emu (mclock, gd_data, gd_addr, gd_rd_n, gd_wr_n, gd_dma_rq, gd_dma_ack, gd_int_rq, gd_iordy, gd_cs, gd_rst, // GD-Rom stuff. gd_cdlrck, gd_cdda_clk, gd_cdbck, // CDDA stuff (missing CDSD atm). cf_data, cf_addr, cf_rd_n, cf_wr_n, cf_dma_rq, cf_dma_ack, // Onboard IDE / CF Card. led); input wire mclock; // Master clock input reg [15:0] cf_data_write; inout [15:0] cf_data; // Hard drive / CF card data port (bidir). assign cf_data = !cf_wr_n ? cf_data_write : 16'bz; // Output data to IDE when "cf_wr_n" is low. // (force to High-Z if "cf_rd_n" is low too). output reg [2:0] cf_addr; // IDE address bits. // output reg [1:0] cf_cs; // IDE "Chip-Select" bits. NOTE: The MSB is labelled CS3 on many specs! // (Note: CS pins are hard-tied on Nemesis board. OzOnE). output reg cf_rd_n; // IDE Read (active low). output reg cf_wr_n; // IDE Write (active low). input cf_dma_rq; // IDE DMA ReQuest input. output reg cf_dma_ack; // IDE DMA ACKnowledge output. reg [23:0] cf_hold_time; // (for holding Read or Write pin state for a set time). // reg gd_rd_n_1, gd_rd_n_2; // reg gd_wr_n_1, gd_wr_n_2; // reg gd_rst_1, gd_rst_2; reg [15:0] gd_data_write; inout wire [15:0] gd_data/* synthesis noprune */; assign gd_data = 16'bz; // !! GD-Rom drive Spy mode !! // inout wire gd_data = !gd_wr_n ? gd_data_write : 16'bz; // !! GD-Rom emu mode !! reg gd_wr_n_1; // Flip-flops for detecting edges. reg gd_wr_n_2; reg gd_rd_n_1; reg gd_rd_n_2; wire gd_wr_rising = gd_wr_n_1 & ~gd_wr_n_2; wire gd_rd_rising = gd_rd_n_1 & ~gd_rd_n_2; input wire [2:0] gd_addr/* synthesis noprune */; // !! GD-Rom drive Spy mode !! input wire gd_rd_n/* synthesis noprune */; input wire gd_wr_n/* synthesis noprune */; input wire gd_dma_rq/* synthesis noprune */; input wire gd_dma_ack/* synthesis noprune */; input wire gd_int_rq/* synthesis noprune */; input wire gd_iordy/* synthesis noprune */; input wire [1:0] gd_cs/* synthesis noprune */; input wire gd_rst/* synthesis noprune */; input wire gd_cdlrck/* synthesis noprune */; input wire gd_cdda_clk/* synthesis noprune */; input wire gd_cdbck/* synthesis noprune */; output wire led = !gd_dma_ack; reg [7:0] cf_sec_count; reg [31:0] cf_lba; wire [7:0] cf_lba3 = cf_lba[31:24] | 8'hE0; // Need to BITWISE OR the top LBA byte with 0xE0 (use 0xE0 mask to select MASTER drive). wire [7:0] cf_lba2 = cf_lba[23:16]; wire [7:0] cf_lba1 = cf_lba[15:8]; wire [7:0] cf_lba0 = cf_lba[7:0]; reg [7:0] cf_wordcount; reg [9:0] gd_state; reg [15:0] ata_cmd; reg [15:0] gd_ata_cmd; reg [15:0] packet_1/* synthesis noprune */; reg [15:0] packet_2/* synthesis noprune */; reg [15:0] packet_3/* synthesis noprune */; reg [15:0] packet_4/* synthesis noprune */; reg [15:0] packet_5/* synthesis noprune */; reg [15:0] packet_6/* synthesis noprune */; wire [7:0] packet_0b = packet_1[7:0]/* synthesis noprune */; wire [7:0] packet_1b = packet_1[15:8]/* synthesis noprune */; wire [7:0] packet_2b = packet_2[7:0]/* synthesis noprune */; wire [7:0] packet_3b = packet_2[15:8]/* synthesis noprune */; wire [7:0] packet_4b = packet_3[7:0]/* synthesis noprune */; wire [7:0] packet_5b = packet_3[15:8]/* synthesis noprune */; wire [7:0] packet_6b = packet_4[7:0]/* synthesis noprune */; wire [7:0] packet_7b = packet_4[15:8]/* synthesis noprune */; wire [7:0] packet_8b = packet_5[7:0]/* synthesis noprune */; wire [7:0] packet_9b = packet_5[15:8]/* synthesis noprune */; wire [7:0] packet_10b = packet_6[7:0]/* synthesis noprune */; wire [7:0] packet_11b = packet_6[15:8]/* synthesis noprune */; reg [11:0] gd_sector_type/* synthesis noprune */; // No point wasting bits! (OzOnE). reg [31:0] gd_start_sector/* synthesis noprune */; reg [31:0] gd_sector_count/* synthesis noprune */; reg [3:0] gd_status; // Only using nibble! reg [3:0] gd_discformat; // Only using nibble! reg [3:0] cdda_repeats; // Only using nibble! reg [23:0] cdda_curraddr; // Using full three bytes together (need to part select when needed). OzOnE. reg [7:0] gd_stat [0:9]; // Array of bytes for sending status back. reg [9:0] reply_rom_addr; reg toc_density/* synthesis noprune */; reg [15:0] toc_bytes/* synthesis noprune */; reg [15:0] toc_byte_count/* synthesis noprune */; // ATA Commands parameter ATA_NOP = 8'h00; parameter ATA_SOFT_RESET = 8'h08; parameter ATA_EXEC_DIAG = 8'h90; parameter ATA_SPI_PACKET = 8'hA0; parameter ATA_IDENTIFY_DEV = 8'hA1; parameter ATA_SET_FEATURES = 8'hEF; // SPI Packet Commands parameter SPI_TEST_UNIT = 8'h00; parameter SPI_REQ_STAT = 8'h10; parameter SPI_REQ_MODE = 8'h11; parameter SPI_SET_MODE = 8'h12; parameter SPI_REQ_ERROR = 8'h13; parameter SPI_GET_TOC = 8'h14; parameter SPI_REQ_SES = 8'h15; parameter SPI_CD_OPEN = 8'h16; parameter SPI_CD_PLAY = 8'h20; parameter SPI_CD_SEEK = 8'h21; parameter SPI_CD_SCAN = 8'h22; parameter SPI_CD_READ = 8'h30; parameter SPI_CD_READ2 = 8'h31; parameter SPI_GET_SCD = 8'h40; initial begin gd_state <= 10'd0; ata_cmd <= 8'h0; // led <= 1'b0; reply_rom_addr <= 10'h00; cf_addr <= 3'h00; // Zero IDE address (not really necessary). // cf_cs <= 2'b10; // IDE CS3 = HIGH, IDE CS1 = LOW (tied on Nemesis board anyway) cf_dma_ack <= 1'b1; // De-assert DMA ACKnowledge (active low). cf_rd_n <= 1'b1; // De-assert IDE Read at power up! cf_wr_n <= 1'b1; // De-assert IDE WRite at power up! end always @(posedge mclock) begin gd_wr_n_1 <= gd_wr_n; gd_wr_n_2 <= gd_wr_n_1; gd_rd_n_1 <= gd_rd_n; gd_rd_n_2 <= gd_rd_n_1; case (gd_state) 0: if (gd_addr == 3'd7 && gd_wr_rising) begin // If in COMMAND reg on RISING edge of "gd_wr_n"... gd_ata_cmd <= gd_data; gd_state <= 10'd2; end // 1: gd_state <= 10'd2; // Spare. 2: begin case (gd_ata_cmd[7:0]) ATA_NOP: gd_state <= 10'd0; // Unhandled? (as yet). OzOnE ATA_SOFT_RESET: gd_state <= 10'd0; // Unhandled (as yet). OzOnE ATA_EXEC_DIAG: gd_state <= 10'd0; // Unhandled (as yet) - not implemented on nullDC anyway. OzOnE ATA_SPI_PACKET: // PACKET command! (Sega type, duh!) if (gd_addr == 3'd0 && gd_wr_rising) begin // If in DATA reg on RISING edge of "gd_wr_n"... packet_1 <= gd_data; // Grab packet WORD 1. gd_state <= 10'd3; end ATA_IDENTIFY_DEV: gd_state <= 10'd0; // Unhandled (as yet) - don't think it ever gets called by my DC BIOS? OzOnE ATA_SET_FEATURES: gd_state <= 10'd0; // Unhandled (as yet). OzOnE default: gd_state <= 10'd0; // Unhandled ATA command, back to idle. endcase end 3: if (gd_addr == 3'd0 && gd_wr_rising) begin packet_2 <= gd_data; // Grab packet WORD 2. gd_state <= 10'd4; end 4: if (gd_addr == 3'd0 && gd_wr_rising) begin packet_3 <= gd_data; // Grab packet WORD 3. gd_state <= 10'd5; end 5: if (gd_addr == 3'd0 && gd_wr_rising) begin packet_4 <= gd_data; // Grab packet WORD 4. gd_state <= 10'd6; end 6: if (gd_addr == 3'd0 && gd_wr_rising) begin packet_5 <= gd_data[7:0]; // Grab packet WORD 5. gd_state <= 10'd7; end 7: if (gd_addr == 3'd0 && gd_wr_rising) begin packet_6 <= gd_data[7:0]; // Grab packet WORD 6. gd_state <= 10'd8; end 8: begin // ** Process SPI (Sega) command packet ** case (packet_0b) // <- (byte addressing starts at zero!) SPI_TEST_UNIT: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_REQ_STAT: begin gd_stat[0] <= {4'b0, gd_status}; // Status is low nibble (force top bits to zero). gd_stat[1] <= {gd_discformat, cdda_repeats}; gd_stat[2] <= 8'h04; // ? This is what nullDC does? gd_stat[3] <= 8'd02; // TNO gd_stat[4] <= 8'd00; // X gd_stat[5] <= cdda_curraddr[23:16]; // Current FAD (MSB?) gd_stat[6] <= cdda_curraddr[15:8]; // Current FAD gd_stat[7] <= cdda_curraddr[7:0]; // Current FAD (LSB?) gd_stat[8] <= 8'd00; // Max Read Error Retry Times. gd_stat[9] <= 8'd00; // All bits zeros. // *** TODO - SORT OUT PIO WORD OUTPUT !! *** gd_state <= 10'd0; end SPI_REQ_MODE: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_SET_MODE: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_REQ_ERROR: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_GET_TOC: begin toc_density <= packet_1b[0]; // Request TOC from Single-density area (0) or Double-density area (1). toc_bytes <= {packet_3b, packet_4b}; // Allocation length in bytes, usually 0x198 (408 bytes). gd_state <= 10'd0; end 8'h70: gd_state <= 10'd0; // Unhandled (as yet). OzOnE 8'h71: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_REQ_SES: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_CD_OPEN: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_CD_PLAY: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_CD_SEEK: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_CD_SCAN: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_CD_READ: begin if (packet_1b[7]==1 && packet_1b[6]==1 && packet_1b[5]==1 && packet_1b[3:1]==3 && packet_1b[4]==0) gd_sector_type <= 12'd2340; else gd_sector_type <= 12'd2048; if (packet_1b[0]) begin // If "parameter type" == 1 (MSF)... gd_start_sector <= (packet_2b*60*75<<16) | (packet_3b*75<<8) | (packet_4b[2]); end else gd_start_sector <= (packet_2b<<16) | (packet_3b<<8) | (packet_4b); gd_sector_count = (packet_8b<<16) | (packet_9b<<8) | (packet_10b); gd_state <= 10'd0; end SPI_CD_READ2: gd_state <= 10'd0; // Unhandled (as yet). OzOnE SPI_GET_SCD: gd_state <= 10'd0; // Unhandled (as yet). OzOnE default: gd_state <= 10'd0; // Unhandled SPI command, back to idle. endcase end default: gd_state <= 10'd0; // Shouldn't ever get a wrong state here, but just in case. endcase end wire [15:0] reply_rom_data; reply_rom reply_rom_inst ( .address ( reply_rom_addr ), .clock ( mclock ), .q ( reply_rom_data ) ); endmodule