/* =============================================================== (C) 2005 Robert Finch All rights reserved. rob@birdcomputer.ca rawATA.v This source code is free for use and modification for non-commercial or evaluation purposes, provided this copyright statement and disclaimer remains present in the file. If you do modify the code, please state the origin and note that you have modified the code. NO WARRANTY. THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED. The user must assume the entire risk of using the Work. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR. IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR LOSSES RELATING TO SUCH UNAUTHORIZED USE. ATA interface Key timing parameters are: TsA = 70 ns address setup before IORD/IOWR clocks = 2*35ns ThA = 10 ns address hold after rd/we_i = 1 clk_i Tpw = 165 ns rd/we_i pulse width = (5 * 35ns = 175) data output must be valid at least 30ns before rising edge of IOWR data must be held at least 15ns after rising edge of IOWR data won't be valid until at least 20ns after iord data will be held for at least 5ns after iord iois16 must change no later than 35 ns after stb_i/address iordy will go low a max of 35ns after iord/iowr reset must pulse low for at least 40 ns Read register 0 to 15 to "prefetch" the data. Then get the real data by waiting 10 clock cycles and reading register 2. Register 2 reflects the contents of the last addressed register. Operation: This interface is a raw interface in the sense that it connects the system directly to the ATA bus. In effect it acts like a simple bus bridge between the SoC bus and the ATA bus. It translates the SoC bus access into a properly timed ATA bus access, and that's about all it does. Accessing the raw ATA interface is fairly straightforward, however it's complicated by the fact that the standard ATA bus is a slow IO bus. This module does NOT generate a delayed ready signal to accomodate for the slow ATA bus. Instead, reading from the interface requires performing a "prefetch" read from the desired register, then reading the output value from register 2 after a delay of at least 10 clock cycles. *** the actual number of clock cycles required may vary depending on the clock frequency used. *** Write access is performed by simply writing to the desired ATA register. However, writes (and reads) must be separated by at least 10 clock cycles. This is to give the ATA interface time to transfer values on the ATA side of the component. A delayed ready signal was not generated to avoid adversly affecting the system bus, in the case that DMA is taking place on the system bus. A delay of approximately 10 clock cycles or more was too great for current uses. As a result, this module responds immediately to reads and writes (it's done within the clock cycle of the access), but a prefetch read is required, and accesses must be separated by at least 10 clock cycles. In many cases the 10 clock cycle access spacing can be hidden by the execution of additional program code taking place between accesses. The state machine assumes a 28.63636MHz clock for timing purposes. The setup and pulse width times will need to be adjusted for a different clock rate (TsA, Tpw). The chip selects are backwards on the schematic!!! Reg 0-15 read or write - trigger an ATA IO cycle 0 inactive register 2 data output (non-ATA standard reg) 6 alternate status register 8 data register 9 error register 10 sector count 11 sector number 12 cylinder low 13 cylinder high 14 head/device 15 command/status register +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |WISHBONE Datasheet |WISHBONE SoC Architecture Specification, Revision B.3 | |Description: Specifications: +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |General Description: raw ATA interface +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Supported Cycles: SLAVE,READ/WRITE | SLAVE,BLOCK READ/WRITE | SLAVE,RMW +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Data port, size: 16 bit |Data port, granularity: 16 bit |Data port, maximum operand size: 16 bit |Data transfer ordering: Undefined |Data transfer sequencing: Undefined +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Clock frequency constraints: none +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Supported signal list and Signal Name WISHBONE equiv. |cross reference to equivalent ack_o ACK_O |WISHBONE signals adr_i ADR_I() | clk_i CLK_I | dat_i(15:0) DAT_I() | dat_o(15:0) DAT_O() | cyc_i CYC_I | stb_i STB_I | we_i WE_I | +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Special requirements: +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 39 LUTs / 35 slices / 172 MHz (speed Spartan3-4) =============================================================== */ `define ATA_READ 16'h0020 `define ATA_WRITE 16'h0030 `define ATA_INITDRIVEPARAM 16'h0091 // register data `define ATA_MASTERLBA 16'h00E0 `define ATA_MASTERCHS 16'h00A0 `define ATA_ALTER_STATUS_SOFT_RESET 16'h0006 // s/w rst_i, no interrupts `define ATA_ALTER_STATUS_END_SOFT_RESET 16'h0002 `define S_IDLE 0 // waiting for access `define S_ATA_RESET0 13 `define S_ATA_RESET1 14 `define S_ATA_RESET2 15 module rawATA ( // WISHBONE System bus interfacing input rst_i, // reset input clk_i, // clock input cyc_i, // cycle valid input stb_i, // core select output ack_o, // data is ready input we_i, // write to core input [3:0] adr_i, // address input [15:0] dat_i, // data input output reg [15:0] dat_o, // data output output vol_o, // volatile register // ATA bus output reg ataReset_n, output reg ataCs0_n, output reg ataCs1_n, output reg ataRd_n, output reg ataWr_n, input ataRdy, output reg [2:0] ataA, inout [15:0] ataD ); parameter pClkFreq = 25000000; // timing parameters must be at least 1 parameter TsA = pClkFreq / 14285714 + 1; // 70ns parameter Tpw = pClkFreq / 6060606 + 1; // 165ns parameter ThA = pClkFreq / 100000000 + 1; // 10 ns (min) parameter Trpw = pClkFreq / 25000000 + 1; // 40 ns reset pulse width localparam S_RESET = TsA+Tpw+ThA+1; // use up the next state localparam maxCnt = S_RESET+Trpw; localparam cntBits = maxCnt > 512 ? 10 : maxCnt > 256 ? 9 : maxCnt > 128 ? 8 : maxCnt > 64 ? 7 : maxCnt > 32 ? 6 : maxCnt > 16 ? 5 : 4 ; // variables reg [cntBits:0] cnt; reg [15:0] dinl; reg wr1; reg rd_rdy; // so that ready goes high right away on a write wire wr_rdy = we_i && cnt==`S_IDLE; assign vol_o = cyc_i & stb_i; assign ack_o = cyc_i & stb_i ? wr_rdy | rd_rdy || (adr_i==4'd2) : 0; assign ataD = wr1 ? dinl : 16'bz; always @(posedge clk_i) if (rst_i) begin ataCs0_n <= 1; ataCs1_n <= 1; ataRd_n <= 1; ataWr_n <= 1; ataReset_n <= 1; wr1 <= 0; rd_rdy <= 0; cnt <= S_RESET; dinl <= 0; end else begin rd_rdy <= 0; // ack_o active for only one cycle case (cnt) // Wait for an access by the system then // assert address/chip select `S_IDLE: if (cyc_i & stb_i) begin ataCs0_n <= adr_i[3]; ataCs1_n <= ~adr_i[3]; ataA <= adr_i[2:0]; dinl <= dat_i; cnt <= cnt + 1; wr1 <= we_i; end // Assert read or write TsA: begin ataRd_n <= wr1; ataWr_n <= ~wr1; cnt <= cnt + 1; end // Data from the IDE needs to be latched here because // the IDE won't hold it TsA+Tpw: if (ataRdy) begin rd_rdy <= ~wr1; // pulse ack_o high on read ataWr_n <= 1; // ready was already pulsed for write ataRd_n <= 1; dat_o <= ataD; cnt <= cnt + 1; end // This state used to meet the address / chip select // hold times. Note: if the clock is faster than 100MHz // more hold time will be needed. TsA+Tpw+ThA: begin ataCs0_n <= 1; ataCs1_n <= 1; wr1 <= 0; cnt <= `S_IDLE; end // Pulse rst_i low (40 ns min) on hardware rst_i S_RESET: begin ataReset_n <= 0; cnt <= cnt + 1; // RESET1 end S_RESET+Trpw: begin ataReset_n <= 1; cnt <= cnt + 1; end // default is to increment counter so it can get // to the next state default: cnt <= cnt + 1; // eventually get to S_IDLE endcase end endmodule