/*
* 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