OpenCores
URL https://opencores.org/ocsvn/nysa_sata/nysa_sata/trunk

Subversion Repositories nysa_sata

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /nysa_sata
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/trunk/test/llw_states.txt
0,0 → 1,5
0 IDLE
1 WRITE_START
2 WRITE
3 WRITE_END
4 WAIT_RESPONSE
/trunk/test/model/sata_model.py
23,9 → 23,11
@cocotb.coroutine
def reset(self):
self.dut.rst = 0
self.dut.write_data_en = 0
self.dut.read_data_en = 0
self.dut.soft_reset_en = 0
#self.dut.write_data_stb = 0
self.dut.hard_drive_command = 0x00
self.dut.execute_command_stb = 0
#self.dut.read_data_stb = 0
self.dut.command_layer_reset = 0
self.dut.sector_count = 0
self.dut.sector_address = 0
self.dut.fifo_reset = 0
52,9 → 54,6
self.dut.platform_ready = 1
 
yield(self.wait_clocks(10))
self.dut.soft_reset_en = 1
yield(self.wait_clocks(10))
self.dut.soft_reset_en = 0
 
def ready(self):
if self.dut.sata_ready == 1:
63,27 → 62,38
 
@cocotb.coroutine
def wait_for_idle(self):
yield(cocotb.triggers.FallingEdge(self.dut.busy))
yield(cocotb.triggers.RisingEdge(self.dut.sata_ready))
print "Wait for idle..."
if self.dut.sata_busy.value == 1:
yield(cocotb.triggers.FallingEdge(self.dut.sata_busy))
if self.dut.sata_ready.value == 0:
yield(cocotb.triggers.RisingEdge(self.dut.sata_ready))
print "Idle!"
 
@cocotb.coroutine
def write_to_hard_drive(self, length, address):
self.dut.u2h_write_enable = 1
#self.dut.u2h_write_enable = 1
self.dut.u2h_write_count = length
#self.dut.h2u_read_enable = 1
self.dut.sector_address = address
#What does this do?
self.dut.sector_count = 0
self.dut.write_data_en = 1
self.dut.sector_count = (length / 8192) + 1
self.dut.hard_drive_command = 0x35
print "Write!"
 
 
yield(self.wait_clocks(10))
self.dut.execute_command_stb = 1
#self.dut.write_data_stb = 1
yield(self.wait_clocks(1))
self.dut.write_data_en = 0
#self.dut.write_data_stb = 0
self.dut.execute_command_stb = 0
yield(self.wait_for_idle())
yield(self.wait_clocks(100))
#self.dut.h2u_read_enable = 0
self.dut.hard_drive_command = 0x00
 
@cocotb.coroutine
def read_from_hard_drive(self, length, address):
self.dut.read_data_en = 1
self.dut.sector_address = address
sector_count = (length / 0x800) + 1
self.dut.sector_count = sector_count
91,10 → 101,26
#Also tell the reader to analyze the incomming data
self.dut.h2u_read_enable = 1
yield(self.wait_clocks(10))
 
print "Read..."
#self.dut.read_data_stb = 1
self.dut.hard_drive_command = 0x25
self.dut.execute_command_stb = 1
yield(self.wait_clocks(1))
#self.dut.read_data_stb = 0
self.dut.execute_command_stb = 0
yield(self.wait_clocks(100))
while (self.dut.h2u_read_total_count.value < length):
if self.dut.sata_ready.value == 1:
#self.dut.read_data_stb = 1
self.dut.execute_command_stb = 1
yield(self.wait_clocks(1))
#self.dut.read_data_stb = 0
self.dut.execute_command_stb = 0
yield(self.wait_clocks(10))
 
yield(self.wait_clocks(100))
self.dut.log.info("count: %d" % self.dut.h2u_read_total_count.value)
yield(self.wait_clocks(100))
 
self.dut.h2u_read_enable = 0
self.dut.read_data_en = 0
 
/trunk/test/scl_commands.txt
0,0 → 1,6
0 IDLE
1 WAIT_FOR_DMA_ACT
2 WAIT_FOR_WRITE_DATA
3 SEND_DATA
4 WAIT_FOR_STATUS
 
/trunk/test/waveforms.gtkw
0,0 → 1,187
[*]
[*] GTKWave Analyzer v3.3.62 (w)1999-2014 BSI
[*] Fri Jun 19 14:57:18 2015
[*]
[dumpfile] "/home/cospan/Projects/nysa-sata/test/design.vcd"
[dumpfile_mtime] "Fri Jun 19 14:47:16 2015"
[dumpfile_size] 12294345
[savefile] "/home/cospan/Projects/nysa-sata/test/waveforms.gtkw"
[timestart] 7530
[size] 1918 1059
[pos] -1 -1
*-11.048740 13340 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] tb_cocotb.
[treeopen] tb_cocotb.fshd.
[treeopen] tb_cocotb.fshd.fcl.
[treeopen] tb_cocotb.fshd.fsll.
[treeopen] tb_cocotb.ss.
[treeopen] tb_cocotb.ss.scl.fifo_out.
[treeopen] tb_cocotb.ss.sll.
[treeopen] tb_cocotb.ss.sll.slr.
[sst_width] 213
[signals_width] 246
[sst_expanded] 1
[sst_vpaned_height] 313
@22
tb_cocotb.test_id[31:0]
@28
tb_cocotb.hd_ready
tb_cocotb.linkup
tb_cocotb.phy_ready
tb_cocotb.platform_ready
tb_cocotb.ss.sata_ready
@200
-
@800200
-SATA Stack
@28
[color] 5
tb_cocotb.ss.clk
[color] 5
tb_cocotb.ss.rst
@200
-
@28
tb_cocotb.ss.sll.slr.data_valid
tb_cocotb.ss.sll.slr.send_r_ok
tb_cocotb.ss.sll.slr.send_r_ip
tb_cocotb.ss.sll.slr.send_r_err
@c00200
-SATA Commands
@28
tb_cocotb.ss.sata_ready
tb_cocotb.ss.scl.sata_busy
@22
tb_cocotb.ss.sector_count[15:0]
tb_cocotb.ss.sector_address[47:0]
tb_cocotb.ss.sector_count[15:0]
@28
tb_cocotb.ss.send_command_stb
tb_cocotb.ss.scl.t_d2h_reg_stb
tb_cocotb.ss.scl.t_d2h_data_stb
@22
tb_cocotb.fshd.fcl.sector_size[15:0]
tb_cocotb.fshd.fcl.sector_count[15:0]
tb_cocotb.ss.scl.sector_count[15:0]
@200
-
@28
tb_cocotb.ss.scl.d2h_error_abrt
tb_cocotb.ss.scl.d2h_error_amnf
tb_cocotb.ss.scl.d2h_error_bbk
tb_cocotb.ss.scl.d2h_error_idnf
tb_cocotb.ss.scl.d2h_error_mc
tb_cocotb.ss.scl.d2h_error_mcr
tb_cocotb.ss.scl.d2h_error_tk0nf
tb_cocotb.ss.scl.d2h_error_unc
@200
-
@28
tb_cocotb.ss.scl.d2h_status_bsy
tb_cocotb.ss.scl.d2h_status_corr
tb_cocotb.ss.scl.d2h_status_drdy
tb_cocotb.ss.scl.d2h_status_drq
tb_cocotb.ss.scl.d2h_status_dsc
tb_cocotb.ss.scl.d2h_status_dwf
tb_cocotb.ss.scl.d2h_status_err
tb_cocotb.ss.scl.d2h_status_idx
@1401200
-SATA Commands
@200
-
@c00200
-raw signals
@2022
^1 /tmp/../home/cospan/Projects/nysa-sata/test/../../../../../tmp/../home/cospan/Projects/nysa-sata/test/../../../../../tmp/../home/cospan/Projects/nysa-sata/test/../../../../../tmp/../home/cospan/Projects/nysa-sata/test/../../../../../tmp/../home/cospan/Projects/nysa-sata/test/primitives.txt
tb_cocotb.ss.sll.rx_din[31:0]
^1 /tmp/../home/cospan/Projects/nysa-sata/test/../../../../../tmp/../home/cospan/Projects/nysa-sata/test/../../../../../tmp/../home/cospan/Projects/nysa-sata/test/../../../../../tmp/../home/cospan/Projects/nysa-sata/test/../../../../../tmp/../home/cospan/Projects/nysa-sata/test/primitives.txt
tb_cocotb.ss.sll.tx_dout[31:0]
@1401200
-raw signals
@200
-
@800200
-Write Data Path
@28
tb_cocotb.ss.scl.execute_command_stb
@22
[color] 2
+{SCL Write State} tb_cocotb.ss.scl.write_state[3:0]
@28
tb_cocotb.ss.scl.transport_layer_ready
@c02022
[color] 2
^2 /tmp/../home/cospan/Projects/nysa-sata/test/transport_states.txt
+{Transport State} tb_cocotb.ss.stl.state[3:0]
@28
[color] 2
(0)tb_cocotb.ss.stl.state[3:0]
[color] 2
(1)tb_cocotb.ss.stl.state[3:0]
[color] 2
(2)tb_cocotb.ss.stl.state[3:0]
[color] 2
(3)tb_cocotb.ss.stl.state[3:0]
@1401200
-group_end
@22
+{Transport State} tb_cocotb.ss.stl.state[3:0]
@28
tb_cocotb.ss.stl.dma_activate_stb
@2022
[color] 2
^3 /tmp/../home/cospan/Projects/nysa-sata/test/llw_states.txt
+{Link Layer Write State} tb_cocotb.ss.sll.slw.state[3:0]
@22
+{Link Layer Write State} tb_cocotb.ss.sll.slw.state[3:0]
@28
tb_cocotb.ss.sll.slw.detect_r_ok
tb_cocotb.ss.sll.slw.detect_r_err
@1000200
-Write Data Path
-SATA Stack
@800200
-Hard Drive
@28
[color] 5
tb_cocotb.fshd.clk
[color] 5
tb_cocotb.fshd.rst
@200
-
@22
+{Faux HD Command Layer State} tb_cocotb.fshd.fcl.state[3:0]
@28
tb_cocotb.fshd.fcl.send_data_stb
tb_cocotb.fshd.fcl.transport_layer_ready
@200
-
@1000200
-Hard Drive
@200
-
@28
tb_cocotb.user_2_hd_reader.enable
tb_cocotb.user_2_hd_reader.hd_read_from_host
@22
tb_cocotb.user_2_hd_reader.hd_data_from_host[31:0]
tb_cocotb.user_2_hd_reader.test_data[31:0]
@28
[color] 1
tb_cocotb.user_2_hd_reader.error
tb_cocotb.hold
@200
-
@28
tb_cocotb.hd_2_user_reader.strobe
@22
tb_cocotb.hd_2_user_reader.count[23:0]
@28
tb_cocotb.hd_2_user_reader.enable
tb_cocotb.hd_write_to_host
tb_cocotb.hd_2_user_reader.ready
tb_cocotb.hd_2_user_reader.activate
@22
tb_cocotb.hd_data_to_host[31:0]
[pattern_trace] 1
[pattern_trace] 0
/trunk/test/Makefile
39,7 → 39,6
 
VERILOG_SOURCES += $(TOPDIR)/sim/tb_cocotb.v
 
 
TOPLEVEL = tb_cocotb
 
GPI_IMPL := vpi
/trunk/test/transport_states.txt
0,0 → 1,12
0 IDLE
1 CHECK_FIS_TYPE
2 WRITE_H2D_REG
3 RETRY
4 READ_D2H_REG
5 READ_PIO_SETUP
6 READ_SET_DEVICE_BITS
7 DMA_ACTIVATE
8 SEND_DATA
9 READ_DATA
 
 
/trunk/test/test_sata.py
31,6 → 31,7
dut.log.info("Sata is Ready")
 
 
 
@cocotb.test(skip = True)
def short_write_test(dut):
"""
88,14 → 89,17
-Number of data should be the same as the write amount
"""
dut.test_id = 3
data_count = 400
data_count = 2048
sata = SataController(dut, CLK_PERIOD)
yield(sata.reset())
 
yield(sata.wait_for_idle())
yield(sata.write_to_hard_drive(data_count, 0x00))
yield(sata.wait_clocks(100))
 
yield(sata.write_to_hard_drive(data_count, 0x00))
dut.u2h_write_enable = 1
yield(sata.wait_clocks(10000))
 
dut.log.info("Wrote %d piece of data to SATA" % data_count)
 
 
141,14 → 145,18
 
length = 400
address = 0x00
dut.u2h_write_enable = 1
yield(sata.wait_clocks(800))
 
dut.write_count = length
dut.write_enable = 1
dut.u2h_write_enable = 1
dut.u2h_write_count = length
#dut.h2u_read_enable = 1
dut.sector_address = address
#What does this do?
#dut.write_count = length
#dut.write_enable = 1
#dut.u2h_write_enable = 1
#dut.u2h_write_count = length
##dut.h2u_read_enable = 1
#dut.sector_address = address
##What does this do?
yield(sata.write_to_hard_drive(length, address))
 
dut.sector_count = 0
dut.write_data_en = 1
yield(sata.wait_clocks(1))
157,7 → 165,7
dut.hold = 1
yield(sata.wait_clocks(200))
dut.hold = 0
yield(sata.wait_clocks(400))
yield(sata.wait_clocks(200))
dut.hold = 1
yield(sata.wait_clocks(300))
dut.hold = 0
165,11 → 173,11
 
dut.write_enable = 0
dut.write_count = 0
yield(sata.wait_clocks(100))
yield(sata.wait_clocks(2000))
#dut.h2u_read_enable = 0
dut.log.info("Wrote %d piece of data to SATA" % length)
 
