-
Notifications
You must be signed in to change notification settings - Fork 42
Sata Interface
The sata_stack.v module exposes the following signals (excluding debug signals):
- rst: Asynchronous SATA stack reset
- clk: Main stack clock. This must be related to your gigabit transceiver. This is generally 40X slower than the gigabit transceiver clock
- Spartan 6 GTP SATA 2 Example:
- GTP frequency: 3GHz
- GTP Data word size: 32-bits
- Data word size using 8B10B encoding: 40-bits
- User Interface Clock: 3000 / 40 = 75MHz
- Spartan 6 GTP SATA 2 Example:
- sata_ready: when both this signal is high and sata_busy is low the sata stack is ready to receive commands
- sata_busy: see above (This should be fixed in future version to only require the 'sata_ready' signal to determine if the stack is ready to use)
- platform_ready: sata stack has detected the platform is ready to use (all PLLs and gigabit transceivers are working)
- platform_error: an error associated with the gigabit transceivers has been detected (PLL lock lost, this is application specific) If this is detected it is a good idea to reset the SATA stack
- linkup: If this is detected the sata stack has successfully linked up with a hard drive. All out of band initialization has been completed.
- send_sync_escape: This is used to cancel an ongoing command (this has not been tested very well)
- hard_drive_error: Mapped to the status bit "error detected" within the hard drive status field (returned from the hard drive)
- execute_command_stb: a strobe on this signal will initiate the command sequence in 'hard_drive_command'
- user_features: SATA specific signals. it is similar to sub functions
- hard_drive_command: commands used to control the hard drive. Two important commands include:
- WRITE_DMA_EXT (0x35): Write data in 8KB packets (sectors) to the hard drive
- READ_DMA_EXT (0x25): Read data in 8KB packets (sectors) from the hard drive
- pio_data_ready: When communicated with the 'peripheral IO' portion of the SATA stack, this flag will indicate that there is data from the hard drive ready on the data interface (see below how to read data from the hard drive)
-
pio_setup_stb: hard drive has acknowledged that the user wants to write data (PIO) and is ready to receive data (this data chunk is relative to the command). This signal can be ignored because the sata stack will automatically read the data from the user_din FIFO (see writing to FIFOs below)
-
dma_setup_stb: NOT USED (Will be removed)
-
dma_activate_stb: hard drive has acknowledged that the user wants to write data (DMA) and is ready to receive a sectors (8KB) worth of data. This signal can be ignored because the sata stack will automatically read the data from the user_din FIFO (see writing to FIFOs below)
-
d2h_data_stb: Data has been read from the hard drive. Users can ignore this and just read data from the user_dout FIFO path
-
set_device_bits_stb: A mechanism in which the hard drive can update the host without the host initating a transfer
-
d2h_reg_stb: Strobe indicating the hard drive has sent data and the 'd2h' signals are populated
-
d2h_fis: (This is normally the 'hard_drive_command') and is supplied with the response
-
d2h_interrupt: hard drive has sent an interrupt (normally not used)
-
d2h_notification: hard drive notification (normally not used)
-
d2h_port_mult: port multiplexer information: (normally not used)
-
d2h_device: hard drive device bits
-
d2h_lba: logical block address
- depends on the command
- when DMA this will return the next sector address
- Example: User writes to sector_address: 0x01, and sector_count: 0x01 this value will return 0x02.
- when used to read the max size of the hard drive, this will return the maximum sector count
- when DMA this will return the next sector address
- depends on the command
-
d2h_sector_count
- returns the number of data sectors read or written
-
d2h_status
- bit field of the hard drive status
-
d2h_error
- error number read from the hard drive
A more detailed description of the data interface is described in the appendix
-
data_in_clk: clock to drive data from the host to the hard drive.
- This clock does not need to be the same as the sata stack clock
-
data_in_clk_valid: data in clock is valid and ready to use
-
user_din: 32-bit data that is strobed into the 2K 32-bit buffer
-
user_din_stb: data is strobed in relative to the data_in_clk signal
-
user_din_ready: one (or two) of the two data buffers is ready
-
user_din_activate: activate one of the two data buffers
-
user_din_size: maximum size of the data buffer. This is 2048:, users should always fill up this buffer when writing to the hard drive
-
user_din_empty: The buffers are completely empty
-
data_out_clk: clock to drive the data from the hard drive to the host
- This clock does not need to be the same as the sata stack clock
-
data_out_clk_valid: data out clock is valid and ready to use
-
user_dout: 32-bit data strobed out using the user_dout_stb signal
-
user_dout_ready: data is ready to be read
-
user_dout_activate: activate the buffer to read
-
user_dout_stb: strobe data from the FIFO
-
user_dout_size: number of 32-bit words within FIFO
-
tx_dout: 32-bit data sent from the sata stack to the platform gigabit transceiver
-
tx_is_k: 4-bit value controlled by the SATA stack indicating that one of the 4 bytes sent is a K code, connect all signals to stack
-
tx_comm_reset: out of band signal (OOB) sent from the sata stack to the gigabit transciever
-
tx_comm_wake: out of band signal (OOB) sent from the sata stack to the gigabit transciever
-
tx_elec_idle: out of band signal (OOB) sent from the sata stack to the gigabit transciever
-
tx_oob_complete: out of band sequence is complete
-
rx_din: 32-bit data read from the gigabit transceiver to the SATA stack
-
rx_is_k: single bit value indicating that the 32-bit value is a k code
-
rx_elec_idle: out of band signal (OOB) from gigabit transciever indicating remote side is IDLE
-
rx_byte_is_aligned: data is aligned correctly
-
comm_init_detect: out of band signal (OOB) 'comm_init' detected
-
comm_wake_detect: out of band signal (OOB) 'comm_wake' detected
-
phy_error: signal from gigabit transceiver indicating an error has occured (disparity, loss of signal, etc...)
-
Linkup: When the 'platform_ready' signal is high and the stack is not linked up it will continually send out the SATA OOB signals to the hard drive in order to initiate a linkup sequence. Once the entire linkup sequence is finished the 'linkup' signal will go high
-
Ready For Commands: SATA stack is ready to receive user commands when the following is true:
- linkup && sata_ready && !sata_busy
-
Command Execution Sequence: When the stack is 'Ready For Commands' (see above) users can send commands to the stack
- Populate the signals:
- hard_drive_command: A command to control the hard drive (0x25: READ_DATA_EXT, 0x35: WRITE_DMA_EXT, etc...)
- sector_count: The number of sectors that will be written or read
- sector_address: The sector address that the read or write will start from:
- Initiate the command:
- execute_command_stb: strobed high for one clock cycle
- Populate the signals:
-
Writing data to the hard drive: Writing data to the hard drive consists of performing the 'Command Execution Sequence' with the WRITE_DMA_EXT command and sending the data using the 'user_din' signals. A description of how to write data through the ppfifo is described below.
- Users can populate the data FIFOs or initate a command first. The order is not important
-
Reading data from the hard drive: Reading data from the hard drive consists of performing the 'Command Execute Sequence' with the "READ_DMA_EXT command. The sata stack will populate the 'user_dout' FIFO with the data read from the hard drive. When the FIFO is full the sata stack will not write more data into it. Refer to 'Read Side' to see how to read the data from the FIFOs
-
Non-Reading/Writing Commands
- There are several non-reading and writing commands (Reset, Total Sector Count, etc...)
- Similar to the Writing/Reading data to/from the hard drive the hard drive accepts other commands. These commands may require the user to populate the 'user_features' and or sector count.
- Example: Retrieving the maximum number of sector in the hard drive:
- user_features: 0x00 (Clear the sub command)
- hard_drive_command: 0x27 (Max LBA)
- Example: Retrieving the maximum number of sector in the hard drive:
The Ping Pong FIFO, or ppfifo, is a cross clock data transfer mechanism that is a mixture between a double buffer and a FIFO.
- It is similar to a FIFO in that users use the 'write_strobe' and 'write_data' to strobe data into the FIFO and use the 'read_strobe' and 'read_data' to read data from the FIFO.
- It is similar to a double buffer because users use the 'write_activate' to choose which side of the double buffer to write to.
- It is different from a buffer because users do not need to keep track of the address.
- The correct side of the double buffer is automatically selected on the read side and the 'reader' does not need to keep track of which buffer the write side selected.
- The write side always knows how much space is available in the FIFO becuase the read side cannot read from the same buffer that is being written to.
- The read side always knows how much data is available in the FIFO because the write side cannot write into the buffer that the read side is using.
- The read side and the write side can operate at different clock frequencies
- the user monitors the 'write_ready' 2 bit signal: When the 'write_ready' signal is not 0 then one of the two buffers is available. The user must then activate that buffer using the 'write_activate' signal. The user then strobes in data up to the maximum size of the buffer 'write_fifo_size'
- users do NOT need to fill up the FIFO to stop using it, just de-assert 'write_activate'
Example Module to Fill the write side of ppfifo
To use this module with the sata stack data write side map the following signals:
- clk: data_in_clk
- i_wr_rdy: user_din_ready
- o_wr_act: user_din_activate
- o_wr_stb: user_din_stb
- i_wr_size: user_din_size
- o_wr_data: user_din
/* Module: ppfifo_data_generator
*
* Description: Populate a Ping Pong FIFO with an incrementing number pattern
*/
module ppfifo_data_generator (
input clk,
input rst,
input i_enable,
//Ping Pong FIFO Interface
input [1:0] i_wr_rdy,
output reg [1:0] o_wr_act,
input [23:0] i_wr_size,
output reg o_wr_stb,
output reg [31:0] o_wr_data
);
//Local Parameters
//Registers/Wires
reg [23:0] r_count;
//Submodules
//Asynchronous Logic
//Synchronous Logic
always @ (posedge clk) begin
if (rst) begin
o_wr_act <= 0;
o_wr_stb <= 0;
o_wr_data <= 0;
r_count <= 0;
end
else begin
//Reset strobe signals
o_wr_stb <= 0;
if (i_enable) begin
if ((i_wr_rdy > 0) && (o_wr_act == 0))begin
r_count <= 0;
if (i_wr_rdy[0]) begin
//Channel 0 is open
o_wr_act[0] <= 1;
end
else begin
//Channel 1 is open
o_wr_act[1] <= 1;
end
end
else begin
if (r_count < i_wr_size) begin
//More room left in the buffer
r_count <= r_count + 1;
o_wr_stb <= 1;
//put the count in the data
o_wr_data <= r_count;
end
else begin
//Filled up the buffer, release it
o_wr_act <= 0;
end
end
end
end
end
endmodule
- the user monitors the 'read_ready' bit: When the 'read_ready' signal is 1 then the ppfifo has a block of data ready for the user. The user activates that block with 'read_activate' signal and uses the 'read_strobe' to read the NEXT data
- 'read_count' is the total number of data elements within the buffer.
- Users must read all the data before setting 'read_activate' low
Example Module to Empty the read side of a ppfifo
To use this module with the sata data read side map the following signals:
- clk: data_out_clk
- i_rd_rdy: user_dout_ready
- o_rd_act: user_dout_activate
- i_rd_size: user_dout_size
- o_rd_stb: user_dout_stb
- i_rd_data: user_dout
/* Module: ppfifo_data_sink
*
* Description: Whenever data is available within the FIFO activate it and read it all
*/
module ppfifo_data_sink (
input clk,
input rst,
//Ping Pong FIFO Interface
input i_rd_rdy,
output reg o_rd_act,
input [23:0] i_rd_size,
output reg o_rd_stb,
input [31:0] i_rd_data
);
//Local Parameters
//Registers/Wires
reg [23:0] r_count;
//Submodules
//Asynchronous Logic
//Synchronous Logic
always @ (posedge clk) begin
if (rst) begin
o_rd_act <= 0;
r_count <= 0;
o_rd_stb <= 0;
end
else begin
//Strobes
o_rd_stb <= 0;
if (i_rd_rdy && !o_rd_act) begin
r_count <= 0;
o_rd_act <= 1;
end
else begin
if (r_count < i_rd_size) begin
o_rd_stb <= 1;
r_count <= r_count + 1;
end
else begin
o_rd_act <= 0;
end
end
end
end
endmodule