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