@cocotb.test(skip = True)
@cocotb.test(skip = False)
def long_write_with_hard_back_preassure_test(dut):
"""
Description:
192,21 → 200,21
dut.write_count = length
dut.write_enable = 1
dut.u2h_write_enable = 1
dut.u2h_write_count = length
yield(sata.wait_clocks(1000))
#dut.u2h_write_count = length
#dut.h2u_read_enable = 1
dut.sector_address = address
#What does this do?
dut.sector_count = 0
dut.write_data_en = 1
yield(sata.wait_clocks(1))
dut.write_data_en = 0
#dut.write_data_en = 1
yield(sata.write_to_hard_drive(length, address))
yield(sata.wait_clocks(2500))
dut.hold = 1
yield(sata.wait_clocks(1))
dut.hold = 0
yield(sata.wait_clocks(400))
yield(sata.wait_clocks(394))
dut.hold = 1
yield(sata.wait_clocks(10))
yield(sata.wait_clocks(9))
dut.hold = 0
yield(sata.wait_clocks(400))
dut.hold = 1
225,7 → 233,7
#dut.h2u_read_enable = 0
dut.log.info("Wrote %d piece of data to SATA" % length)
 
@cocotb.test(skip = False)
@cocotb.test(skip = True)
def long_write_long_read_back_preassure_test(dut):
"""
Description:
/trunk/rtl/phy/oob_controller.v
31,21 → 31,24
input clk,
 
input platform_ready, //the underlying physical platform is
output reg platform_error, //Underlyaing physal platform received an error, this should probably be a reset
output reg linkup, //link is finished
 
output reg tx_comm_reset, //send a init OOB signal
output reg tx_comm_wake, //send a wake OOB signal
input tx_oob_complete, //Phy has said we are finished with this OOB transaction
 
input comm_init_detect, //detected an init
input comm_wake_detect, //detected a wake on the rx lines
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
input rx_is_elec_idle,
input rx_byte_is_aligned,
input phy_error,
 
output reg [31:0] tx_dout,
output reg tx_isk,
output reg tx_is_k,
output reg tx_set_elec_idle,
output [3:0] lax_state
 
65,15 → 68,17
parameter SEND_WAKE = 4'h5;
parameter WAIT_FOR_WAKE = 4'h6;
parameter WAIT_FOR_NO_WAKE = 4'h7;
parameter WAIT_FOR_ALIGN = 4'h8;
parameter SEND_ALIGN = 4'h9;
parameter DETECT_SYNC = 4'hA;
parameter READY = 4'hB;
parameter WAIT_FOR_IDLE = 4'h8;
parameter WAIT_FOR_ALIGN = 4'h9;
parameter SEND_ALIGN = 4'hA;
parameter DETECT_SYNC = 4'hB;
parameter READY = 4'hC;
 
//Registers/Wires
reg [3:0] state;
reg [31:0] timer;
reg [1:0] no_align_count;
reg [3:0] retries;
 
//timer used to send 'INITs', WAKEs' and read them
wire timeout;
83,8 → 88,10
//Submodules
//Asynchronous Logic
assign timeout = (timer == 0);
assign align_detected = ((rx_isk > 0) && (rx_din == `PRIM_ALIGN) && rx_byte_is_aligned);
assign sync_detected = ((rx_isk > 0) && (rx_din == `PRIM_SYNC));
//assign align_detected = ((rx_is_k > 0) && (rx_din == `PRIM_ALIGN) && !phy_error);
//assign align_detected = ((rx_is_k > 0) && (rx_din == `PRIM_ALIGN));
assign align_detected = ((rx_is_k > 0) && (rx_din == `PRIM_ALIGN) && rx_byte_is_aligned);
assign sync_detected = ((rx_is_k > 0) && (rx_din == `PRIM_SYNC));
assign lax_state = state;
 
//Synchronous Logic
97,12 → 104,14
state <= IDLE;
linkup <= 0;
timer <= 0;
tx_comm_reset <= 1;
tx_comm_reset <= 0;
tx_comm_wake <= 0;
tx_dout <= 0;
tx_isk <= 0;
tx_is_k <= 0;
tx_set_elec_idle <= 1;
no_align_count <= 0;
platform_error <= 0;
retries <= 0;
end
else begin
//to support strobes, continuously reset the following signals
109,7 → 118,7
tx_comm_reset <= 0;
tx_comm_wake <= 0;
 
tx_isk <= 0;
tx_is_k <= 0;
 
 
//timer (when reache 0 timeout has occured)
120,6 → 129,7
//main state machine, if this reaches ready an initialization sequence has completed
case (state)
IDLE: begin
platform_error <= 0;
linkup <= 0;
tx_set_elec_idle <= 1;
if (platform_ready) begin
129,6 → 139,7
// DCM has generated the correct clocks
timer <= 32'h000000A2;
state <= SEND_RESET;
tx_comm_reset <= 1;
end
end
SEND_RESET: begin
137,9 → 148,8
//SATA hard drive, or reset it so that it can be initiated to state
 
//strobe the comm init so that the platform will send an INIT OOB signal
tx_comm_reset <= 1;
if (timeout) begin
timer <= 32'd`INITIALIZE_TIMEOUT;
if (timeout || tx_oob_complete) begin
timer <= `INITIALIZE_TIMEOUT;
state <= WAIT_FOR_INIT;
$display ("oob_controller: wait for INIT");
end
149,7 → 159,8
//go back to the SEND_RESET state
if (comm_init_detect) begin
//HD said 'sup' go to a wake
timer <= 0;
//timer <= 0;
timer <= 32'h00001000;
state <= WAIT_FOR_NO_INIT;
$display ("oob_controller: wait for INIT to go low");
end
160,7 → 171,7
end
WAIT_FOR_NO_INIT: begin
//wait for the init signal to go low from the device
if (!comm_init_detect) begin
if (!comm_init_detect && (timeout || tx_oob_complete)) begin
$display ("oob_controller: INIT deasserted");
$display ("oob_controller: start configuration");
state <= WAIT_FOR_CONFIGURE_END;
170,15 → 181,15
$display ("oob_controller: System is configured");
state <= SEND_WAKE;
timer <= 32'h0000009B;
tx_comm_wake <= 1;
//end
end
SEND_WAKE: begin
//XXX: In the groundhog COMM WAKE was continuously send for a long period of time
//Send the WAKE sequence to the hard drive to initiate a wakeup sequence
tx_comm_wake <= 1;
//XXX: Is this timeout correct?
//880uS
if (timeout) begin
if (timeout || tx_oob_complete) begin
//timer <= 32'd`INITIALIZE_TIMEOUT;
timer <= 32'h000203AD;
state <= WAIT_FOR_WAKE;
206,10 → 217,30
$display ("oob_controller: detected WAKE deasserted");
$display ("oob_controller: Send Dialtone, wait for ALIGN");
//Going to add more timeout
timer <= 32'h203AD;
state <= WAIT_FOR_ALIGN;
//timer <= 32'h0203AD;
timer <= 32'h0203AD;
state <= WAIT_FOR_ALIGN;
//state <= WAIT_FOR_IDLE;
retries <= 4;
end
end
/*
WAIT_FOR_IDLE: begin
if (!rx_is_elec_idle) begin
state <= WAIT_FOR_ALIGN;
timer <= 32'h0101D0;
end
else if (timeout) begin
if (retries > 0) begin
timer <= 32'h0203AD;
retries <= retries - 1;
end
if (retries == 0) begin
state <= IDLE;
end
end
end
*/
WAIT_FOR_ALIGN: begin
//transmit the 'dialtone' continuously
//since we need to start sending actual data (not OOB signals, get out
217,7 → 248,8
tx_set_elec_idle <= 0;
//a sequence of 0's and 1's
tx_dout <= `DIALTONE;
tx_isk <= 0;
tx_is_k <= 0;
//$display ("rx din: %h, k: %h", rx_din, rx_is_k);
if (align_detected) begin
//we got something from the device!
timer <= 0;
235,7 → 267,7
end
SEND_ALIGN: begin
tx_dout <= `PRIM_ALIGN;
tx_isk <= 1;
tx_is_k <= 1;
if (!align_detected) begin
$display ("oob_controller: detected ALIGN deasserted");
//XXX: Groundhog detects the SYNC primitve before declaring linkup
244,7 → 276,7
state <= READY;
end
else begin
no_align_count <= no_align_count + 1;
no_align_count <= no_align_count + 2'b01;
end
end
end
254,13 → 286,18
end
end
READY: begin
linkup <= 1;
linkup <= 1;
/*
if (phy_error) begin
platform_error <= 1;
end
*/
if (comm_init_detect) begin
state <= IDLE;
end
end
default: begin
state <= IDLE;
state <= IDLE;
end
endcase
 
/trunk/rtl/phy/sata_phy_layer.v
31,27 → 31,29
input clk,
 
input platform_ready, //the underlying physical platform is
output platform_error,
output linkup, //link is finished
 
output [31:0] tx_dout,
output tx_isk,
output tx_is_k,
output tx_comm_reset,
output tx_comm_wake,
output tx_elec_idle,
input tx_oob_complete,
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
input rx_elec_idle,
input rx_byte_is_aligned,
 
input comm_init_detect,
input comm_wake_detect,
 
output phy_ready,
input phy_error,
output [3:0] lax_state
 
);
 
 
//Parameters
parameter NOT_READY = 4'h0;
parameter SEND_FIRST_ALIGN = 4'h1;
64,90 → 66,94
 
//OOB Control
wire [31:0] oob_tx_dout;
wire oob_tx_isk;
wire oob_tx_is_k;
 
//Phy Control
wire [31:0] phy_tx_dout;
wire phy_tx_isk;
wire align_detected;
wire phy_tx_is_k;
//wire align_detected;
wire oob_platform_error;
reg phy_platform_error;
 
 
 
//Submodules
oob_controller oob (
.rst (rst),
.clk (clk),
.rst (rst ),
.clk (clk ),
 
//OOB controller
.platform_ready (platform_ready),
.linkup (linkup),
.phy_error (phy_error ),
.platform_ready (platform_ready ),
.platform_error (oob_platform_error ),
.linkup (linkup ),
 
//Platform Control
.tx_dout (oob_tx_dout),
.tx_isk (oob_tx_isk),
.tx_comm_reset (tx_comm_reset),
.tx_comm_wake (tx_comm_wake),
.tx_set_elec_idle (tx_elec_idle),
.tx_dout (oob_tx_dout ),
.tx_is_k (oob_tx_is_k ),
.tx_comm_reset (tx_comm_reset ),
.tx_comm_wake (tx_comm_wake ),
.tx_set_elec_idle (tx_elec_idle ),
.tx_oob_complete (tx_oob_complete ),
 
.rx_din (rx_din),
.rx_isk (rx_isk),
.comm_init_detect (comm_init_detect),
.comm_wake_detect (comm_wake_detect),
.rx_byte_is_aligned (rx_byte_is_aligned),
.rx_is_elec_idle (rx_elec_idle),
.lax_state (lax_state)
.rx_din (rx_din ),
.rx_is_k (rx_is_k ),
.comm_init_detect (comm_init_detect ),
.comm_wake_detect (comm_wake_detect ),
.rx_is_elec_idle (rx_elec_idle ),
.rx_byte_is_aligned (rx_byte_is_aligned ),
.lax_state (lax_state )
 
);
 
//Asynchronous Logic
assign tx_dout = !linkup ? oob_tx_dout : phy_tx_dout;
assign tx_isk = !linkup ? oob_tx_isk : phy_tx_isk;
assign tx_is_k = !linkup ? oob_tx_is_k : phy_tx_is_k;
 
assign phy_tx_dout = `PRIM_ALIGN;
assign phy_tx_isk = 1;
assign phy_tx_is_k = 1;
 
assign align_detected = ((rx_isk > 0) && (rx_din == `PRIM_ALIGN) && rx_byte_is_aligned);
//assign align_detected = ((rx_is_k > 0) && (rx_din == `PRIM_ALIGN) && !phy_error);
//assign phy_ready = ((state == READY) && (!align_detected));
assign phy_ready = (state == READY);
assign platform_error = oob_platform_error || phy_platform_error;
 
 
 
