Line 29... |
Line 29... |
|
|
input rst, //reset
|
input rst, //reset
|
input clk,
|
input clk,
|
|
|
input platform_ready, //the underlying physical platform is
|
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 linkup, //link is finished
|
|
|
output reg tx_comm_reset, //send a init OOB signal
|
output reg tx_comm_reset, //send a init OOB signal
|
output reg tx_comm_wake, //send a wake 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_init_detect, //detected an init
|
input comm_wake_detect, //detected a wake on the rx lines
|
input comm_wake_detect, //detected a wake on the rx lines
|
|
|
input [31:0] rx_din,
|
input [31:0] rx_din,
|
input [3:0] rx_isk,
|
input [3:0] rx_is_k,
|
input rx_is_elec_idle,
|
input rx_is_elec_idle,
|
input rx_byte_is_aligned,
|
input rx_byte_is_aligned,
|
|
input phy_error,
|
|
|
output reg [31:0] tx_dout,
|
output reg [31:0] tx_dout,
|
output reg tx_isk,
|
output reg tx_is_k,
|
output reg tx_set_elec_idle,
|
output reg tx_set_elec_idle,
|
output [3:0] lax_state
|
output [3:0] lax_state
|
|
|
|
|
);
|
);
|
Line 63... |
Line 66... |
parameter WAIT_FOR_NO_INIT = 4'h3;
|
parameter WAIT_FOR_NO_INIT = 4'h3;
|
parameter WAIT_FOR_CONFIGURE_END = 4'h4;
|
parameter WAIT_FOR_CONFIGURE_END = 4'h4;
|
parameter SEND_WAKE = 4'h5;
|
parameter SEND_WAKE = 4'h5;
|
parameter WAIT_FOR_WAKE = 4'h6;
|
parameter WAIT_FOR_WAKE = 4'h6;
|
parameter WAIT_FOR_NO_WAKE = 4'h7;
|
parameter WAIT_FOR_NO_WAKE = 4'h7;
|
parameter WAIT_FOR_ALIGN = 4'h8;
|
parameter WAIT_FOR_IDLE = 4'h8;
|
parameter SEND_ALIGN = 4'h9;
|
parameter WAIT_FOR_ALIGN = 4'h9;
|
parameter DETECT_SYNC = 4'hA;
|
parameter SEND_ALIGN = 4'hA;
|
parameter READY = 4'hB;
|
parameter DETECT_SYNC = 4'hB;
|
|
parameter READY = 4'hC;
|
|
|
//Registers/Wires
|
//Registers/Wires
|
reg [3:0] state;
|
reg [3:0] state;
|
reg [31:0] timer;
|
reg [31:0] timer;
|
reg [1:0] no_align_count;
|
reg [1:0] no_align_count;
|
|
reg [3:0] retries;
|
|
|
//timer used to send 'INITs', WAKEs' and read them
|
//timer used to send 'INITs', WAKEs' and read them
|
wire timeout;
|
wire timeout;
|
wire align_detected;
|
wire align_detected;
|
wire sync_detected;
|
wire sync_detected;
|
|
|
//Submodules
|
//Submodules
|
//Asynchronous Logic
|
//Asynchronous Logic
|
assign timeout = (timer == 0);
|
assign timeout = (timer == 0);
|
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 sync_detected = ((rx_isk > 0) && (rx_din == `PRIM_SYNC));
|
//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;
|
assign lax_state = state;
|
|
|
//Synchronous Logic
|
//Synchronous Logic
|
initial begin
|
initial begin
|
tx_set_elec_idle <= 1;
|
tx_set_elec_idle <= 1;
|
Line 95... |
Line 102... |
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
if (rst) begin
|
if (rst) begin
|
state <= IDLE;
|
state <= IDLE;
|
linkup <= 0;
|
linkup <= 0;
|
timer <= 0;
|
timer <= 0;
|
tx_comm_reset <= 1;
|
tx_comm_reset <= 0;
|
tx_comm_wake <= 0;
|
tx_comm_wake <= 0;
|
tx_dout <= 0;
|
tx_dout <= 0;
|
tx_isk <= 0;
|
tx_is_k <= 0;
|
tx_set_elec_idle <= 1;
|
tx_set_elec_idle <= 1;
|
no_align_count <= 0;
|
no_align_count <= 0;
|
|
platform_error <= 0;
|
|
retries <= 0;
|
end
|
end
|
else begin
|
else begin
|
//to support strobes, continuously reset the following signals
|
//to support strobes, continuously reset the following signals
|
tx_comm_reset <= 0;
|
tx_comm_reset <= 0;
|
tx_comm_wake <= 0;
|
tx_comm_wake <= 0;
|
|
|
tx_isk <= 0;
|
tx_is_k <= 0;
|
|
|
|
|
//timer (when reache 0 timeout has occured)
|
//timer (when reache 0 timeout has occured)
|
if (timer > 0) begin
|
if (timer > 0) begin
|
timer <= timer - 1;
|
timer <= timer - 1;
|
end
|
end
|
|
|
//main state machine, if this reaches ready an initialization sequence has completed
|
//main state machine, if this reaches ready an initialization sequence has completed
|
case (state)
|
case (state)
|
IDLE: begin
|
IDLE: begin
|
|
platform_error <= 0;
|
linkup <= 0;
|
linkup <= 0;
|
tx_set_elec_idle <= 1;
|
tx_set_elec_idle <= 1;
|
if (platform_ready) begin
|
if (platform_ready) begin
|
$display ("oob_controller: send RESET");
|
$display ("oob_controller: send RESET");
|
//the platform is ready
|
//the platform is ready
|
// PLL has locked onto a clock
|
// PLL has locked onto a clock
|
// DCM has generated the correct clocks
|
// DCM has generated the correct clocks
|
timer <= 32'h000000A2;
|
timer <= 32'h000000A2;
|
state <= SEND_RESET;
|
state <= SEND_RESET;
|
|
tx_comm_reset <= 1;
|
end
|
end
|
end
|
end
|
SEND_RESET: begin
|
SEND_RESET: begin
|
//XXX: In the groundhog COMM RESET was continuously issued for a long period of time
|
//XXX: In the groundhog COMM RESET was continuously issued for a long period of time
|
//send the INIT sequence, this will initiate a communication with the
|
//send the INIT sequence, this will initiate a communication with the
|
//SATA hard drive, or reset it so that it can be initiated to state
|
//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
|
//strobe the comm init so that the platform will send an INIT OOB signal
|
tx_comm_reset <= 1;
|
if (timeout || tx_oob_complete) begin
|
if (timeout) begin
|
timer <= `INITIALIZE_TIMEOUT;
|
timer <= 32'd`INITIALIZE_TIMEOUT;
|
|
state <= WAIT_FOR_INIT;
|
state <= WAIT_FOR_INIT;
|
$display ("oob_controller: wait for INIT");
|
$display ("oob_controller: wait for INIT");
|
end
|
end
|
end
|
end
|
WAIT_FOR_INIT: begin
|
WAIT_FOR_INIT: begin
|
//wait for a response from the SATA harddrive, if the timeout occurs
|
//wait for a response from the SATA harddrive, if the timeout occurs
|
//go back to the SEND_RESET state
|
//go back to the SEND_RESET state
|
if (comm_init_detect) begin
|
if (comm_init_detect) begin
|
//HD said 'sup' go to a wake
|
//HD said 'sup' go to a wake
|
timer <= 0;
|
//timer <= 0;
|
|
timer <= 32'h00001000;
|
state <= WAIT_FOR_NO_INIT;
|
state <= WAIT_FOR_NO_INIT;
|
$display ("oob_controller: wait for INIT to go low");
|
$display ("oob_controller: wait for INIT to go low");
|
end
|
end
|
if (timeout) begin
|
if (timeout) begin
|
$display ("oob_controller: timed out while waiting for INIT");
|
$display ("oob_controller: timed out while waiting for INIT");
|
state <= IDLE;
|
state <= IDLE;
|
end
|
end
|
end
|
end
|
WAIT_FOR_NO_INIT: begin
|
WAIT_FOR_NO_INIT: begin
|
//wait for the init signal to go low from the device
|
//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: INIT deasserted");
|
$display ("oob_controller: start configuration");
|
$display ("oob_controller: start configuration");
|
state <= WAIT_FOR_CONFIGURE_END;
|
state <= WAIT_FOR_CONFIGURE_END;
|
end
|
end
|
end
|
end
|
WAIT_FOR_CONFIGURE_END: begin
|
WAIT_FOR_CONFIGURE_END: begin
|
$display ("oob_controller: System is configured");
|
$display ("oob_controller: System is configured");
|
state <= SEND_WAKE;
|
state <= SEND_WAKE;
|
timer <= 32'h0000009B;
|
timer <= 32'h0000009B;
|
|
tx_comm_wake <= 1;
|
//end
|
//end
|
end
|
end
|
SEND_WAKE: begin
|
SEND_WAKE: begin
|
//XXX: In the groundhog COMM WAKE was continuously send for a long period of time
|
//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
|
//Send the WAKE sequence to the hard drive to initiate a wakeup sequence
|
tx_comm_wake <= 1;
|
|
//XXX: Is this timeout correct?
|
//XXX: Is this timeout correct?
|
//880uS
|
//880uS
|
if (timeout) begin
|
if (timeout || tx_oob_complete) begin
|
//timer <= 32'd`INITIALIZE_TIMEOUT;
|
//timer <= 32'd`INITIALIZE_TIMEOUT;
|
timer <= 32'h000203AD;
|
timer <= 32'h000203AD;
|
state <= WAIT_FOR_WAKE;
|
state <= WAIT_FOR_WAKE;
|
end
|
end
|
end
|
end
|
Line 204... |
Line 215... |
//XXX: Is this timeout correct?
|
//XXX: Is this timeout correct?
|
//880uS
|
//880uS
|
$display ("oob_controller: detected WAKE deasserted");
|
$display ("oob_controller: detected WAKE deasserted");
|
$display ("oob_controller: Send Dialtone, wait for ALIGN");
|
$display ("oob_controller: Send Dialtone, wait for ALIGN");
|
//Going to add more timeout
|
//Going to add more timeout
|
timer <= 32'h203AD;
|
//timer <= 32'h0203AD;
|
|
timer <= 32'h0203AD;
|
state <= WAIT_FOR_ALIGN;
|
state <= WAIT_FOR_ALIGN;
|
|
//state <= WAIT_FOR_IDLE;
|
|
retries <= 4;
|
end
|
end
|
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
|
WAIT_FOR_ALIGN: begin
|
//transmit the 'dialtone' continuously
|
//transmit the 'dialtone' continuously
|
//since we need to start sending actual data (not OOB signals, get out
|
//since we need to start sending actual data (not OOB signals, get out
|
// of tx idle)
|
// of tx idle)
|
tx_set_elec_idle <= 0;
|
tx_set_elec_idle <= 0;
|
//a sequence of 0's and 1's
|
//a sequence of 0's and 1's
|
tx_dout <= `DIALTONE;
|
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
|
if (align_detected) begin
|
//we got something from the device!
|
//we got something from the device!
|
timer <= 0;
|
timer <= 0;
|
//now send an align from my side
|
//now send an align from my side
|
state <= SEND_ALIGN;
|
state <= SEND_ALIGN;
|
Line 233... |
Line 265... |
state <= IDLE;
|
state <= IDLE;
|
end
|
end
|
end
|
end
|
SEND_ALIGN: begin
|
SEND_ALIGN: begin
|
tx_dout <= `PRIM_ALIGN;
|
tx_dout <= `PRIM_ALIGN;
|
tx_isk <= 1;
|
tx_is_k <= 1;
|
if (!align_detected) begin
|
if (!align_detected) begin
|
$display ("oob_controller: detected ALIGN deasserted");
|
$display ("oob_controller: detected ALIGN deasserted");
|
//XXX: Groundhog detects the SYNC primitve before declaring linkup
|
//XXX: Groundhog detects the SYNC primitve before declaring linkup
|
if (no_align_count == 3) begin
|
if (no_align_count == 3) begin
|
$display ("oob_controller: ready");
|
$display ("oob_controller: ready");
|
state <= READY;
|
state <= READY;
|
end
|
end
|
else begin
|
else begin
|
no_align_count <= no_align_count + 1;
|
no_align_count <= no_align_count + 2'b01;
|
end
|
end
|
end
|
end
|
end
|
end
|
DETECT_SYNC: begin
|
DETECT_SYNC: begin
|
if (sync_detected) begin
|
if (sync_detected) begin
|
state <= READY;
|
state <= READY;
|
end
|
end
|
end
|
end
|
READY: begin
|
READY: begin
|
linkup <= 1;
|
linkup <= 1;
|
|
/*
|
|
if (phy_error) begin
|
|
platform_error <= 1;
|
|
end
|
|
*/
|
if (comm_init_detect) begin
|
if (comm_init_detect) begin
|
state <= IDLE;
|
state <= IDLE;
|
end
|
end
|
end
|
end
|
default: begin
|
default: begin
|