/* * JR-IDE Project * - (c) 2017 Alan Hightower * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ `define VERSION_MAJOR 8'd1 `define VERSION_MINOR 8'd8 module datafifo ( input rst, input wclk, input we, input [15:0] wdata, input rclk, input re, output [15:0] rdata ); reg [15:0] mem[1023:0]; reg [9:0] waddr; reg [9:0] raddr; reg [15:0] data; always @(posedge wclk) begin if (rst) begin waddr <= 9'b0000000000; end else if (we) begin waddr <= waddr + 1; mem[waddr] <= wdata[15:0]; end end always @(posedge rclk) begin if (rst) begin raddr <= 9'b0000000000; end else if (re) begin raddr <= raddr + 1; end data <= mem[raddr]; end assign rdata = data; endmodule module bridge_top ( output sys_LED, // Local LED for activity input sys_REF, // 20 MHz reference input pad_RSTn, // IDE interface inout [15:0] ide_D, // Data bus input [2:0] ide_A, // Address bus input [1:0] ide_CSn, // Chip selects input ide_RDn, // Read strobe input ide_WRn, // Write strobe input ide_RSTn, // Reset output ide_IRQen, // IRQ enable output ide_IRQout, // IRQ level output ide_DASP, // Disk activity output ide_OEn, // data bus enable output ide_DIR, // data bus direction // Raspberry PI input pi_RX, // BCM15 : console receive output pi_TX, // BCM14 : console transmit input spi_CSn, // BCM8 input spi_CLK, // BCM11 input spi_MOSI, // BCM10 output spi_MISO, // BCM9 output pi_IRQn, // BCM24 (gpio read 5) // FTDI serial cable output debug_TX, // input debug_RX ); // No PLL in the 100-pin package. Use external oscillator localparam CLOCK_REF = 20000000; /* wire pll_LOCK; wire pll_CLK; SB_PLL40_CORE #( .FEEDBACK_PATH ("SIMPLE"), .DIVR (4'b0000), // DIVR = 0 .DIVF (7'b0101111), // DIVF = 47 / F_VCO = 960 MHz .DIVQ (3'b101), // DIVQ = 5 .FILTER_RANGE (3'b010) // FILTER_RANGE = 2 ) uut ( .LOCK (pll_LOCK), .RESETB (1'b1), .BYPASS (1'b0), .REFERENCECLK (sys_REF), // 20 MHz .PLLOUTCORE (pll_CLK) // 30 MHz ); */ wire ide_CLK; SB_GB clock_buffer ( .USER_SIGNAL_TO_GLOBAL_BUFFER (sys_REF),//(pll_CLK), .GLOBAL_BUFFER_OUTPUT (ide_CLK) ); wire sys_RSTn_in; SB_IO #( .PIN_TYPE(6'b 0000_01), // input only .PULLUP(1'b 1) // Pull-up enabled ) reset_PAD ( .PACKAGE_PIN(pad_RSTn), .OUTPUT_ENABLE(), .D_OUT_0(), .D_IN_0(sys_RSTn_in) ); wire sys_RSTn; SB_GB reset_buffer ( .USER_SIGNAL_TO_GLOBAL_BUFFER (sys_RSTn_in),//(pll_LOCK), .GLOBAL_BUFFER_OUTPUT (sys_RSTn) ); // IDE bi-directional bus control reg data_dir; reg data_en; assign ide_DIR = data_dir; assign ide_OEn = ~data_en; wire [15:0] ide_DOE = {16{(data_en & data_dir)}}; wire [15:0] ide_DIN; reg [15:0] ide_DAT; SB_IO #( .PIN_TYPE(6'b 1010_01), // input + tri-state output .PULLUP(1'b 1) // Pull-up enabled ) ide_PAD [15:0] ( .PACKAGE_PIN(ide_D), .OUTPUT_ENABLE(ide_DOE), .D_OUT_0(ide_DAT), .D_IN_0(ide_DIN) ); // Synchronize control strobes from IDE bus reg ide_RD; reg ide_WR; reg ide_CSA; reg ide_CSB; reg ide_CS; always @(posedge ide_CLK) begin ide_RD <= ~ide_RDn; ide_WR <= ~ide_WRn; ide_CSA <= ~ide_CSn[0]; ide_CSB <= ~ide_CSn[1]; ide_CS <= ~ide_CSn[0] | ~ide_CSn[1]; end /* * Serial data from the Pi console gets directly * connected to the debug output pin. It is also * connected to a UART/RX block which feeds a FIFO * to the Pi. This is so a console utility can * service the port on the connected IDE host. */ assign debug_TX = pi_RX; // temporary assign pi_TX = debug_RX; // ********* ATAPI REGISTER FILE ********* /* * Historcally the IDE register file came from the Western * Digital WD1010 Hard Drive Controller ASIC. Refer to it's * data sheet if you want a trip down memory lane on how we * arrived here. */ /* CS0:1 - [R] Error register * - bit 7: BBK - Set if bad block detected * - bit 6: UNC - Set if uncorrectable CRC error * - bit 5: MC - Set if media changed * - bit 4: IDNF - Sector not found * - bit 3: MCR - Media changed requested (hit eject button) * - bit 2: ABRT - Aborted command * - bit 1: TK0NF - Track 0 not found * - bit 0: AMNF - Address mark not found */ reg ireg_IDNF; // CS0:A1:b4 reg ireg_ABRT; // CS0:A1:b2 wire [7:0] ireg_ERR = { 3'b000, ireg_IDNF, 1'b0, ireg_ABRT, 2'b00 }; // CS0:1 - [W] Feature register (command argument) // Historically - write precompensation cylinder / 4 reg [7:0] ireg_FEAT; // CS0:2 - [R/W] Number of sectors to be transfered (zero = 256) reg [7:0] ireg_SECZ; // CS0:3 - [R/W] Starting sector number (LBA byte 0) reg [7:0] ireg_SECN; // CS0:4 - [R/W] Cylinder number low (or LBA byte 1) reg [7:0] ireg_CYLL; // CS0:5 - [R/W] Cylinder number high (or LBA byte 2) reg [7:0] ireg_CYLH; /* CS0:6 - [R/W] Drive/head register * - bit 7: EXT (obsolete - always 1) Extension bit * When 0, append CRC data to sector data * - bit 6: 1 = LBA mode, 0 = CHS mode * - bit 5: (obsolete - always 1) Sector size * Combination w/ bit 6: 128, 256, (512), 1024 * - bit 4: 0 = master, 1 = slave * - bit 3: HS3 head bit 3 (or LBA bit 27) * - bit 2: HS2 head bit 2 (or LBA bit 26) * - bit 1: HS1 head bit 1 (or LBA bit 25) * - bit 0: HS0 head bit 0 (or LBA bit 24) */ reg ireg_LBA; // CS0:A6:b6 reg ireg_SLAVE; // CS0:A6:b4 reg [3:0] ireg_HEAD; // CS0:A6:b3-0 wire [7:0] ireg_DRVH = { 1'b1, ireg_LBA, 1'b1, ireg_SLAVE, ireg_HEAD }; /* CS0:7 - [R] Status register * - bit 7: BSY - Busy * - bit 6: DRDY - Drive ready * - bit 5: DF - Drive fault * - bit 4: DSC - Drive seek complete * - bit 3: DRQ - Data Request * - bit 2: CORR - Correctable read error occured * - bit 1: IDX - Index mark under read head * - bit 0: ERR - If any bit in error register is set */ reg ireg_BSY = 1'b0; // CS0:A7:b7 reg ireg_DRDY = 1'b0; // CS0:A7:b6 reg ireg_DF = 1'b0; // CS0:A7:b5 reg ireg_DSC = 1'b0; // CS0:A7:b4 wire ireg_DRQ; // CS0:A7:b3 wire [7:0] ireg_STS = { ireg_BSY, ireg_DRDY, ireg_DF, ireg_DSC, ireg_DRQ, 2'b00, ireg_IDNF | ireg_ABRT }; // CS0:7 - [W] Command register reg [7:0] ireg_CMD = 8'h00; /* CS1:6 - [W] Device control register * - bit 7: HOB - High order byte (48-bit LBA) * - bit 6: reserved * - bit 5: reserved * - bit 4: reserved * - bit 3: reserved * - bit 2: SRST - Host software reset * - bit 1: IENn - Interrupt enable * - bit 0: zero */ reg ireg_SRST = 1'b0; // CS1:A6:b2 reg ireg_IENn = 1'b1; // CS1:A6:b1 wire [7:0] ireg_DCTL = { 5'b00000, ireg_SRST, ireg_IENn, 1'b0 }; // ********* SUPPORT REGISTER FILE ********* reg [7:0] ireg_SECR = 8'h00; // Byte remainder of transfer size reg ireg_IRQACT = 1'b0; // Wether the IRQ driver is enabled atm reg ireg_IRQOUT = 1'b0; // Input state of the IRQ driver reg ireg_IRQPIn = 1'b0; // IRQ to RPi - pending reg ireg_SRSTP = 1'b1; // Reset pending reg ireg_EMUX = 1'b0; // Error reg mux control reg ireg_FRST = 1'b0; // FIFO reset strobe `define DRQ_MODE_OFF 2'b00 // Static value 0 `define DRQ_MODE_ON 2'b01 // Static value 1 `define DRQ_MODE_READSEC 2'b10 // IFIFO >= 256 words `define DRQ_MODE_WRITESEC 2'b11 // OFIFO >= 256 words reg [1:0] ireg_DRQm = `DRQ_MODE_OFF; // Data request mux mode reg [11:0] ififo_CNT = 12'h000; // Total words in PI->CPLD FIFO reg [11:0] ofifo_CNT = 12'h400; // Total words available in CPLD->PI FIFO wire [15:0] ififo_OUT; // Forward dec for IFIFO output (unreg) wire [15:0] ofifo_OUT; // Forward dec for OFIFO output (unreg) /* * Change the behaviour of the DRQ signal to the host * based on a) the transfer mode we are currently in, and * b) the level of the FIFOs. */ assign ireg_DRQ = (ireg_DRQm == `DRQ_MODE_ON) ? 1'b1 : (ireg_DRQm == `DRQ_MODE_READSEC) ? |ififo_CNT : (ireg_DRQm == `DRQ_MODE_WRITESEC) ? |ofifo_CNT : 1'b0; /* * I am not using the normal Lattice FIFO E/F/AE/AF flags as * they do not propagate at controllable atomic points. * For example, a 'real' IDE device will add 256 words to the * read data availability when a block is transfered in from * storage and ready to move out the data register. Once * the first word is available, all words are available. It * has IORDY to help. We don't here. * * If a SPI transfer started filling the FIFO, ~E or ~AE * could be affected before we have enough of the 256 words * a host could transfer before looking at the DRQ line again. * The Lattice FIFO has controllable high and low water marks, * however they are static and I'd rather have finer control * over how thresholds are managed going forward. During * a register transfer in, an adjustment value is applied by * the PI giving it complete control over how and how much the * flags are affected at any given time. * * Using the high and low watermark feature of Lattice FIFO * flags could be an option. However there has to be more * state glue logic added and the continuous presence of a * stable clock on both sides - not possible with SPI. * Keeping control on the PI is just simpler and works better. */ // ********* OUT-GOING REGISTER DATA FORMAT TO THE PI ********* wire [111:0] spi_REGSOUT = { // 16-bit flags - LE byte 0 ireg_DRDY, // 7: STS: Drive ready ireg_DF, // 6: STS: Drive fault ireg_DSC, // 5: STS: Drive seek complete ireg_DRQm, // 4-3: STS: Data request mux mode ireg_EMUX, // 2: Error mux control ireg_LBA, // 1: LBA mode ireg_SLAVE, // 0: Master/slave // 16-bit flags - LE byte 1 ireg_SRST, // 15: Soft reset request ireg_IENn, // 14: Host interrupt enable ireg_IRQACT, // 13: Host interrupt active ireg_IRQPIn, // 12: Output pending to RPi ireg_SRSTP, // 11: Reset pending ireg_IDNF, // 10: ERR: Sector not found ireg_ABRT, // 9: ERR: Aborted command ireg_BSY, // 8: STS: Busy // 16-bit command and feature arguement ireg_CMD, ireg_FEAT, // 16-bit transfer size ireg_SECR, // Byte remainder for packet formats ireg_SECZ, // Number of 512 byte transfers (sectors) // 32-bit LE logical block address - LE ireg_SECN, // LBA0: Start sector number ireg_CYLL, // LBA1: Lower cylinder number ireg_CYLH, // LBA2: Upper cylinder number 4'b0000, // Upper nibble pad ireg_HEAD, // LBA3: Head number // Current FIFO levels ififo_CNT[7:0], // Input FIFO level 4'b000, ififo_CNT[11:8], ofifo_CNT[7:0], // Output FIFO free level 4'b000, ofifo_CNT[11:8] }; // ********* SPI PROTOCOL ENGINE ********* /* * Many SPI peripheral implementations will use an independent * internal clock to over-sample the transitions on the SPI * lines. This makes the world easy in that you never have to * cross a clock domain. However it limits the total speed of * the SPI clock to a subset of the sampling clock. * * I didn't want to do that here opting to direct drive the * SPI flip-flops using the SPI clock and rising edge of CS * and use FIFOs and transfer logic to move data and status * to the IDE state machine. * * The SPI data format follows (8-bit word size): * * * * Read data commands require an extra dummy byte before the start * of data to be read to allow advance latching. Both read and * write data commands require the byte count to be present as a * 16-bit LE value in ARG1/ARG2. Nearly all commands need some * trailing clocks to drive completion logic in the state machine. */ `define state_SPI_CMD 3'b0_00 `define state_SPI_IGNORE 3'b0_01 `define state_SPI_FIFO_READ 3'b1_00 `define state_SPI_FIFO_WRITE 3'b1_01 `define state_SPI_REG_READ 3'b1_10 `define state_SPI_REG_WRITE 3'b1_11 reg [2:0] spi_state; reg [15:0] spi_count; reg [23:0] spi_arg; reg [111:0] spi_shifti; reg [111:0] spi_datain; reg [111:0] spi_shifto; reg ififo_xfer; // FIFO transfer in strobe reg ofifo_xfer; // FIFO transfer out strobe wire [111:0] spi_shift = { spi_shifti[110:0], spi_MOSI }; always @(posedge spi_CLK or posedge spi_CSn) begin if (spi_CSn) begin spi_state <= `state_SPI_CMD; spi_count <= 16'h0000; spi_arg <= 24'h000000; // During CMD dword and first FIFO read byte, clock 0's spi_shifto <= { 8'h00, `VERSION_MAJOR, `VERSION_MINOR, 88'h0000000000000000000000 }; spi_shifti <= 112'h0000000000000000000000000000; spi_datain <= 112'h0000000000000000000000000000; ififo_xfer <= 1'b0; ofifo_xfer <= 1'b0; end else begin spi_shifti <= spi_shift; spi_shifto <= { spi_shifto[110:0], 1'b0 }; spi_count <= spi_count + 1; ififo_xfer <= (spi_count[3:0] == 4'b1111); ofifo_xfer <= (spi_count[3:0] == 4'b0101); case (spi_state) `state_SPI_CMD : begin if (spi_count == 16'd31) begin // Lower 3 bits of first (upper) byte of command word spi_state <= spi_shift[26:24]; spi_arg <= spi_shift[23:0]; spi_count <= 16'h0000; spi_shifto <= spi_REGSOUT; // override/squash strobe on this word boundary ififo_xfer <= 1'b0; end end `state_SPI_REG_WRITE : begin if (spi_count == 16'd111) begin spi_state <= `state_SPI_IGNORE; spi_datain <= spi_shift; end end `state_SPI_REG_READ : begin if (spi_count == 16'd111) spi_state <= `state_SPI_IGNORE; end `state_SPI_IGNORE : spi_count <= 16'd0; `state_SPI_FIFO_READ : begin // (word count * 16 bits) + 4 if (spi_count == { spi_arg[11:0], 4'b0100 }) spi_state <= `state_SPI_IGNORE; if (spi_count[3:0] == 4'b0111) spi_shifto[111:96] <= ofifo_OUT; end `state_SPI_FIFO_WRITE : begin // (word count * 16 bits) + 4 if (spi_count == { spi_arg[11:0], 4'b0100 }) spi_state <= `state_SPI_IGNORE; end endcase end end assign spi_MISO = spi_shifto[111]; // ********* ATAPI FINITE STATE MACHINE ********* /* * Transfer a single bit across clock domains (SPI -> IDE) * to indicate a SPI register write is complete so the * latched datain values above can be processed by the * IDE state machine. * * There is no state progression in the IDE FSM that can * last as long as the time it takes for a subsequent * SPI transaction from the PI + the time it takes to * actually cross latch the data from the SPI datain * holding register to the IDE registers. So the data * should remain stable till that point. This does * assume the IDE sys clock is fast enough to process * a single cycle transfer state between bus accesses * as bus accesses always have priority. */ wire spi_reg_write = (spi_state == `state_SPI_REG_WRITE); reg spi_reg_write_d1; reg spi_reg_write_d2; reg spi_reg_pending; /* * */ `define state_IO_IDLE 4'b0_000 `define state_IO_RESET 4'b0_001 `define state_IO_RESET_DELAY 4'b0_010 `define state_IO_XFER_REGS 4'b0_011 `define state_IO_WRITE_REG 4'b1_000 `define state_IO_WRITE_DATA 4'b1_001 `define state_IO_WRITE_WAIT 4'b1_010 `define state_IO_READ_REG 4'b1_100 `define state_IO_READ_FETCH 4'b1_101 `define state_IO_READ_DATA 4'b1_110 `define state_IO_READ_WAIT 4'b1_111 `define state_IO_READ_SFETCH 4'b0_100 `define state_IO_READ_SDATA 4'b0_101 `define state_IO_WRITE_SDATA 4'b0_111 reg [3:0] state; always @(posedge ide_CLK or negedge sys_RSTn) begin if (~sys_RSTn) begin state <= `state_IO_IDLE; data_dir <= 1'b0; // IDE bus direction data_en <= 1'b0; // IDE bus drivers enable ireg_IDNF <= 1'b0; // CS0:1R ERR[4] - ID not found ireg_ABRT <= 1'b0; // CS0:1R ERR[2] - Abort ireg_FEAT <= 8'h00; // CS0:1W Feature ireg_SECZ <= 8'h00; // CS0:2 Sector xfer count ireg_SECN <= 8'h01; // CS0:3 Starting sector # ireg_CYLL <= 8'h00; // CS0:4 Starting cyl low ireg_CYLH <= 8'h00; // CS0:5 Starting cyl high ireg_LBA <= 1'b0; // CS0:6 DRVH[6] LBA mode enable ireg_SLAVE <= 1'b0; // CS0:6 DRVH[4] Master/Slave Select ireg_HEAD <= 4'b0000; // CS0:6 DRVH[3:0] Head number ireg_BSY <= 1'b0; // CS0:7R STS[7] Busy indicator ireg_DRDY <= 1'b0; // CS0:7R STS[6] Drive ready ireg_DF <= 1'b0; // CS0:7R STS[5] Drive fault ireg_DSC <= 1'b0; // CS0:7R STS[4] Drive seek complete ireg_CMD <= 8'h00; // CS0:7W Command ireg_SRST <= 1'b0; // CS1:6W DCTL[2] Soft reset ireg_IENn <= 1'b1; // CS1:6W DCTL[1] Interrupt enable ireg_SECR <= 8'h00; // Byte remainder of xfer size ireg_IRQACT <= 1'b0; // IRQ driver output enable ireg_IRQOUT <= 1'b0; // IRQ driver state ireg_IRQPIn <= 1'b0; // IRQ to RPi pending ireg_SRSTP <= 1'b1; // Reset pending ireg_EMUX <= 1'b0; // Error register mux ireg_FRST <= 1'b0; // FIFO reset strobe ireg_DRQm <= `DRQ_MODE_OFF; // Data request mux ififo_CNT <= 12'h000; // Words in PI->CPLD FIFO ofifo_CNT <= 12'h400; // Words avail in CPLD->PI FIFO spi_reg_pending <= 1'b0; // Cross latch SPI regs/counts end else begin // Synchronize cross latch of SPI data spi_reg_write_d2 <= spi_reg_write_d1; spi_reg_write_d1 <= spi_reg_write; if (spi_reg_write_d2 & ~spi_reg_write_d1) // falling edge spi_reg_pending <= 1'b1; // Finite State Machine for IDE I/O interface case (state) `state_IO_IDLE : begin // Reminder: listed in reverse priority order if (~ide_RSTn | ireg_SRST) state <= `state_IO_RESET; if (spi_reg_pending) state <= `state_IO_XFER_REGS; if (ide_CS & ide_RD) begin if (ide_CSA && (ide_A[2:0] == 3'b000)) state <= `state_IO_READ_FETCH; else if (ide_CSB && (ide_A[2:0] == 3'b001)) state <= `state_IO_READ_SFETCH; else state <= `state_IO_READ_REG; data_dir <= 1'b1; // data_en <= 1'b1; end if (ide_CS & ide_WR) begin if (ide_CSA && (ide_A[2:0] == 3'b000)) state <= `state_IO_WRITE_DATA; else if (ide_CSB && (ide_A[2:0] == 3'b001)) state <= `state_IO_WRITE_SDATA; else state <= `state_IO_WRITE_REG; data_dir <= 1'b0; data_en <= 1'b1; end end `state_IO_RESET : begin state <= `state_IO_RESET_DELAY; // immediate register actions - wait on PI for rest ireg_ABRT <= 1'b1; // current command aborted ireg_BSY <= 1'b1; // drive busy ireg_DRDY <= 1'b0; // drive not ready ireg_DRQm <= `DRQ_MODE_OFF; ireg_IRQACT <= 1'b0; // de-assert any host IRQ ireg_IRQPIn <= 1'b1; // de-assert any Pi IRQ ireg_SRSTP <= 1'b1; // software reset pending ireg_EMUX <= 1'b0; // error mux control ireg_FRST <= 1'b1; // Reset FIFOs ififo_CNT <= 12'h000; // Reset FIFO levels to empty ofifo_CNT <= 12'h400; end `state_IO_RESET_DELAY : begin state <= `state_IO_IDLE; ireg_IRQPIn <= 1'b0; // assert Pi IRQ ireg_FRST <= 1'b0; // FIFOs ready on next clock end `state_IO_XFER_REGS : begin state <= `state_IO_IDLE; ireg_DRDY <= spi_datain[111]; ireg_DF <= spi_datain[110]; ireg_DSC <= spi_datain[109]; ireg_DRQm <= spi_datain[108:107]; ireg_EMUX <= spi_datain[106]; ireg_LBA <= spi_datain[105]; ireg_SLAVE <= spi_datain[104]; ireg_SRST <= spi_datain[103]; ireg_IENn <= spi_datain[102]; ireg_IRQACT <= spi_datain[101]; ireg_IRQPIn <= spi_datain[100]; ireg_SRSTP <= spi_datain[99]; ireg_IDNF <= spi_datain[98]; ireg_ABRT <= spi_datain[97]; ireg_BSY <= spi_datain[96]; ireg_CMD <= spi_datain[95:88]; ireg_FEAT <= spi_datain[87:80]; ireg_SECR <= spi_datain[79:72]; ireg_SECZ <= spi_datain[71:64]; ireg_SECN <= spi_datain[63:56]; ireg_CYLL <= spi_datain[55:48]; ireg_CYLH <= spi_datain[47:40]; ireg_HEAD <= spi_datain[35:32]; // bits 36-39 ignored (upper 4 bits of LBA/head) ififo_CNT <= ififo_CNT + { spi_datain[19:16], spi_datain[31:24] }; ofifo_CNT <= ofifo_CNT + { spi_datain[3:0], spi_datain[15:8] }; // bits 20-23 ignored (upper 4 bits of upper ififo_ADJ byte) // bits 4-7 ignored (upped 4 bits of upper ofifo_ADJ byte) spi_reg_pending <= 1'b0; end `state_IO_READ_REG : begin state <= `state_IO_READ_WAIT; data_en <= |ide_A; ide_DAT[15:8] <= 8'h00; ide_DAT[7:0] <= (ide_CSA && (ide_A[2:0] == 3'b001)) ? ireg_EMUX ? ireg_FEAT : ireg_ERR : (ide_CSA && (ide_A[2:0] == 3'b010)) ? ireg_SECZ : (ide_CSA && (ide_A[2:0] == 3'b011)) ? ireg_SECN : (ide_CSA && (ide_A[2:0] == 3'b100)) ? ireg_CYLL : (ide_CSA && (ide_A[2:0] == 3'b101)) ? ireg_CYLH : (ide_CSA && (ide_A[2:0] == 3'b110)) ? ireg_DRVH : (ide_CSA && (ide_A[2:0] == 3'b111)) ? ireg_STS : // (ide_CSB && (ide_A[2:0] == 3'b010)) ? ireg_UART : (ide_CSB && (ide_A[2:0] == 3'b011)) ? ireg_SECR : (ide_CSB && (ide_A[2:0] == 3'b110)) ? ireg_STS : 8'h00; end `state_IO_READ_FETCH : begin state <= `state_IO_READ_DATA; end `state_IO_READ_DATA : begin state <= `state_IO_READ_WAIT; data_en <= 1'b1; if (|ififo_CNT) begin ide_DAT <= { ififo_OUT[7:0], ififo_OUT[15:8] }; ififo_CNT <= ififo_CNT - 1; end else ide_DAT <= 16'h0000; end `state_IO_READ_SFETCH : begin state <= `state_IO_READ_SDATA; end `state_IO_READ_SDATA : begin state <= `state_IO_READ_WAIT; data_en <= 1'b1; ide_DAT <= 16'h0000; //{ 8'h00, stojr_out }; end `state_IO_READ_WAIT : begin if (~ide_RD) begin state <= `state_IO_IDLE; // data_en <= 1'b0; end end `state_IO_WRITE_REG : begin state <= `state_IO_WRITE_WAIT; if (ide_CSA) begin case (ide_A[2:0]) 3'b001 : ireg_FEAT <= ide_DIN[7:0]; 3'b010 : ireg_SECZ <= ide_DIN[7:0]; 3'b011 : ireg_SECN <= ide_DIN[7:0]; 3'b100 : ireg_CYLL <= ide_DIN[7:0]; 3'b101 : ireg_CYLH <= ide_DIN[7:0]; 3'b110 : begin ireg_LBA <= ide_DIN[6]; ireg_SLAVE <= ide_DIN[4]; ireg_HEAD <= ide_DIN[3:0]; end 3'b111 : // Command register - trigger IRQ to PI begin ireg_CMD <= ide_DIN[7:0]; ireg_IDNF <= 1'b0; // clear error bits ireg_ABRT <= 1'b0; ireg_BSY <= 1'b1; // busy ireg_IRQPIn <= 1'b0; // active ireg_DRQm <= `DRQ_MODE_OFF; ireg_EMUX <= 1'b0; // Reset FIFOs on every command ireg_FRST <= 1'b1; ififo_CNT <= 12'h000; ofifo_CNT <= 12'h400; end endcase end if (ide_CSB) begin case (ide_A[2:0]) 3'b011 : ireg_SECR <= ide_DIN[7:0]; 3'b110 : begin ireg_SRST <= ide_DIN[2]; ireg_IENn <= ide_DIN[1]; end endcase end end `state_IO_WRITE_DATA : begin state <= `state_IO_WRITE_WAIT; if (|ofifo_CNT) ofifo_CNT <= ofifo_CNT - 1; end `state_IO_WRITE_SDATA : begin state <= `state_IO_WRITE_WAIT; end `state_IO_WRITE_WAIT : begin ireg_FRST <= 1'b0; if (~ide_WR) begin state <= `state_IO_IDLE; data_en <= 1'b0; end end endcase end end // RPI -> CPLD data input FIFO datafifo FIFO_IN ( .rst (ireg_FRST), .wclk (spi_CLK), .we ((spi_state == `state_SPI_FIFO_WRITE) && ififo_xfer), .wdata (spi_shifti[15:0]), .rclk (ide_CLK), .re (state == `state_IO_READ_FETCH), .rdata (ififo_OUT) ); // CPLD -> RPI data output FIFO datafifo FIFO_OUT ( .rst (ireg_FRST), .wclk (ide_CLK), .we (state == `state_IO_WRITE_DATA), .wdata ({ide_DIN[7:0], ide_DIN[15:8]}), .rclk (spi_CLK), .re ((spi_state == `state_SPI_FIFO_READ) && ofifo_xfer), .rdata (ofifo_OUT) ); // Conditions that illuminate the drive activity LED wire [2:0] ide_ACTIVE = { ireg_BSY, // Command servicing active (ififo_CNT != 12'h000), // In-bound data transfer (R) (ofifo_CNT != 12'h400) // Out-bound data transfer (W) }; assign ide_DASP = |ide_ACTIVE; // to external open drain nFET // Static output assignments from registered logic assign pi_IRQn = ireg_IRQPIn; // GPIO.5 / BCM24 assign ide_IRQen = ireg_IRQACT; assign ide_IRQout = ireg_IRQOUT; reg [21:0] pwm_COUNT = 22'd0; always @(posedge sys_REF) begin pwm_COUNT <= pwm_COUNT + 1; end assign sys_LED = pwm_COUNT[21]; endmodule