//Synchronous Logic
always @ (posedge clk) begin
if (rst) begin
state <= NOT_READY;
align_count <= 0;
phy_platform_error<= 0;
end
else begin
if (state == READY) begin
align_count <= align_count + 1;
align_count <= align_count + 8'h01;
end
case (state)
NOT_READY: begin
align_count <= 0;
align_count <= 0;
phy_platform_error <= 0;
if (linkup) begin
`ifdef VERBOSE
$display ("sata_phy_layer: linkup! send aligns");
`endif
state <= SEND_FIRST_ALIGN;
state <= SEND_FIRST_ALIGN;
end
end
SEND_FIRST_ALIGN: begin
state <= SEND_SECOND_ALIGN;
state <= SEND_SECOND_ALIGN;
end
SEND_SECOND_ALIGN: begin
state <= READY;
state <= READY;
end
READY: begin
if (align_count == 255) begin
state <= SEND_FIRST_ALIGN;
state <= SEND_FIRST_ALIGN;
`ifdef VERBOSE
$display ("sata_phy_layer: linkup! send alignment dwords");
`else
$display ("sata_phy_layer: .");
`endif
//Send an align primitive
end
if (phy_error) begin
phy_platform_error <= 1;
end
end
default: begin
end
/trunk/rtl/sata_stack.v
33,29 → 33,30
input data_out_clk_valid,
 
input platform_ready, //the underlying physical platform is
output wire linkup, //link is finished
output sata_ready,
output sata_init,
output platform_error, //Underlying platform errored out, the
//clock is misaligned, stack should
//probably be reset
output linkup, //link is finished
 
input send_sync_escape,
input [15:0] user_features,
input [15:0] user_features,
 
//User Interface
output busy,
output error,
output sata_ready,
output sata_busy,
 
output hard_drive_error,
 
input write_data_en,
input single_rdwr,
input read_data_en,
// input write_data_stb,
// input read_data_stb,
 
input send_user_command_stb,
input soft_reset_en,
input [7:0] command,
input execute_command_stb,
input command_layer_reset,
input [7:0] hard_drive_command,
output pio_data_ready,
 
input [15:0] sector_count,
input [47:0] sector_address,
input [15:0] sector_count,
input [47:0] sector_address,
 
 
output dma_activate_stb,
63,32 → 64,30
output pio_setup_stb,
output d2h_data_stb,
output dma_setup_stb,
output wire set_device_bits_stb,
output set_device_bits_stb,
 
output dbg_send_command_stb,
output dbg_send_control_stb,
output dbg_send_data_stb,
 
output [7:0] d2h_fis,
output d2h_interrupt,
output d2h_notification,
output [3:0] d2h_port_mult,
output [7:0] d2h_device,
output [47:0] d2h_lba,
output [15:0] d2h_sector_count,
output [7:0] d2h_status,
output [7:0] d2h_error,
output [3:0] d2h_port_mult,
output [7:0] d2h_device,
output [47:0] d2h_lba,
output [15:0] d2h_sector_count,
output [7:0] d2h_status,
output [7:0] d2h_error,
 
input [31:0] user_din,
input [31:0] user_din,
input user_din_stb,
output [1:0] user_din_ready,
input [1:0] user_din_activate,
output [23:0] user_din_size,
output [1:0] user_din_ready,
input [1:0] user_din_activate,
output [23:0] user_din_size,
output user_din_empty,
 
output [31:0] user_dout,
output [31:0] user_dout,
output user_dout_ready,
input user_dout_activate,
input user_dout_stb,
output [23:0] user_dout_size,
output [23:0] user_dout_size,
 
 
output transport_layer_ready,
98,65 → 97,33
//Buffer
//Platform Interface
output [31:0] tx_dout,
output tx_isk,
output tx_is_k, //Connect All 4 'tx_is_k'to this signal
output tx_comm_reset,
output tx_comm_wake,
output tx_elec_idle,
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
input rx_elec_idle,
input rx_byte_is_aligned,
input comm_init_detect,
input comm_wake_detect,
input rx_byte_is_aligned,
input tx_oob_complete,
input phy_error,
 
 
//Debug
output dbg_remote_abort,
output dbg_xmit_error,
output dbg_read_crc_error,
 
//PIO
output dbg_pio_response,
output dbg_pio_direction,
output [15:0] dbg_pio_transfer_count,
output [7:0] dbg_pio_e_status,
 
//Host dbg_ to Device Regster Values
output [7:0] dbg_h2d_command,
output [15:0] dbg_h2d_features,
output [7:0] dbg_h2d_control,
output [3:0] dbg_h2d_port_mult,
output [7:0] dbg_h2d_device,
output [47:0] dbg_h2d_lba,
output [15:0] dbg_h2d_sector_count,
 
//DMA Specific Control
 
//Data Control
output dbg_cl_if_ready,
output dbg_cl_if_activate,
output [23:0] dbg_cl_if_size,
output dbg_cl_if_strobe,
output [31:0] dbg_cl_if_data,
output [3:0] dbg_cc_lax_state,
output [3:0] dbg_cw_lax_state,
 
output [1:0] dbg_cl_of_ready,
output [1:0] dbg_cl_of_activate,
output dbg_cl_of_strobe,
output [31:0] dbg_cl_of_data,
output [23:0] dbg_cl_of_size,
output [3:0] dbg_t_lax_state,
 
output [3:0] dbg_cc_lax_state,
output [3:0] dbg_cr_lax_state,
output [3:0] dbg_cw_lax_state,
output [3:0] dbg_li_lax_state,
output [3:0] dbg_lr_lax_state,
output [3:0] dbg_lw_lax_state,
output [3:0] dbg_lw_lax_fstate,
 
output [3:0] dbg_t_lax_state,
 
output [3:0] dbg_li_lax_state,
output [3:0] dbg_lr_lax_state,
output [3:0] dbg_lw_lax_state,
output [3:0] dbg_lw_lax_fstate,
 
//Link Layer
input prim_scrambler_en,
input data_scrambler_en,
163,26 → 130,11
 
output dbg_ll_write_ready,
output dbg_ll_paw,
output dbg_ll_write_start,
output dbg_ll_write_strobe,
output dbg_ll_write_finished,
output [31:0] dbg_ll_write_data,
output [31:0] dbg_ll_write_size,
output dbg_ll_write_hold,
output dbg_ll_write_abort,
 
output dbg_ll_read_start,
output dbg_ll_read_strobe,
output [31:0] dbg_ll_read_data,
output dbg_ll_read_ready,
output dbg_ll_read_finished,
output dbg_ll_remote_abort,
output dbg_ll_xmit_error,
 
output dbg_ll_send_crc,
 
//Phy Layer
output [3:0] lax_state,
output [3:0] oob_state,
 
//Primative Detection
output dbg_detect_sync,
204,10 → 156,10
 
output dbg_send_holda,
 
output [23:0] slw_in_data_addra,
output [12:0] slw_d_count,
output [12:0] slw_write_count,
output [3:0] slw_buffer_pos
output [23:0] slw_in_data_addra,
output [12:0] slw_d_count,
output [12:0] slw_write_count,
output [3:0] slw_buffer_pos
);
 
//Parameters
237,7 → 189,7
wire ll_write_strobe;
wire ll_write_finished;
wire [31:0] ll_write_data;
wire [31:0] ll_write_size;
wire [23:0] ll_write_size;
wire ll_write_hold;
wire ll_write_abort;
 
252,11 → 204,11
wire ll_xmit_error;
 
wire [31:0] ll_tx_dout;
wire ll_tx_isk;
wire ll_tx_is_k;
 
//Phy Layer
wire [31:0] phy_tx_dout;
wire phy_tx_isk;
wire phy_tx_is_k;
 
//User Interface state machine
 
271,7 → 223,6
wire [47:0] h2d_lba;
wire [15:0] h2d_sector_count;
 
 
wire remote_abort;
wire xmit_error;
wire read_crc_error;
295,7 → 246,6
wire [31:0] cl_of_data;
wire [23:0] cl_of_size;
 
 
//Link Layer Interface
wire t_sync_escape;
wire t_write_start;
302,7 → 252,7
wire t_write_strobe;
wire t_write_finished;
wire [31:0] t_write_data;
wire [31:0] t_write_size;
wire [23:0] t_write_size;
wire t_write_hold;
wire t_write_abort;
wire t_xmit_error;
314,7 → 264,6
wire t_read_finished;
wire t_read_crc_ok;
wire t_remote_abort;
 
//Comand Layer registers
 
//Submodules
328,20 → 277,18
.data_out_clk_valid (data_out_clk_valid ),
 
//Application Interface
.sata_init (sata_init ),
.command_layer_ready (sata_ready ),
.busy (busy ),
.dev_error (error ),
.sata_busy (sata_busy ),
.hard_drive_error (hard_drive_error ),
.send_sync_escape (send_sync_escape ),
.user_features (user_features ),
 
.write_data_en (write_data_en ),
.single_rdwr (single_rdwr ),
.read_data_en (read_data_en ),
// .write_data_stb (write_data_stb ),
// .read_data_stb (read_data_stb ),
.execute_command_stb (execute_command_stb ),
 
.send_user_command_stb(send_user_command_stb ),
.soft_reset_en (soft_reset_en ),
.command (command ),
.command_layer_reset (command_layer_reset ),
.hard_drive_command (hard_drive_command ),
.pio_data_ready (pio_data_ready ),
 
.sector_count (sector_count ),
352,6 → 299,7
.user_din_ready (user_din_ready ),
.user_din_activate (user_din_activate ),
.user_din_size (user_din_size ),
.user_din_empty (user_din_empty ),
 
.user_dout (user_dout ),
.user_dout_ready (user_dout_ready ),
418,15 → 366,10
.t_of_size (of_size ),
 
.cl_c_state (dbg_cc_lax_state ),
.cl_r_state (dbg_cr_lax_state ),
.cl_w_state (dbg_cw_lax_state )
 
 
 
);
 
 
 
//Transport Layer
sata_transport_layer stl (
.rst (rst | !linkup ),
468,6 → 411,7
.h2d_sector_count (h2d_sector_count ),
 
//Device to Host Register Values
.d2h_fis (d2h_fis ),
.d2h_interrupt (d2h_interrupt ),
.d2h_notification (d2h_notification ),
.d2h_port_mult (d2h_port_mult ),
552,10 → 496,10
.phy_ready (phy_ready ),
.platform_ready (platform_ready ),
.tx_dout (ll_tx_dout ),
.tx_isk (ll_tx_isk ),
.tx_is_k (ll_tx_is_k ),
 
.rx_din (rx_din ),
.rx_isk (rx_isk ),
.rx_is_k (rx_is_k ),
.is_device (1'b0 ),
 
//Primative Detection
603,23 → 547,26
 
//Control/Status
.platform_ready (platform_ready ),
.platform_error (platform_error ),
.linkup (linkup ),
 
//Platform Interface
.tx_dout (phy_tx_dout ),
.tx_isk (phy_tx_isk ),
.tx_is_k (phy_tx_is_k ),
.tx_comm_reset (tx_comm_reset ),
.tx_comm_wake (tx_comm_wake ),
.tx_elec_idle (tx_elec_idle ),
.tx_oob_complete (tx_oob_complete ),
 
.rx_din (rx_din ),
.rx_isk (rx_isk ),
.rx_is_k (rx_is_k ),
.comm_init_detect (comm_init_detect ),
.comm_wake_detect (comm_wake_detect ),
.rx_elec_idle (rx_elec_idle ),
.rx_byte_is_aligned (rx_byte_is_aligned ),
.phy_error (phy_error ),
 
.lax_state (lax_state ),
.lax_state (oob_state ),
.phy_ready (phy_ready )
);
 
628,41 → 575,25
//Asynchronous Logic
 
//control of data to the platform controller
//In order to send align primitives the phy must sometimes take over the bus
assign tx_dout = (phy_ready) ? ll_tx_dout : phy_tx_dout;
assign tx_isk = (phy_ready) ? ll_tx_isk : phy_tx_isk;
assign tx_is_k = (phy_ready) ? ll_tx_is_k : phy_tx_is_k;
 
//no activity on the stack
 
//Debug
assign ll_write_start = t_write_start;
assign dbg_ll_write_start = t_write_start;
assign ll_write_data = t_write_data;
assign dbg_ll_write_data = t_write_data;
assign ll_write_hold = t_write_hold;
assign dbg_ll_write_hold = t_write_hold;
assign ll_write_size = t_write_size;
assign dbg_ll_write_size = t_write_size;
assign ll_write_abort = t_write_abort;
assign dbg_ll_write_abort = t_write_abort;
 
assign ll_read_ready = t_read_ready;
assign dbg_ll_read_ready = t_read_ready;
assign ll_sync_escape = t_sync_escape;
 
assign dbg_ll_write_strobe = ll_write_strobe;
assign t_write_strobe = ll_write_strobe;
 
assign dbg_ll_write_finished = ll_write_finished;
assign t_write_finished = ll_write_finished;
 
 
assign dbg_ll_read_strobe = ll_read_strobe;
assign dbg_ll_read_start = ll_read_start;
assign dbg_ll_read_finished = ll_read_finished;
assign dbg_ll_read_data = ll_read_data;
assign dbg_ll_remote_abort = ll_remote_abort;
assign dbg_ll_xmit_error = ll_xmit_error;
 
assign t_read_strobe = ll_read_strobe;
assign t_read_start = ll_read_start;
assign t_read_finished = ll_read_finished;
671,44 → 602,17
assign t_xmit_error = ll_xmit_error;
assign t_read_crc_ok = ll_read_crc_ok;
 
assign dbg_send_command_stb = send_command_stb;
assign dbg_send_control_stb = send_control_stb;
assign dbg_send_data_stb = send_data_stb;
 
assign dbg_remote_abort = remote_abort;
assign dbg_xmit_error = xmit_error;
assign dbg_read_crc_error = read_crc_error;
 
assign dbg_h2d_command = h2d_command;
assign dbg_h2d_features = h2d_features;
assign dbg_h2d_control = h2d_control;
assign dbg_h2d_port_mult = h2d_port_mult;
assign dbg_h2d_device = h2d_device;
assign dbg_h2d_sector_count = h2d_sector_count;
 
 
assign cl_if_ready = if_ready;
assign dbg_cl_if_activate = cl_if_activate;
assign if_activate = cl_if_activate;
assign dbg_cl_if_size = if_size;
assign cl_if_size = if_size;
assign dbg_cl_if_strobe = cl_if_strobe;
assign if_strobe = cl_if_strobe;
assign dbg_cl_if_data = if_data;
assign cl_if_data = if_data;
 
assign cl_of_ready = of_ready;
assign dbg_cl_of_ready = of_ready;
assign of_activate = cl_of_activate;
assign dbg_cl_of_activate = cl_of_activate;
assign of_strobe = cl_of_strobe;
assign dbg_cl_of_strobe = cl_of_strobe;
assign of_data = cl_of_data;
assign dbg_cl_of_data = cl_of_data;
assign cl_of_size = of_size;
assign dbg_cl_of_size = of_size;
 
 
 
//Synchronous Logic
endmodule
/trunk/rtl/sata_defines.v
26,7 → 26,7
`define __SATA_DEFINES__
 
//Presuming 75MHz clock
`define CLOCK_RATE (75000000)
`define SATA_CLOCK_RATE (75000000)
// 1 / 880uS = 1136 times per seconds
`define NORMAL_TIMEOUT (1000000) / 880
 
36,7 → 36,7
`define FIFO_ADDRESS_WIDTH 11
 
//880uS
//`define INITIALIZE_TIMEOUT ((`CLOCK_RATE) / (`NORMAL_TIMEOUT))
//`define INITIALIZE_TIMEOUT ((`SATA_CLOCK_RATE) / (`NORMAL_TIMEOUT))
`define INITIALIZE_TIMEOUT 66000
//`define SEND_WAKE_TIMEOUT 4E
 
/trunk/rtl/generic/ppfifo.v
58,7 → 58,6
localparam FIFO_DEPTH = (1 << ADDRESS_WIDTH);
 
//Local Registers/Wires
assign write_fifo_size = FIFO_DEPTH;
 
//Write Side
wire ppfifo_ready; // The write side only needs to
86,27 → 85,6
reg [4:0] w_reset_timeout;
wire ready;
 
//assign r_wselect = (write_activate == 2'b00) ? 1'b0 :
// (write_activate == 2'b01) ? 1'b0 :
// (write_activate == 2'b10) ? 1'b1 :
// reset ? 1'b0 :
// r_wselect;
// //I know this can be shortened down but it's more
// //readible thi way
 
assign addr_in = {r_wselect, write_address};
//assign write_enable = (write_activate > 0) && write_strobe;
assign ppfifo_ready = !(w_reset || r_reset);
assign ready = ppfifo_ready;
 
//assign wcc_tie_select = (wcc_read_ready == 2'b00) ? 1'b0 :
// (wcc_read_ready == 2'b01) ? 1'b0 :
// (wcc_read_ready == 2'b10) ? 1'b1 :
// wcc_tie_select;
// If the first FIFO is ready,
// then both FIFOs are ready then
// keep the first FIFO
 
//Read Side
wire [ADDRESS_WIDTH: 0] addr_out; //Actual address to the BRAM
reg r_reset;
140,24 → 118,49
wire [DATA_WIDTH - 1: 0] w_read_data; //data from the read FIFO
reg [DATA_WIDTH - 1: 0] r_read_data; //data from the read FIFO
 
 
 
//assign r_wselect = (write_activate == 2'b00) ? 1'b0 :
// (write_activate == 2'b01) ? 1'b0 :
// (write_activate == 2'b10) ? 1'b1 :
// reset ? 1'b0 :
// r_wselect;
// //I know this can be shortened down but it's more
// //readible thi way
 
assign write_fifo_size = FIFO_DEPTH;
 
assign addr_in = {r_wselect, write_address};
//assign write_enable = (write_activate > 0) && write_strobe;
assign ppfifo_ready = !(w_reset || r_reset);
assign ready = ppfifo_ready;
 
//assign wcc_tie_select = (wcc_read_ready == 2'b00) ? 1'b0 :
// (wcc_read_ready == 2'b01) ? 1'b0 :
// (wcc_read_ready == 2'b10) ? 1'b1 :
// wcc_tie_select;
// If the first FIFO is ready,
// then both FIFOs are ready then
// keep the first FIFO
 
assign addr_out = {r_rselect, r_address};
 
 
//Debug
wire [23:0] debug_f0_w_count;
wire [23:0] debug_f1_w_count;
//wire [23:0] debug_f0_w_count;
//wire [23:0] debug_f1_w_count;
 
wire [23:0] debug_f0_r_size;
wire [23:0] debug_f1_r_size;
//wire [23:0] debug_f0_r_size;
//wire [23:0] debug_f1_r_size;
 
//wire [23:0] debug_f0_r_count;
//wire [23:0] debug_f1_r_count;
 
assign debug_f0_w_count = w_count[0];
assign debug_f1_w_count = w_count[1];
//assign debug_f0_w_count = w_count[0];
//assign debug_f1_w_count = w_count[1];
 
assign debug_f0_r_size = r_size[0];
assign debug_f1_r_size = r_size[1];
//assign debug_f0_r_size = r_size[0];
//assign debug_f1_r_size = r_size[1];
 
assign inactive = (w_count[0] == 0) &&
(w_count[1] == 0) &&
291,8 → 294,8
w_reset_timeout <= 0;
end
else begin
if (w_reset && (w_reset_timeout < 4'h4)) begin
w_reset_timeout <= w_reset_timeout + 1;
if (w_reset && (w_reset_timeout < 5'h4)) begin
w_reset_timeout <= w_reset_timeout + 5'h1;
end
else begin
w_reset <= 0;
306,8 → 309,8
r_reset_timeout <= 0;
end
else begin
if (r_reset && (r_reset_timeout < 4'h4)) begin
r_reset_timeout <= r_reset_timeout + 1;
if (r_reset && (r_reset_timeout < 5'h4)) begin
r_reset_timeout <= r_reset_timeout + 5'h1;
end
else begin
r_reset <= 0;
/trunk/rtl/transport/sata_transport_layer.v
66,6 → 66,7
input [15:0] h2d_sector_count,
 
//Device to Host Registers
output reg [7:0] d2h_fis,
output reg d2h_interrupt,
output reg d2h_notification,
output reg [3:0] d2h_port_mult,
100,7 → 101,7
input ll_write_strobe,
input ll_write_finished,
output [31:0] ll_write_data,
output [31:0] ll_write_size,
output [23:0] ll_write_size,
output ll_write_hold,
output ll_write_abort,
input ll_xmit_error,
136,9 → 137,9
 
//Registers/Wires
reg [3:0] fis_id_state;
reg [7:0] current_fis;
reg [3:0] state;
reg detect_fis;
reg [7:0] current_fis;
wire processing_fis;
 
//data direction
159,7 → 160,7
 
reg reg_write_start;
wire [31:0] reg_write_data;
wire [31:0] reg_write_size;
wire [23:0] reg_write_size;
reg reg_write_ready;
wire reg_write_hold;
wire reg_write_abort;
177,7 → 178,7
reg data_write_start;
wire data_write_strobe;
wire data_read_strobe;
wire [31:0] data_write_size;
wire [23:0] data_write_size;
wire [31:0] data_write_data;
wire data_write_hold;
wire data_write_abort;
185,8 → 186,10
reg data_read_ready;
reg send_data_fis_id;
 
reg ll_write_finished_en;
 
 
 
//Asnchronous Logic
assign lax_state = state;
assign transport_layer_ready = (state == IDLE) && link_layer_ready;
199,26 → 202,25
assign ll_write_start = (reg_write) ? reg_write_start : data_write_start;
assign ll_write_data = (reg_write) ? register_fis[register_fis_ptr] : data_write_data;
assign ll_write_size = (reg_write) ? reg_write_size : data_write_size;
assign ll_write_hold = (reg_write) ? 0 : data_write_hold;
assign ll_write_abort = (reg_write) ? 0 : data_write_abort;
assign cl_if_strobe = (reg_write) ? 0 : (!send_data_fis_id && data_write_strobe);
assign ll_write_hold = (reg_write) ? 1'b0 : data_write_hold;
assign ll_write_abort = (reg_write) ? 1'b0 : data_write_abort;
assign cl_if_strobe = (reg_write) ? 1'b0 : (!send_data_fis_id && data_write_strobe);
 
//Read Control
assign ll_read_ready = (reg_read) ? 1 : data_read_ready;
assign cl_of_strobe = (reg_read) ? 0 : ((state == READ_DATA) && data_read_strobe);
assign ll_read_ready = (reg_read) ? 1'b1 : data_read_ready;
assign cl_of_strobe = (reg_read) ? 1'b0 : ((state == READ_DATA) && data_read_strobe);
assign cl_of_data = ll_read_data;
 
//Data Register Write Control Signals
assign data_write_data = (send_data_fis_id) ? `FIS_DATA : cl_if_data;
assign data_write_data = (send_data_fis_id) ? {24'h000, `FIS_DATA} : cl_if_data;
//the first DWORD is the FIS ID
assign data_write_size = (cl_if_size + 1);
//assign data_write_size = cl_if_size;
assign data_write_size = cl_if_size + 24'h1;
//Add 1 to the size so that there is room for the FIS ID
assign data_write_strobe = ll_write_strobe;
assign data_read_strobe = ll_read_strobe;
assign data_write_hold = 0;
assign data_write_hold = 1'b0;
//There should never be a hold on the data becuase the CL will set it up
assign data_write_abort = 0;
assign data_write_abort = 1'b0;
assign read_crc_error = !ll_read_crc_ok;
 
 
225,8 → 227,8
//H2D Register Write control signals
assign reg_write_strobe = ll_write_strobe;
assign reg_write_size = `FIS_H2D_REG_SIZE;
assign reg_write_hold = 0;
assign reg_write_abort = 0;
assign reg_write_hold = 1'b0;
assign reg_write_abort = 1'b0;
assign reg_write = (state == WRITE_H2D_REG) || (send_command_stb || send_control_stb);
 
//D2H Register Read control signals
258,41 → 260,43
//FIS ID State machine
always @ (posedge clk) begin
if (rst) begin
fis_id_state <= IDLE;
detect_fis <= 0;
current_fis <= 0;
fis_id_state <= IDLE;
detect_fis <= 0;
current_fis <= 0;
d2h_fis <= 0;
end
else begin
//in order to set all the detect_* high when the actual fis is detected send this strobe
if(ll_read_finished) begin
current_fis <= 0;
fis_id_state <= IDLE;
current_fis <= 0;
fis_id_state <= IDLE;
end
else begin
case (fis_id_state)
IDLE: begin
current_fis <= 0;
detect_fis <= 0;
current_fis <= 0;
detect_fis <= 0;
if (ll_read_start) begin
detect_fis <= 1;
fis_id_state <= READ_FIS;
detect_fis <= 1;
fis_id_state <= READ_FIS;
end
end
READ_FIS: begin
if (ll_read_strobe) begin
detect_fis <= 0;
detect_fis <= 0;
current_fis <= ll_read_data[7:0];
d2h_fis <= ll_read_data[7:0];
fis_id_state <= WAIT_FOR_END;
end
end
WAIT_FOR_END: begin
if (ll_read_finished) begin
current_fis <= 0;
fis_id_state <= IDLE;
current_fis <= 0;
fis_id_state <= IDLE;
end
end
default: begin
fis_id_state <= IDLE;
fis_id_state <= IDLE;
end
endcase
end
347,11 → 351,12
 
data_write_start <= 0;
 
ll_write_finished_en <= 0;
end
else begin
//Strobed signals
if (phy_ready) begin
//only deassert a link layer strobe when Phy is ready
//only deassert a link layer strobe when Phy is ready and not sending aligns
data_write_start <= 0;
reg_write_start <= 0;
end
388,11 → 393,16
cl_if_activate <= 1;
end
 
if (ll_write_finished) begin
ll_write_finished_en <= 1;
end
 
case (state)
IDLE: begin
register_fis_ptr <= 0;
reg_read_count <= 0;
cmd_bit <= 0;
ll_write_finished_en <= 0;
//Detect a FIS
if(ll_read_start) begin
//detect the start of a frame
424,13 → 434,13
CHECK_FIS_TYPE: begin
if (detect_dma_setup) begin
//XXX: Future work!
reg_read_count <= reg_read_count + 1;
reg_read_count <= reg_read_count + 8'h1;
state <= IDLE;
end
else if (detect_dma_activate) begin
//hard drive is ready to receive data
state <= DMA_ACTIVATE;
reg_read_count <= reg_read_count + 1;
reg_read_count <= reg_read_count + 8'h1;
//state <= IDLE;
end
else if (detect_d2h_data) begin
445,7 → 455,7
d2h_port_mult <= ll_read_data[11:8];
 
state <= READ_D2H_REG;
reg_read_count <= reg_read_count + 1;
reg_read_count <= reg_read_count + 8'h1;
end
else if (detect_pio_setup) begin
//store the error, status, direction interrupt from this read
458,7 → 468,7
d2h_port_mult <= ll_read_data[11:8];
 
state <= READ_PIO_SETUP;
reg_read_count <= reg_read_count + 1;
reg_read_count <= reg_read_count + 8'h1;
end
else if (detect_set_device_bits) begin
//store the error, a subset of the status bit and the interrupt
480,10 → 490,10
WRITE_H2D_REG: begin
if (register_fis_ptr < `FIS_H2D_REG_SIZE) begin
if (reg_write_strobe) begin
register_fis_ptr <= register_fis_ptr + 1;
register_fis_ptr <= register_fis_ptr + 8'h1;
end
end
if (ll_write_finished) begin
if (ll_write_finished_en) begin
if (ll_xmit_error) begin
state <= RETRY;
end
494,6 → 504,7
end
RETRY: begin
if (link_layer_ready) begin
ll_write_finished_en <= 0;
reg_write_start <= 1;
register_fis_ptr <= 0;
state <= WRITE_H2D_REG;
517,7 → 528,7
end
endcase
if (reg_read_stb) begin
reg_read_count <= reg_read_count + 1;
reg_read_count <= reg_read_count + 8'h1;
end
if (ll_read_finished) begin
d2h_reg_stb <= 1;
544,7 → 555,7
end
endcase
if (reg_read_stb) begin
reg_read_count <= reg_read_count + 1;
reg_read_count <= reg_read_count + 8'h1;
end
if (ll_read_finished) begin
pio_setup_stb <= 1;
563,7 → 574,7
if (ll_write_strobe && send_data_fis_id) begin
send_data_fis_id <= 0;
end
if (ll_write_finished) begin
if (ll_write_finished_en) begin
cl_if_activate <= 0;
state <= IDLE;
if (pio_response) begin
/trunk/rtl/link/sata_link_layer_write.v
24,8 → 24,6
 
 
 
//THERE APPEARS TO BE AN ERROR WHEN WRITING TO A HARDDRIVE, IT MANIFESTS AS A CRC ERROR
 
`include "sata_defines.v"
 
`define MIN_HOLDA_TIMEOUT 4
58,15 → 56,15
output reg send_holda,
 
output [31:0] tx_dout,
output tx_isk,
output tx_is_k,
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
 
input write_start,
output reg write_strobe,
input [31:0] write_data,
input [31:0] write_size, //maximum 2048
input [23:0] write_size, //maximum 2048
input write_hold,
output reg write_finished,
output reg xmit_error,
94,8 → 92,9
//fstate
parameter FIRST_DATA = 4'h1;
parameter ENQUEUE = 4'h2;
parameter WRITE_CRC = 4'h3;
parameter WAIT = 4'h4;
parameter LAST_DATA = 4'h3;
parameter WRITE_CRC = 4'h4;
parameter WAIT = 4'h5;
 
//state
parameter WRITE_START = 4'h1;
135,7 → 134,6
//CRC
//XXX: Tie the CRC_EN to the read strobe
wire [31:0] crc_dout;
reg [31:0] crc_data;
 
//Scrambler
reg scr_rst;
209,7 → 207,7
(send_sync) ? `PRIM_SYNC:
bump_buffer[buffer_pos];
 
assign tx_isk = ( send_x_rdy ||
assign tx_is_k = ( send_x_rdy ||
send_sof ||
send_eof ||
send_wtrm ||
233,7 → 231,7
 
 
//Synchronous Logic
//Incomming buffer (this is the buffer afte the scrambler and CRC)
//Incomming buffer (this is the buffer after the scrambler and CRC)
always @ (posedge clk) begin
if (rst) begin
fstate <= IDLE;
244,7 → 242,6
scr_rst <= 1;
wr_en <= 0;
write_strobe <= 0;
crc_data <= 0;
end
else begin
//Strobes
267,46 → 264,44
end
end
FIRST_DATA: begin
//$display ("LLW: Data Size: %d", data_size);
write_strobe <= 1;
wr_en <= 1;
scr_en <= 1;
scr_din <= write_data;
fstate <= ENQUEUE;
if (data_size == 1) begin
fstate <= LAST_DATA;
end
else begin
fstate <= ENQUEUE;
end
end
ENQUEUE: begin
if (data_size == 1) begin
in_data_addra <= in_data_addra + 1;
wr_en <= 1;
scr_en <= 1;
scr_din <= crc_dout;
fstate <= WRITE_CRC;
in_data_addra <= in_data_addra + 24'h1;
wr_en <= 1;
scr_en <= 1;
scr_din <= write_data;
//write_strobe <= 1;
if (in_data_addra < data_size - 2) begin
write_strobe <= 1;
end
else begin
if (in_data_addra < data_size - 1) begin
// if (in_data_addra < data_size) begin
//Put all the data into the FIFO
write_strobe <= 1;
wr_en <= 1;
scr_en <= 1;
in_data_addra <= in_data_addra + 1;
scr_din <= write_data;
end
else begin
//put the CRC into the FIFO
//in_data_addra <= in_data_addra + 1;
wr_en <= 1;
scr_en <= 1;
in_data_addra <= in_data_addra + 1;
scr_din <= crc_dout;
fstate <= WRITE_CRC;
end
fstate <= LAST_DATA;
end
end
LAST_DATA: begin
in_data_addra <= in_data_addra + 24'h1;
wr_en <= 1;
scr_en <= 1;
scr_din <= crc_dout;
fstate <= WRITE_CRC;
end
WRITE_CRC: begin
fstate <= WAIT;
fstate <= WAIT;
end
WAIT: begin
scr_rst <= 1;
scr_rst <= 1;
if (state == WRITE) begin
//Because a transaction is in progress and our write buffer is full we can reset the in address to 0
in_data_addra <= 0;
338,7 → 333,7
else begin
 
if (dhold_delay_cnt < `DHOLD_DELAY) begin
dhold_delay_cnt <= dhold_delay_cnt + 1;
dhold_delay_cnt <= dhold_delay_cnt + 4'h1;
end
else begin
dhold_delay <= 1;
394,6 → 389,7
 
end
else begin
//XXX: Remove Bump Buffer
if ((state == WRITE_START) || ((state != IDLE) && (d_count != write_count))) begin
bump_buffer[3] <= bump_buffer[2];
bump_buffer[2] <= bump_buffer[1];
401,6 → 397,7
bump_buffer[0] <= rd_dout;
d_count <= write_count;
end
//XXX: End Remove Bump Buffer
 
//write_strobe <= 0;
write_finished <= 0;
418,7 → 415,7
`endif
 
if (min_holda_count < `MIN_HOLDA_TIMEOUT) begin
min_holda_count <= min_holda_count + 1;
min_holda_count <= min_holda_count + 4'h1;
end
 
if (phy_ready) begin
456,7 → 453,7
state <= WRITE;
send_sof <= 1;
//bump_buffer[buffer_pos] <= rd_dout;
write_count <= write_count + 1;
write_count <= write_count + 13'h1;
//Send First Read
//read the first packet of data
end
468,7 → 465,7
WRITE: begin
if (!write_ready) begin
if (neg_phy_ready && (buffer_pos == 0)) begin
buffer_pos <= buffer_pos + 1;
buffer_pos <= buffer_pos + 4'h1;
end
 
`ifdef DHOLD_DELAY_EN
491,15 → 488,15
end
 
else begin
if (write_count <= data_size + 1) begin
if (write_count <= data_size + 1) begin //is this data_size + 1 for the CRC?
if (buffer_pos > 0) begin
buffer_pos <= buffer_pos - 1;
if (buffer_pos == 1) begin
write_count <= write_count + 1;
write_count <= write_count + 13'h1;
end
end
else begin
write_count <= write_count + 1;
write_count <= write_count + 13'h1;
end
end
else begin
516,7 → 513,7
`endif
min_holda_count <= 0;
//XXX: I may need this to capture holds at the end of a trnasfer
buffer_pos <= buffer_pos + 1;
buffer_pos <= buffer_pos + 4'h1;
send_holda <= 1;
end
end
/trunk/rtl/link/sata_link_layer_read.v
49,10 → 49,10
input detect_xrdy_xrdy,
 
output [31:0] tx_dout,
output tx_isk,
output tx_is_k,
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
 
output reg read_strobe,
output reg [31:0] read_data,
91,11 → 91,7
 
//CRC
//XXX: Tie the CRC_EN to an incomming data dword
wire crc_en;
wire [31:0] crc_din;
wire [31:0] crc_dout;
reg crc_data;
reg crc_check;
 
reg [31:0] prev_crc;
reg [31:0] prev_data;
110,18 → 106,10
wire [31:0] descr_dout;
 
//SubModules
crc c (
.rst (rst || idle ),
.clk (clk ),
.en (crc_en ),
.din (crc_din ),
.dout (crc_dout )
);
 
scrambler descr (
.rst (rst || idle),
.clk (clk ),
.prim_scrambler (0 ),
.prim_scrambler (1'b0 ),
.en (descr_en ),
.din (rx_din ),
.dout (descr_dout )
140,7 → 128,7
(send_holda) ? `PRIM_HOLDA :
`PRIM_SYNC;
 
assign tx_isk = ( send_r_rdy ||
assign tx_is_k = ( send_r_rdy ||
send_r_ip ||
send_r_err ||
send_r_ok ||
153,12 → 141,11
assign read_finished = detect_eof;
assign read_start = detect_sof;
assign data_valid = (state == READ) &&
(rx_isk == 0) &&
(rx_is_k == 0) &&
(!detect_hold) &&
(!detect_holda) &&
(!detect_align);
 
assign crc_en = data_valid;
assign descr_en = (data_scrambler_en && (detect_sof || data_valid));
assign descr_din = (data_valid) ? rx_din : 32'h00000000;
//assign crc_ok = (prev_data == prev_crc);
/trunk/rtl/link/sata_link_layer.v
42,15 → 42,15
 
//XXX: I probably need some feedback to indicate that there is room to write
output [31:0] tx_dout,
output tx_isk,
output tx_is_k,
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
 
input write_start,
output write_strobe,
input [31:0] write_data,
input [31:0] write_size,
input [23:0] write_size,
input write_hold,
output write_finished,
input write_abort,
122,20 → 122,20
 
wire sli_idle;
wire [31:0] sli_tx_dout;
wire sli_tx_isk;
wire sli_tx_is_k;
 
reg write_en;
wire write_idle;
wire [31:0] slw_tx_dout;
wire slw_tx_isk;
wire slw_tx_is_k;
 
reg read_en;
wire read_idle;
wire [31:0] slr_tx_dout;
wire slr_tx_isk;
wire slr_tx_is_k;
 
wire [31:0] ll_tx_dout;
wire ll_tx_isk;
wire ll_tx_is_k;
 
wire last_prim;
 
155,13 → 155,13
.last_prim (last_prim ),
 
.rx_din (rx_din ),
.rx_isk (rx_isk ),
.rx_is_k (rx_is_k ),
 
.ll_tx_din (ll_tx_dout ),
.ll_tx_isk (ll_tx_isk ),
.ll_tx_is_k (ll_tx_is_k ),
 
.cont_tx_dout (tx_dout ),
.cont_tx_isk (tx_isk ),
.cont_tx_is_k (tx_is_k ),
 
.detect_sync (detect_sync ),
.detect_r_rdy (detect_r_rdy ),
216,9 → 216,9
.post_align_write (post_align_write ),
 
.tx_dout (slw_tx_dout ),
.tx_isk (slw_tx_isk ),
.tx_is_k (slw_tx_is_k ),
.rx_din (rx_din ),
.rx_isk (rx_isk ),
.rx_is_k (rx_is_k ),
 
.xmit_error (xmit_error ),
.wsize_z_error (wsize_z_error ),
255,9 → 255,9
.detect_xrdy_xrdy (detect_xrdy_xrdy ),
 
.tx_dout (slr_tx_dout ),
.tx_isk (slr_tx_isk ),
.tx_is_k (slr_tx_is_k ),
.rx_din (rx_din ),
.rx_isk (rx_isk ),
.rx_is_k (rx_is_k ),
 
.read_ready (read_ready ),
.read_strobe (read_strobe ),
275,7 → 275,7
 
//Asynchronous logic
assign ll_tx_dout = (!read_idle) ? slr_tx_dout : (!write_idle) ? slw_tx_dout : sli_tx_dout;
assign ll_tx_isk = (!read_idle) ? slr_tx_isk : (!write_idle) ? slw_tx_isk : sli_tx_isk;
assign ll_tx_is_k = (!read_idle) ? slr_tx_is_k : (!write_idle) ? slw_tx_is_k : sli_tx_is_k;
 
 
assign sli_tx_dout = (send_pmnack) ? `PRIM_PMNACK :
282,7 → 282,7
(send_pmack) ? `PRIM_PMACK :
`PRIM_SYNC;
 
assign sli_tx_isk = 1;
assign sli_tx_is_k = 1;
 
assign link_layer_ready = (state == IDLE) && read_idle && write_idle;
 
/trunk/rtl/link/cont_controller.v
36,13 → 36,13
 
 
input [31:0] ll_tx_din,
input ll_tx_isk,
input ll_tx_is_k,
 
output [31:0] cont_tx_dout,
output cont_tx_isk,
output cont_tx_is_k,
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
 
output detect_sync,
output detect_r_rdy,
118,39 → 118,39
);
 
//Asynchronous Logic
assign detect_sync = ((rx_isk[0]) && (rx_din == `PRIM_SYNC )) || sync_cont; //sync (normal) == sync(cont)
assign detect_r_rdy = ((rx_isk[0]) && (rx_din == `PRIM_R_RDY )) || r_rdy_cont;
assign detect_r_ip = ((rx_isk[0]) && (rx_din == `PRIM_R_IP )) || r_ip_cont;
assign detect_r_err = ((rx_isk[0]) && (rx_din == `PRIM_R_ERR )) || r_err_cont;
assign detect_r_ok = ((rx_isk[0]) && (rx_din == `PRIM_R_OK )) || r_ok_cont;
assign detect_x_rdy = ((rx_isk[0]) && (rx_din == `PRIM_X_RDY )) || x_rdy_cont;
assign detect_sof = (rx_isk[0]) && (rx_din == `PRIM_SOF );
assign detect_eof = (rx_isk[0]) && (rx_din == `PRIM_EOF );
assign detect_wtrm = ((rx_isk[0]) && (rx_din == `PRIM_WTRM )) || wtrm_cont;
assign detect_cont = (rx_isk[0]) && (rx_din == `PRIM_CONT );
assign detect_hold = ((rx_isk[0]) && (rx_din == `PRIM_HOLD )) || hold_cont; //hold (normal) == hold (cont)
assign detect_holda = ((rx_isk[0]) && (rx_din == `PRIM_HOLDA )) || holda_cont; //holda (normal) == holda (cont)
assign detect_preq_s = ((rx_isk[0]) && (rx_din == `PRIM_PREQ_S )) || pmreq_s_cont;
assign detect_preq_p = ((rx_isk[0]) && (rx_din == `PRIM_PREQ_P )) || pmreq_p_cont;
assign detect_align = (rx_isk[0]) && (rx_din == `PRIM_ALIGN );
assign detect_sync = ((rx_is_k[0]) && (rx_din == `PRIM_SYNC )) || sync_cont; //sync (normal) == sync(cont)
assign detect_r_rdy = ((rx_is_k[0]) && (rx_din == `PRIM_R_RDY )) || r_rdy_cont;
assign detect_r_ip = ((rx_is_k[0]) && (rx_din == `PRIM_R_IP )) || r_ip_cont;
assign detect_r_err = ((rx_is_k[0]) && (rx_din == `PRIM_R_ERR )) || r_err_cont;
assign detect_r_ok = ((rx_is_k[0]) && (rx_din == `PRIM_R_OK )) || r_ok_cont;
assign detect_x_rdy = ((rx_is_k[0]) && (rx_din == `PRIM_X_RDY )) || x_rdy_cont;
assign detect_sof = (rx_is_k[0]) && (rx_din == `PRIM_SOF );
assign detect_eof = (rx_is_k[0]) && (rx_din == `PRIM_EOF );
assign detect_wtrm = ((rx_is_k[0]) && (rx_din == `PRIM_WTRM )) || wtrm_cont;
assign detect_cont = (rx_is_k[0]) && (rx_din == `PRIM_CONT );
assign detect_hold = ((rx_is_k[0]) && (rx_din == `PRIM_HOLD )) || hold_cont; //hold (normal) == hold (cont)
assign detect_holda = ((rx_is_k[0]) && (rx_din == `PRIM_HOLDA )) || holda_cont; //holda (normal) == holda (cont)
assign detect_preq_s = ((rx_is_k[0]) && (rx_din == `PRIM_PREQ_S )) || pmreq_s_cont;
assign detect_preq_p = ((rx_is_k[0]) && (rx_din == `PRIM_PREQ_P )) || pmreq_p_cont;
assign detect_align = (rx_is_k[0]) && (rx_din == `PRIM_ALIGN );
 
assign detect_xrdy_xrdy = ((((rx_isk[0])&& (rx_din == `PRIM_X_RDY )) || x_rdy_cont) && ll_tx_isk && (ll_tx_din == `PRIM_X_RDY));
assign detect_xrdy_xrdy = ((((rx_is_k[0])&& (rx_din == `PRIM_X_RDY )) || x_rdy_cont) && ll_tx_is_k && (ll_tx_din == `PRIM_X_RDY));
 
assign sync_cont = sync_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign hold_cont = hold_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign holda_cont = holda_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign pmreq_p_cont = pmreq_p_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign pmreq_s_cont = pmreq_s_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign r_err_cont = r_err_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign r_ip_cont = r_ip_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign r_ok_cont = r_ok_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign r_rdy_cont = r_rdy_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign wtrm_cont = wtrm_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign x_rdy_cont = x_rdy_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_isk[0] || detect_align));
assign sync_cont = sync_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign hold_cont = hold_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign holda_cont = holda_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign pmreq_p_cont = pmreq_p_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign pmreq_s_cont = pmreq_s_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign r_err_cont = r_err_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign r_ip_cont = r_ip_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign r_ok_cont = r_ok_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign r_rdy_cont = r_rdy_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign wtrm_cont = wtrm_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
assign x_rdy_cont = x_rdy_cont_ready && ((rx_din == `PRIM_CONT) || (!rx_is_k[0] || detect_align));
 
 
assign cont_tx_dout = (!xmit_cont_en) ? ll_tx_din : //when transmit cont gen is disable
((tx_prev_prim != ll_tx_din) && ll_tx_isk) ? ll_tx_din : //if the prev != curr (exit)
((tx_prev_prim != ll_tx_din) && ll_tx_is_k) ? ll_tx_din : //if the prev != curr (exit)
(last_prim) ? ll_tx_din:
(tx_cont_enable) ? //if the cont is enabled
send_cont ? `PRIM_CONT : //need to first send the cont
157,13 → 157,13
scram_dout : //send the junk
ll_tx_din; //tx cont is not enabled
 
assign cont_tx_isk = (!xmit_cont_en) ? ll_tx_isk :
((tx_prev_prim != ll_tx_din) && ll_tx_isk) ? ll_tx_isk ://if the prev != curr (exit)
(last_prim) ?ll_tx_isk:
(tx_cont_enable) ? //if the cont is enabled
send_cont ? 1 : //need to first send the cont
0 : //send the junk
ll_tx_isk; //tx cont is not enabled
assign cont_tx_is_k = (!xmit_cont_en) ? ll_tx_is_k :
((tx_prev_prim != ll_tx_din) && ll_tx_is_k) ? ll_tx_is_k ://if the prev != curr (exit)
(last_prim) ?ll_tx_is_k:
(tx_cont_enable) ? //if the cont is enabled
send_cont ? 1'b1 : //need to first send the cont
1'b0 : //send the junk
ll_tx_is_k; //tx cont is not enabled
assign scram_en = tx_cont_enable;
 
//Synchronous logic
188,7 → 188,7
end
else begin
if (!detect_align) begin
if (rx_isk) begin
if (rx_is_k) begin
if (rx_din == `PRIM_CONT) begin
cont_detect <= 1;
end
275,7 → 275,7
 
end
end
if (!rx_isk[0] && !cont_detect) begin
if (!rx_is_k[0] && !cont_detect) begin
cont_detect <= 0;
hold_cont_ready <= 0;
holda_cont_ready <= 0;
307,7 → 307,7
 
send_cont <= 0;
 
if (ll_tx_isk) begin
if (ll_tx_is_k) begin
 
//reset everything because the previous primative is not equal to the current one
if (tx_prev_prim != ll_tx_din) begin
/trunk/rtl/command/sata_command_layer.v
37,23 → 37,21
input data_out_clk_valid,
 
//User Interface
output sata_init,
output command_layer_ready,
output reg busy,
output reg sata_busy,
input send_sync_escape,
input [15:0] user_features,
 
//XXX: New Stb
input write_data_en,
input single_rdwr,
input read_data_en,
output dev_error,
// input write_data_stb,
// input read_data_stb,
output hard_drive_error,
 
input send_user_command_stb,
input soft_reset_en,
input execute_command_stb,
input command_layer_reset,
 
output reg pio_data_ready,
input [7:0] command,
input [7:0] hard_drive_command,
 
input [15:0] sector_count,
input [47:0] sector_address,
63,6 → 61,7
output [1:0] user_din_ready,
input [1:0] user_din_activate,
output [23:0] user_din_size,
output user_din_empty,
 
output [31:0] user_dout,
output user_dout_ready,
116,7 → 115,26
input [7:0] d2h_status,
input [7:0] d2h_error,
 
output d2h_error_bbk, //Bad Block
output d2h_error_unc, //Uncorrectable Error
output d2h_error_mc, //Removable Media Error
output d2h_error_idnf, //request sector's ID Field could not be found
output d2h_error_mcr, //Removable Media Error
output d2h_error_abrt, //Abort (from invalid command, drive not ready, write fault)
output d2h_error_tk0nf, //Track 0 not found
output d2h_error_amnf, //Data Address Mark is not found after finding correct ID
 
output d2h_status_bsy, //Set to 1 when drive has access to command block, no other bits are valid when 1
// Set after reset
// Set after soft reset (srst)
// Set immediately after host writes to command register
output d2h_status_drdy, //Drive is ready to accept command
output d2h_status_dwf, //Drive Write Fault
output d2h_status_dsc, //Drive Seek Complete
output d2h_status_drq, //Data Request, Drive is ready to send data to the host
output d2h_status_corr, //Correctable Data bit (an error that was encountered but was corrected)
output d2h_status_idx, //once per disc revolution this bit is set to one then back to zero
output d2h_status_err, //error bit, if this bit is high check the error flags
 
//command layer data interface
input t_if_strobe,
134,8 → 152,7
 
//Debug
output [3:0] cl_c_state,
output [3:0] cl_w_state,
output [3:0] cl_r_state
output [3:0] cl_w_state
 
);
 
145,12 → 162,9
parameter PIO_WAIT_FOR_DATA = 4'h1;
parameter PIO_WRITE_DATA = 4'h2;
 
parameter WAIT_FOR_DATA = 4'h1;
 
parameter WAIT_FOR_DMA_ACT = 4'h1;
parameter WAIT_FOR_WRITE_DATA = 4'h2;
parameter SEND_DATA = 4'h3;
parameter WAIT_FOR_STATUS = 4'h4;
 
//Registers/Wires
reg [3:0] cntrl_state;
159,31 → 173,16
wire idle;
reg cntrl_send_data_stb;
reg send_command_stb;
reg prev_send_command;
 
wire dev_busy;
wire dev_data_req;
 
reg [31:0] reset_count;
wire reset_timeout;
 
//Read State Machine
reg [3:0] read_state;
reg read_data_stb;
reg single_read_prev;
 
//Write State Machine
reg [3:0] write_state;
reg write_data_stb;
reg single_write_prev;
 
reg dma_send_data_stb;
reg dma_act_detected;
reg dma_act_detected_en;
 
wire write_data_available;
reg first_write;
reg first_read;
 
reg enable_tl_data_ready;
 
//Ping Pong FIFOs
191,7 → 190,6
wire [1:0] if_write_activate;
wire [23:0] if_write_size;
wire if_write_strobe;
wire if_starved;
wire [31:0] if_write_data;
 
wire if_read_strobe;
233,7 → 231,8
.write_activate (if_write_activate ),
.write_fifo_size (if_write_size ),
.write_strobe (if_write_strobe ),
.starved (if_starved ),
//.starved (if_starved ),
.starved (user_din_empty ),
 
//read side
//XXX: This can be different clocks
242,7 → 241,8
.read_ready (if_read_ready ),
.read_activate (if_read_activate ),
.read_count (if_read_size ),
.read_data (if_read_data )
.read_data (if_read_data ),
.inactive ( )
);
 
 
262,7 → 262,8
.write_activate (of_write_activate ),
.write_fifo_size (of_write_size ),
.write_strobe (of_write_strobe ),
.starved (out_fifo_starved ),
//.starved (out_fifo_starved ),
.starved ( ),
 
//read side
//XXX: This can be different clocks
271,7 → 272,8
.read_ready (of_read_ready ),
.read_activate (of_read_activate ),
.read_count (of_read_size ),
.read_data (of_read_data )
.read_data (of_read_data ),
.inactive ( )
);
 
 
302,10 → 304,7
assign if_write_strobe = user_din_stb;
assign user_din_ready = if_write_ready;
assign if_write_activate = user_din_activate;
//assign user_din_size = if_write_size;
assign user_din_size = 24'h00800;
//assign user_din_size = 24'h00400;
//assign user_din_size = 24'h00200;
assign user_din_size = if_write_size;
 
assign user_dout = of_read_data;
assign user_dout_ready = of_read_ready;
313,32 → 312,39
assign user_dout_size = of_read_size;
assign of_read_strobe = user_dout_stb;
 
assign d2h_status_bsy = d2h_status[7];
assign d2h_status_drdy = d2h_status[6];
assign d2h_status_dwf = d2h_status[5];
assign d2h_status_dsc = d2h_status[4];
assign d2h_status_drq = d2h_status[3];
assign d2h_status_corr = d2h_status[2];
assign d2h_status_idx = d2h_status[1];
assign d2h_status_err = d2h_status[0];
 
assign write_data_available = (if_read_ready || if_read_activate) || (if_write_ready != 2'b11);
assign d2h_error_bbk = d2h_error[7];
assign d2h_error_unc = d2h_error[6];
assign d2h_error_mc = d2h_error[5];
assign d2h_error_idnf = d2h_error[4];
assign d2h_error_mcr = d2h_error[3];
assign d2h_error_abrt = d2h_error[2];
assign d2h_error_tk0nf = d2h_error[1];
assign d2h_error_amnf = d2h_error[0];
 
 
//Strobes
assign t_send_command_stb = read_data_stb || write_data_stb || send_command_stb;
//assign t_send_command_stb = read_data_stb || write_data_stb || execute_command_stb;
assign t_send_command_stb = execute_command_stb;
assign t_send_data_stb = dma_send_data_stb ||cntrl_send_data_stb;
 
//IDLE
assign idle = (cntrl_state == IDLE) &&
(read_state == IDLE) &&
(write_state == IDLE) &&
transport_layer_ready;
 
assign command_layer_ready = idle;
assign sata_init = reset_timeout;
 
assign h2d_command = (write_data_en) ? `COMMAND_DMA_WRITE_EX :
(read_data_en) ? `COMMAND_DMA_READ_EX :
(send_user_command_stb) ? command :
h2d_command;
 
assign h2d_command = hard_drive_command;
assign h2d_sector_count = sector_count;
assign h2d_lba = (write_data_en) ? (!single_rdwr && !first_write) ? d2h_lba + 1 : sector_address :
(read_data_en) ? (!single_rdwr && !first_read) ? d2h_lba + 1 : sector_address :
sector_address;
assign h2d_lba = sector_address;
 
//XXX: The individual bits should be controlled directly
assign h2d_control = {5'h00, srst, 2'b00};
349,14 → 355,11
 
assign dev_busy = status[`STATUS_BUSY_BIT];
assign dev_data_req = status[`STATUS_DRQ_BIT];
assign dev_error = status[`STATUS_ERR_BIT];
assign hard_drive_error = status[`STATUS_ERR_BIT];
 
assign cl_c_state = cntrl_state;
assign cl_r_state = read_state;
assign cl_w_state = write_state;
assign cl_c_state = cntrl_state;
assign cl_w_state = write_state;
 
assign reset_timeout = (reset_count >= `RESET_TIMEOUT);
 
//Synchronous Logic
 
//Control State Machine
373,54 → 376,37
pio_data_ready <= 0;
status <= 0;
 
prev_send_command <= 0;
send_command_stb <= 0;
 
reset_count <= 0;
busy <= 1;
sata_busy <= 0;
sync_escape <= 0;
end
else begin
t_send_control_stb <= 0;
cntrl_send_data_stb <= 0;
pio_data_ready <= 0;
send_command_stb <= 0;
 
//Reset Count
if (reset_count < `RESET_TIMEOUT) begin
reset_count <= reset_count + 1;
end
if (!reset_timeout) begin
cntrl_state <= IDLE;
end
 
//detected the first a user attempting to send a command
if (send_user_command_stb && !prev_send_command) begin
prev_send_command <= 1;
send_command_stb <= 1;
end
if (!send_user_command_stb) begin
prev_send_command <= 0;
end
 
if (t_d2h_reg_stb) begin
busy <= 0;
//Receiving a register strobe from the device
sata_busy <= 0;
h2d_features <= `D2H_REG_FEATURES;
end
if (t_send_command_stb || t_send_control_stb || send_user_command_stb) begin
busy <= 1;
if (send_user_command_stb) begin
h2d_features <= user_features;
end
/*
if (t_send_command_stb || t_send_control_stb) begin
sata_busy <= 1;
end
*/
if (execute_command_stb) begin
h2d_features <= user_features;
sata_busy <= 1;
end
 
case (cntrl_state)
IDLE: begin
 
//Soft Reset will break out of any flow
if ((soft_reset_en) && !srst) begin
if (command_layer_reset && !srst) begin
srst <= 1;
t_send_control_stb <= 1;
reset_count <= 0;
end
 
if (idle) begin
427,7 → 413,7
//The only way to transition to another state is if CL is IDLE
 
//User Initiated commands
if (!soft_reset_en && srst && reset_timeout) begin
if (!command_layer_reset && srst) begin
srst <= 0;
t_send_control_stb <= 1;
end
475,146 → 461,43
 
if (send_sync_escape) begin
cntrl_state <= IDLE;
busy <= 0;
sync_escape <= 1;
sata_busy <= 0;
end
end
end
 
//Read State Machine
always @ (posedge clk) begin
if (rst || (!linkup)) begin
read_state <= IDLE;
sync_escape <= 0;
read_data_stb <= 0;
single_read_prev <= 0;
first_read <= 1;
end
else begin
read_data_stb <= 0;
sync_escape <= 0;
 
if (!read_data_en) begin
single_read_prev <= 0;
end
 
case (read_state)
IDLE: begin
if (idle) begin
sync_escape <= 0;
//The only way to transition to another state is if CL is IDLE
if (read_data_en) begin
if (single_rdwr) begin
if (!single_read_prev) begin
single_read_prev <= 1;
read_data_stb <= 1;
read_state <= WAIT_FOR_DATA;
end
end
else begin
//send a request to read data
read_data_stb <= 1;
read_state <= WAIT_FOR_DATA;
end
end
else begin
first_read <= 1;
end
end
end
WAIT_FOR_DATA: begin
//This state seems useless because it only sets a value but the state is used to indicate the system is idle or not
if (t_d2h_data_stb) begin
first_read <= 0;
end
/*
if (soft_reset_en) begin
//XXX: Issue a SYNC ESCAPE to cancel a large read request otherwise let it play out
//sync_escape <= 1;
end
*/
end
default: begin
read_state <= IDLE;
end
endcase
 
if (soft_reset_en || !reset_timeout || send_sync_escape) begin
if (read_state != IDLE) begin
sync_escape <= 1;
end
if (send_sync_escape) begin
sync_escape <= 1;
end
read_state <= IDLE;
end
 
//If this is received go back to IDLE
if (t_d2h_reg_stb) begin
read_state <= IDLE;
end
end
end
 
//Write State Machine
always @ (posedge clk) begin
if (rst || (!linkup)) begin
if (rst || !linkup) begin
write_state <= IDLE;
 
dma_send_data_stb <= 0;
 
write_data_stb <= 0;
single_write_prev <= 0;
first_write <= 1;
enable_tl_data_ready <= 0;
 
dma_act_detected <= 0;
dma_act_detected_en <= 0;
end
else begin
dma_send_data_stb <= 0;
write_data_stb <= 0;
 
if (enable_tl_data_ready && if_read_activate) begin
//Closes the loop on the data write feedback
enable_tl_data_ready <= 0;
end
 
if (!write_data_en) begin
single_write_prev <= 0;
end
 
if (t_dma_activate_stb) begin
//Set an enable signal instead of a strobe so that there is no chance of missing this signal
dma_act_detected <= 1;
dma_act_detected_en <= 1;
end
 
case (write_state)
IDLE: begin
enable_tl_data_ready <= 0;
if (idle) begin
//The only way to transition to another state is if CL is IDLE
if (write_data_en) begin
if (single_rdwr) begin
if (!single_write_prev) begin
single_write_prev <= 1;
write_state <= WAIT_FOR_DMA_ACT;
write_data_stb <= 1;
end
end
else begin
//send a request to write data
write_state <= WAIT_FOR_DMA_ACT;
write_data_stb <= 1;
end
//if (write_data_stb) begin
if (dma_act_detected_en) begin
//send a request to write data
write_state <= WAIT_FOR_DMA_ACT;
end
else begin
//reset the the first write when the user deassertes the write_data_en
first_write <= 1;
end
end
end
WAIT_FOR_DMA_ACT: begin
if (dma_act_detected) begin
dma_act_detected <= 0;
first_write <= 0;
if (dma_act_detected_en) begin
dma_act_detected_en <= 0;
enable_tl_data_ready <= 1;
write_state <= WAIT_FOR_WRITE_DATA;
end
621,6 → 504,7
end
WAIT_FOR_WRITE_DATA: begin
if (if_read_activate) begin
enable_tl_data_ready <= 0;
write_state <= SEND_DATA;
end
end
628,11 → 512,7
if (transport_layer_ready) begin
//Send the Data FIS
dma_send_data_stb <= 1;
write_state <= WAIT_FOR_DMA_ACT;
end
end
WAIT_FOR_STATUS: begin
if (t_d2h_reg_stb) begin
dma_act_detected_en <= 0;
write_state <= IDLE;
end
end
642,7 → 522,8
endcase
 
 
if (soft_reset_en || !reset_timeout) begin
//if (command_layer_reset || !reset_timeout) begin
if (command_layer_reset) begin
//Break out of the normal flow and return to IDLE
write_state <= IDLE;
end
656,8 → 537,5
end
end
 
 
 
endmodule
 
 
/trunk/sim/tb_cocotb.v
11,12 → 11,14
 
output linkup, //link is finished
output sata_ready,
output busy,
output sata_busy,
 
input write_data_en,
input read_data_en,
//input write_data_stb,
//input read_data_stb,
input [7:0] hard_drive_command,
input execute_command_stb,
 
input soft_reset_en,
input command_layer_reset,
input [15:0] sector_count,
input [47:0] sector_address,
 
61,23 → 63,21
reg [31:0] test_id = 0;
 
wire [31:0] tx_dout;
wire tx_isk;
wire tx_is_k;
wire tx_comm_reset;
wire tx_comm_wake;
wire tx_elec_idle;
 
wire [31:0] rx_din;
wire [3:0] rx_isk;
wire [3:0] rx_is_k;
wire rx_elec_idle;
wire comm_init_detect;
wire comm_wake_detect;
 
wire rx_byte_is_aligned;
 
reg r_rst;
reg r_write_data_en;
reg r_read_data_en;
reg r_soft_reset_en;
reg r_write_data_stb;
reg r_read_data_stb;
reg r_command_layer_reset;
reg [15:0] r_sector_count;
reg [47:0] r_sector_address;
reg r_prim_scrambler_en;
85,24 → 85,26
reg r_platform_ready;
reg r_dout_count;
reg r_hold;
reg r_single_rdwr;
 
reg r_u2h_write_enable;
reg [23:0] r_u2h_write_count;
reg [23:0] r_u2h_write_count;
reg r_h2u_read_enable;
 
reg [7:0] r_hard_drive_command;
reg r_execute_command_stb;
 
wire hd_read_from_host;
wire [31:0] hd_data_from_host;
wire [31:0] hd_data_from_host;
 
 
wire hd_write_to_host;
wire [31:0] hd_data_to_host;
wire [31:0] hd_data_to_host;
 
wire [31:0] user_dout;
wire [31:0] user_dout;
wire user_dout_ready;
wire user_dout_activate;
wire user_dout_stb;
wire [23:0] user_dout_size;
wire [23:0] user_dout_size;
 
 
wire [31:0] user_din;
111,11 → 113,24
wire [1:0] user_din_activate;
wire [23:0] user_din_size;
 
wire dma_activate_stb;
wire d2h_reg_stb;
wire pio_setup_stb;
wire d2h_data_stb;
wire dma_setup_stb;
wire set_device_bits_stb;
wire [7:0] d2h_fis;
wire i_rx_byte_is_aligned;
 
 
 
 
 
//There is a bug in COCOTB when stiumlating a signal, sometimes it can be corrupted if not registered
always @ (*) r_rst = rst;
always @ (*) r_write_data_en = write_data_en;
always @ (*) r_read_data_en = read_data_en;
always @ (*) r_soft_reset_en = soft_reset_en;
//always @ (*) r_write_data_stb = write_data_stb;
//always @ (*) r_read_data_stb = read_data_stb;
always @ (*) r_command_layer_reset= command_layer_reset;
always @ (*) r_sector_count = sector_count;
always @ (*) r_sector_address = sector_address;
always @ (*) r_prim_scrambler_en = prim_scrambler_en;
122,7 → 137,6
always @ (*) r_data_scrambler_en = data_scrambler_en;
always @ (*) r_platform_ready = platform_ready;
always @ (*) r_hold = hold;
always @ (*) r_single_rdwr = single_rdwr;
 
always @ (*) r_u2h_write_enable = u2h_write_enable;
always @ (*) r_u2h_write_count = u2h_write_count;
129,6 → 143,9
 
always @ (*) r_h2u_read_enable = h2u_read_enable;
 
always @ (*) r_hard_drive_command = hard_drive_command;
always @ (*) r_execute_command_stb= execute_command_stb;
 
//Submodules
 
//User Generated Test Data
187,37 → 204,49
sata_stack ss (
.rst (r_rst ), //reset
.clk (clk ), //clock used to run the stack
.data_in_clk (clk ),
.data_in_clk_valid (1'b1 ),
.data_out_clk (clk ),
.data_out_clk_valid (1'b1 ),
.command_layer_reset (r_command_layer_reset),
 
.platform_ready (platform_ready ), //the underlying physical platform is
.platform_error ( ),
.linkup (linkup ), //link is finished
 
.sata_ready (sata_ready ),
.sata_busy (sata_busy ),
 
.busy (busy ),
.send_sync_escape (1'b0 ),
.hard_drive_error ( ),
 
.write_data_en (r_write_data_en ),
.single_rdwr (r_single_rdwr ),
.read_data_en (r_read_data_en ),
.pio_data_ready ( ),
 
.send_user_command_stb (1'b0 ),
.soft_reset_en (r_soft_reset_en ),
.command (1'b0 ),
 
//Host to Device Control
// .write_data_stb (r_write_data_stb ),
// .read_data_stb (r_read_data_stb ),
.hard_drive_command (r_hard_drive_command ),
.execute_command_stb (r_execute_command_stb),
.user_features (16'h0000 ),
.sector_count (r_sector_count ),
.sector_address (r_sector_address ),
 
.d2h_interrupt (d2h_interrupt ),
.d2h_notification (d2h_notification ),
.d2h_port_mult (d2h_port_mult ),
.d2h_device (d2h_device ),
.d2h_lba (d2h_lba ),
.d2h_sector_count (d2h_sector_count ),
.d2h_status (d2h_status ),
.d2h_error (d2h_error ),
.dma_activate_stb (dma_activate_stb ),
.d2h_reg_stb (d2h_reg_stb ),
.pio_setup_stb (pio_setup_stb ),
.d2h_data_stb (d2h_data_stb ),
.dma_setup_stb (dma_setup_stb ),
.set_device_bits_stb (set_device_bits_stb ),
 
.d2h_fis (d2h_fis ),
.d2h_interrupt (d2h_interrupt ),
.d2h_notification (d2h_notification ),
.d2h_port_mult (d2h_port_mult ),
.d2h_device (d2h_device ),
.d2h_lba (d2h_lba ),
.d2h_sector_count (d2h_sector_count ),
.d2h_status (d2h_status ),
.d2h_error (d2h_error ),
 
//Data from host to the hard drive path
.data_in_clk (clk ),
.data_in_clk_valid (1'b1 ),
.user_din (user_din ), //User Data Here
.user_din_stb (user_din_stb ), //Strobe Each Data word in here
.user_din_ready (user_din_ready ), //Using PPFIFO Ready Signal
224,6 → 253,9
.user_din_activate (user_din_activate ), //Activate PPFIFO Channel
.user_din_size (user_din_size ), //Find the size of the data to write to the device
 
//Data from hard drive to host path
.data_out_clk (clk ),
.data_out_clk_valid (1'b1 ),
.user_dout (user_dout ),
.user_dout_ready (user_dout_ready ),
.user_dout_activate (user_dout_activate ),
233,23 → 265,27
.transport_layer_ready (transport_layer_ready),
.link_layer_ready (link_layer_ready ),
.phy_ready (phy_ready ),
.phy_error (1'b0 ),
 
.tx_dout (tx_dout ),
.tx_isk (tx_isk ),
.tx_is_k (tx_is_k ),
.tx_comm_reset (tx_comm_reset ),
.tx_comm_wake (tx_comm_wake ),
.tx_elec_idle (tx_elec_idle ),
.tx_oob_complete (1'b1 ),
 
.rx_din (rx_din ),
.rx_isk (rx_isk ),
.rx_is_k (rx_is_k ),
.rx_elec_idle (rx_elec_idle ),
.rx_byte_is_aligned (i_rx_byte_is_aligned ),
.comm_init_detect (comm_init_detect ),
.comm_wake_detect (comm_wake_detect ),
.rx_byte_is_aligned (rx_byte_is_aligned ),
 
 
.prim_scrambler_en (r_prim_scrambler_en ),
.data_scrambler_en (r_data_scrambler_en )
//.prim_scrambler_en (r_prim_scrambler_en ),
.prim_scrambler_en (1'b1 ),
//.data_scrambler_en (r_data_scrambler_en )
.data_scrambler_en (1'b1 )
);
 
faux_sata_hd fshd (
256,12 → 292,12
.rst (r_rst ),
.clk (clk ),
.tx_dout (rx_din ),
.tx_isk (rx_isk ),
.tx_is_k (rx_is_k ),
 
.rx_din (tx_dout ),
.rx_isk ({3'b000, tx_isk} ),
.rx_is_k ({3'b000, tx_is_k} ),
.rx_is_elec_idle (tx_elec_idle ),
.rx_byte_is_aligned (rx_byte_is_aligned ),
.rx_byte_is_aligned (i_rx_byte_is_aligned ),
 
.comm_reset_detect (tx_comm_reset ),
.comm_wake_detect (tx_comm_wake ),
273,43 → 309,45
// .phy_ready (phy_ready ),
 
 
.dbg_data_scrambler_en (r_data_scrambler_en ),
//.dbg_data_scrambler_en (r_data_scrambler_en ),
.dbg_data_scrambler_en (1'b1 ),
 
.dbg_hold (r_hold ),
 
.dbg_ll_write_start (0 ),
.dbg_ll_write_data (0 ),
.dbg_ll_write_start (1'b0 ),
.dbg_ll_write_data (32'h0 ),
.dbg_ll_write_size (0 ),
.dbg_ll_write_hold (0 ),
.dbg_ll_write_abort (0 ),
.dbg_ll_write_hold (1'b0 ),
.dbg_ll_write_abort (1'b0 ),
 
.dbg_ll_read_ready (0 ),
.dbg_t_en (0 ),
.dbg_ll_read_ready (1'b0 ),
.dbg_t_en (1'b0 ),
 
.dbg_send_reg_stb (0 ),
.dbg_send_dma_act_stb (0 ),
.dbg_send_data_stb (0 ),
.dbg_send_pio_stb (0 ),
.dbg_send_dev_bits_stb (0 ),
.dbg_send_reg_stb (1'b0 ),
.dbg_send_dma_act_stb (1'b0 ),
.dbg_send_data_stb (1'b0 ),
.dbg_send_pio_stb (1'b0 ),
.dbg_send_dev_bits_stb (1'b0 ),
 
.dbg_pio_transfer_count(0 ),
.dbg_pio_direction (0 ),
.dbg_pio_e_status (0 ),
.dbg_pio_transfer_count(16'h0000 ),
.dbg_pio_direction (1'b0 ),
.dbg_pio_e_status (8'h00 ),
 
.dbg_d2h_interrupt (0 ),
.dbg_d2h_notification (0 ),
.dbg_d2h_status (0 ),
.dbg_d2h_error (0 ),
.dbg_d2h_port_mult (0 ),
.dbg_d2h_device (0 ),
.dbg_d2h_lba (0 ),
.dbg_d2h_sector_count (0 ),
.dbg_d2h_interrupt (1'b0 ),
.dbg_d2h_notification (1'b0 ),
.dbg_d2h_status (8'b0 ),
.dbg_d2h_error (8'b0 ),
.dbg_d2h_port_mult (4'b0000 ),
.dbg_d2h_device (8'h00 ),
.dbg_d2h_lba (48'h000000000000 ),
.dbg_d2h_sector_count (16'h0000 ),
 
.dbg_cl_if_data (0 ),
.dbg_cl_if_ready (0 ),
.dbg_cl_if_size (0 ),
.dbg_cl_of_ready (0 ),
.dbg_cl_of_size (0 ),
.dbg_cl_if_data (32'b0 ),
.dbg_cl_if_ready (1'b0 ),
.dbg_cl_if_size (24'h0 ),
 
.dbg_cl_of_ready (2'b0 ),
.dbg_cl_of_size (24'h0 ),
.hd_read_from_host (hd_read_from_host ),
.hd_data_from_host (hd_data_from_host ),
 
/trunk/sim/faux_sata_hd_command_layer.v
104,16 → 104,17
parameter READ_IN_PROGRESS = 4'h6;
parameter SEND_STATUS = 4'h7;
 
parameter SLEEP_LENGTH = 100;
 
//Registers/Wires
reg [3:0] state = SLEEP_START;
wire idle;
 
reg [8:0] byte_count = 0;
reg [15:0] sector_count = 0;
reg [15:0] sector_size = 16'h0000;
reg [16:0] sector_count = 0;
reg [16:0] sector_size = 16'h0000;
 
reg [15:0] sleep_count = 0;
reg [15:0] sleep_size = 1000;
 
 
wire soft_reset;
152,7 → 153,6
sector_size <= 1000;
 
sleep_count <= 0;
sleep_size <= 1000;
 
 
 
181,14 → 181,16
send_dev_bits_stb <= 0;
 
if (soft_reset) begin
if (soft_reset) begin
$display ("Reset from soft reset");
end
state <= SLEEP_START;
sleep_count <= 0;
sleep_size <= 1000;
end
 
case (state)
SLEEP_START: begin
if (sleep_count < sleep_size) begin
if (sleep_count < SLEEP_LENGTH) begin
sleep_count <= sleep_count + 1;
end
else begin
196,6 → 198,7
end
end
SEND_DIAGNOSTICS: begin
$display ("Send Diagnostics");
send_reg_stb <= 1;
state <= IDLE;
end
205,19 → 208,22
d2h_lba <= h2d_lba;
d2h_sector_count <= h2d_sector_count;
 
sector_size <= h2d_sector_count;
if (h2d_sector_count == 0) begin
sector_size <= 17'h10000;
end
else begin
sector_size <= h2d_sector_count;
end
 
case (h2d_command)
`COMMAND_DMA_READ_EX: begin
//send_data_stb <= 1;
sector_count <= 0;
sector_size <= h2d_sector_count;
state <= SEND_DATA;
end
`COMMAND_DMA_WRITE_EX: begin
send_dma_act_stb <= 1;
sector_count <= 0;
sector_size <= h2d_sector_count;
state <= DMA_READY;
end
default: begin
285,7 → 291,6
$display ("fcl: Entered illegal state, restart");
state <= SLEEP_START;
sleep_count <= 0;
sleep_size <= 1000;
end
endcase
end
/trunk/sim/sata_defines.v
26,7 → 26,7
`define __SATA_DEFINES__
 
//Presuming 75MHz clock
`define CLOCK_RATE (75000000)
`define SATA_CLOCK_RATE (75000000)
// 1 / 880uS = 1136 times per seconds
`define NORMAL_TIMEOUT (1000000) / 880
 
36,7 → 36,7
`define FIFO_ADDRESS_WIDTH 11
 
//880uS
//`define INITIALIZE_TIMEOUT ((`CLOCK_RATE) / (`NORMAL_TIMEOUT))
//`define INITIALIZE_TIMEOUT ((`SATA_CLOCK_RATE) / (`NORMAL_TIMEOUT))
`define INITIALIZE_TIMEOUT 66000
//`define SEND_WAKE_TIMEOUT 4E
 
/trunk/sim/faux_sata_hd.v
31,12 → 31,12
 
//Data Interface
output [31:0] tx_dout,
output [3:0] tx_isk,
output [3:0] tx_is_k,
output tx_set_elec_idle,
output rx_byte_is_aligned,
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
input rx_is_elec_idle,
 
input comm_reset_detect,
143,10 → 143,10
//Parameters
//Registers/Wires
wire [31:0] phy_tx_dout;
wire phy_tx_isk;
wire phy_tx_is_k;
 
wire [31:0] sll_tx_dout;
wire sll_tx_isk;
wire sll_tx_is_k;
 
wire ll_ready;
wire ll_write_start;
280,11 → 280,11
 
//incomming/output data
.tx_dout (phy_tx_dout ),
.tx_isk (phy_tx_isk ),
.tx_is_k (phy_tx_is_k ),
.tx_set_elec_idle (tx_set_elec_idle ),
 
.rx_din (rx_din ),
.rx_isk (rx_isk ),
.rx_is_k (rx_is_k ),
.rx_is_elec_idle (rx_is_elec_idle ),
.rx_byte_is_aligned (rx_byte_is_aligned ),
 
303,11 → 303,11
sata_link_layer fsll (
.rst (rst || !hd_ready ),
.clk (clk ),
.prim_scrambler_en (1 ),
.prim_scrambler_en (1'b1 ),
.data_scrambler_en (data_scrambler_en ),
 
.link_layer_ready (ll_ready ),
.sync_escape (0 ),
.sync_escape (1'b0 ),
.hold (dbg_hold ),
 
//Transport Layer Interface
332,11 → 332,11
.phy_ready (phy_ready ),
.platform_ready (hd_ready ),
.tx_dout (sll_tx_dout ),
.tx_isk (sll_tx_isk ),
.tx_is_k (sll_tx_is_k ),
 
.rx_din (rx_din ),
.rx_isk (rx_isk ),
.is_device (1 )
.rx_is_k (rx_is_k ),
.is_device (1'b1 )
);
 
faux_sata_hd_transport ftl (
419,7 → 419,7
);
 
faux_hd_command_layer fcl(
.rst (rst ),
.rst (rst || !hd_ready ),
.clk (clk ),
 
.command_layer_ready (command_layer_ready ),
486,8 → 486,8
);
 
assign tx_dout = !phy_ready ? phy_tx_dout : sll_tx_dout;
assign tx_isk[3:1] = 3'b000;
assign tx_isk[0] = !phy_ready ? phy_tx_isk : sll_tx_isk;
assign tx_is_k[3:1] = 3'b000;
assign tx_is_k[0] = !phy_ready ? phy_tx_is_k : sll_tx_is_k;
 
 
//Debug
/trunk/sim/faux_sata_hd_phy.v
31,12 → 31,12
 
//Data Interface
output reg [31:0] tx_dout,
output reg tx_isk,
output reg tx_is_k,
output reg tx_set_elec_idle,
output reg rx_byte_is_aligned,
 
input [31:0] rx_din,
input [3:0] rx_isk,
input [3:0] rx_is_k,
input rx_is_elec_idle,
 
input comm_reset_detect,
87,8 → 87,8
//Asynchronous Logic
 
assign lax_state = state;
assign align_detected = ((rx_isk > 0) && (rx_din == `PRIM_ALIGN));
assign dialtone_detected = ((rx_isk == 0) && (rx_din == `DIALTONE));
assign align_detected = ((rx_is_k > 0) && (rx_din == `PRIM_ALIGN));
assign dialtone_detected = ((rx_is_k == 0) && (rx_din == `DIALTONE));
assign timeout = (timer == 0);
assign phy_ready = (state == READY);
 
97,7 → 97,7
if (rst) begin
state <= IDLE;
tx_dout <= 0;
tx_isk <= 0;
tx_is_k <= 0;
tx_set_elec_idle <= 1;
timer <= 0;
hd_ready <= 0;
118,12 → 118,14
 
if ((comm_reset_detect) && (state > WAIT_FOR_NO_RESET)) begin
$display("faux_sata_hd: Asynchronous RESET detected");
state <= IDLE;
align_count <= 0;
hd_ready <= 0;
state <= WAIT_FOR_NO_RESET;
end
 
case (state)
IDLE: begin
align_count <= 0;
align_count <= 0;
hd_ready <= 0;
tx_set_elec_idle <= 1;
if (comm_reset_detect) begin
136,8 → 138,7
if (!comm_reset_detect) begin
//host stopped sending reset
$display("faux_sata_hd: RESET deasserted");
hd_ready <= 0;
tx_set_elec_idle <= 1;
hd_ready <= 0;
state <= SEND_INIT;
end
end
170,26 → 171,30
end
WAIT_FOR_DIALTONE: begin
if (dialtone_detected) begin
$display ("faul_sata_hd: detected dialtone");
$display ("faux_sata_hd: detected dialtone");
state <= SEND_ALIGN;
end
end
SEND_ALIGN: begin
$display ("faul_sata_hd: send aligns");
$display ("faux_sata_hd: send aligns");
tx_set_elec_idle <= 0;
tx_dout <= `PRIM_ALIGN;
tx_isk <= 1;
tx_is_k <= 1;
state <= WAIT_FOR_ALIGN;
timer <= 32'h`INITIALIZE_TIMEOUT;
rx_byte_is_aligned <= 1;
end
WAIT_FOR_ALIGN: begin
tx_is_k <= 1;
tx_dout <= `PRIM_ALIGN;
rx_byte_is_aligned <= 1;
//$display ("faux_sata_hd: waiting for aligns...");
//$display ("rx din: %h, k: %h", rx_din, rx_is_k);
if (align_detected) begin
$display ("faux_sata_hd: detected ALIGN primitive from host");
$display ("faux_sata_hd: Ready");
tx_dout <= `PRIM_ALIGN;
tx_isk <= 1;
tx_is_k <= 1;
timer <= 0;
state <= READY;
end
201,7 → 206,7
READY: begin
hd_ready <= 1;
rx_byte_is_aligned <= 1;
tx_isk <= 1;
tx_is_k <= 1;
tx_dout <= `PRIM_SYNC;
if (align_count == 255) begin
tx_dout <= `PRIM_ALIGN;
210,13 → 215,13
end
SEND_FIRST_ALIGNMENT: begin
rx_byte_is_aligned <= 1;
tx_isk <= 1;
tx_is_k <= 1;
tx_dout <= `PRIM_ALIGN;
state <= SEND_SECOND_ALIGNMENT;
end
SEND_SECOND_ALIGNMENT: begin
rx_byte_is_aligned <= 1;
tx_isk <= 1;
tx_is_k <= 1;
tx_dout <= `PRIM_ALIGN;
state <= READY;
end
/trunk/README.md
7,12 → 7,6
 
This code was written a long time ago and I've learned much more about verilog and project organization
since then. It has been proven in a Virtex 6 FPGA reading and writing to/from four Sata 2 hard drives at
the same time. There were some issues found when the internal buffers inside the hard drives began to
fill up requiring a lot of starting and stopping of this stack. It lead to some dropped data. There was
a horrible fix for it in the sata_link_write.v involving a small buffer. This made if very difficult to
debug because the stack wouldn't allow me to read the non-scrambled data within the logic analyzer.
There should be a more elegant solution to it.
 
Most of the license is MIT but some of the licenses are GPL
 
TODO: Fix Link layer... there is a small FIFO in there that is used to handle all starting and stopping

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.