Line 64... |
Line 64... |
input [7:0] h2d_device,
|
input [7:0] h2d_device,
|
input [47:0] h2d_lba,
|
input [47:0] h2d_lba,
|
input [15:0] h2d_sector_count,
|
input [15:0] h2d_sector_count,
|
|
|
//Device to Host Registers
|
//Device to Host Registers
|
|
output reg [7:0] d2h_fis,
|
output reg d2h_interrupt,
|
output reg d2h_interrupt,
|
output reg d2h_notification,
|
output reg d2h_notification,
|
output reg [3:0] d2h_port_mult,
|
output reg [3:0] d2h_port_mult,
|
output reg [7:0] d2h_device,
|
output reg [7:0] d2h_device,
|
output reg [47:0] d2h_lba,
|
output reg [47:0] d2h_lba,
|
Line 98... |
Line 99... |
|
|
output ll_write_start,
|
output ll_write_start,
|
input ll_write_strobe,
|
input ll_write_strobe,
|
input ll_write_finished,
|
input ll_write_finished,
|
output [31:0] ll_write_data,
|
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_hold,
|
output ll_write_abort,
|
output ll_write_abort,
|
input ll_xmit_error,
|
input ll_xmit_error,
|
|
|
input ll_read_start,
|
input ll_read_start,
|
Line 134... |
Line 135... |
parameter READ_DATA = 4'h9;
|
parameter READ_DATA = 4'h9;
|
|
|
|
|
//Registers/Wires
|
//Registers/Wires
|
reg [3:0] fis_id_state;
|
reg [3:0] fis_id_state;
|
|
reg [7:0] current_fis;
|
reg [3:0] state;
|
reg [3:0] state;
|
reg detect_fis;
|
reg detect_fis;
|
reg [7:0] current_fis;
|
|
wire processing_fis;
|
wire processing_fis;
|
|
|
//data direction
|
//data direction
|
wire data_direction;
|
wire data_direction;
|
|
|
Line 157... |
Line 158... |
reg [7:0] register_fis_ptr;
|
reg [7:0] register_fis_ptr;
|
reg cmd_bit;
|
reg cmd_bit;
|
|
|
reg reg_write_start;
|
reg reg_write_start;
|
wire [31:0] reg_write_data;
|
wire [31:0] reg_write_data;
|
wire [31:0] reg_write_size;
|
wire [23:0] reg_write_size;
|
reg reg_write_ready;
|
reg reg_write_ready;
|
wire reg_write_hold;
|
wire reg_write_hold;
|
wire reg_write_abort;
|
wire reg_write_abort;
|
wire reg_write_strobe;
|
wire reg_write_strobe;
|
|
|
Line 175... |
Line 176... |
|
|
//data state machine signals
|
//data state machine signals
|
reg data_write_start;
|
reg data_write_start;
|
wire data_write_strobe;
|
wire data_write_strobe;
|
wire data_read_strobe;
|
wire data_read_strobe;
|
wire [31:0] data_write_size;
|
wire [23:0] data_write_size;
|
wire [31:0] data_write_data;
|
wire [31:0] data_write_data;
|
wire data_write_hold;
|
wire data_write_hold;
|
wire data_write_abort;
|
wire data_write_abort;
|
|
|
reg data_read_ready;
|
reg data_read_ready;
|
reg send_data_fis_id;
|
reg send_data_fis_id;
|
|
|
|
reg ll_write_finished_en;
|
|
|
|
|
|
|
//Asnchronous Logic
|
//Asnchronous Logic
|
assign lax_state = state;
|
assign lax_state = state;
|
assign transport_layer_ready = (state == IDLE) && link_layer_ready;
|
assign transport_layer_ready = (state == IDLE) && link_layer_ready;
|
Line 197... |
Line 200... |
|
|
//Write Control
|
//Write Control
|
assign ll_write_start = (reg_write) ? reg_write_start : data_write_start;
|
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_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_size = (reg_write) ? reg_write_size : data_write_size;
|
assign ll_write_hold = (reg_write) ? 0 : data_write_hold;
|
assign ll_write_hold = (reg_write) ? 1'b0 : data_write_hold;
|
assign ll_write_abort = (reg_write) ? 0 : data_write_abort;
|
assign ll_write_abort = (reg_write) ? 1'b0 : data_write_abort;
|
assign cl_if_strobe = (reg_write) ? 0 : (!send_data_fis_id && data_write_strobe);
|
assign cl_if_strobe = (reg_write) ? 1'b0 : (!send_data_fis_id && data_write_strobe);
|
|
|
//Read Control
|
//Read Control
|
assign ll_read_ready = (reg_read) ? 1 : data_read_ready;
|
assign ll_read_ready = (reg_read) ? 1'b1 : data_read_ready;
|
assign cl_of_strobe = (reg_read) ? 0 : ((state == READ_DATA) && data_read_strobe);
|
assign cl_of_strobe = (reg_read) ? 1'b0 : ((state == READ_DATA) && data_read_strobe);
|
assign cl_of_data = ll_read_data;
|
assign cl_of_data = ll_read_data;
|
|
|
//Data Register Write Control Signals
|
//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
|
//the first DWORD is the FIS ID
|
assign data_write_size = (cl_if_size + 1);
|
assign data_write_size = cl_if_size + 24'h1;
|
//assign data_write_size = cl_if_size;
|
|
//Add 1 to the size so that there is room for the FIS ID
|
//Add 1 to the size so that there is room for the FIS ID
|
assign data_write_strobe = ll_write_strobe;
|
assign data_write_strobe = ll_write_strobe;
|
assign data_read_strobe = ll_read_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
|
//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;
|
assign read_crc_error = !ll_read_crc_ok;
|
|
|
|
|
//H2D Register Write control signals
|
//H2D Register Write control signals
|
assign reg_write_strobe = ll_write_strobe;
|
assign reg_write_strobe = ll_write_strobe;
|
assign reg_write_size = `FIS_H2D_REG_SIZE;
|
assign reg_write_size = `FIS_H2D_REG_SIZE;
|
assign reg_write_hold = 0;
|
assign reg_write_hold = 1'b0;
|
assign reg_write_abort = 0;
|
assign reg_write_abort = 1'b0;
|
assign reg_write = (state == WRITE_H2D_REG) || (send_command_stb || send_control_stb);
|
assign reg_write = (state == WRITE_H2D_REG) || (send_command_stb || send_control_stb);
|
|
|
//D2H Register Read control signals
|
//D2H Register Read control signals
|
assign reg_read = (state == READ_D2H_REG) || detect_d2h_reg ||
|
assign reg_read = (state == READ_D2H_REG) || detect_d2h_reg ||
|
(state == READ_PIO_SETUP) || detect_pio_setup ||
|
(state == READ_PIO_SETUP) || detect_pio_setup ||
|
Line 259... |
Line 261... |
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
if (rst) begin
|
if (rst) begin
|
fis_id_state <= IDLE;
|
fis_id_state <= IDLE;
|
detect_fis <= 0;
|
detect_fis <= 0;
|
current_fis <= 0;
|
current_fis <= 0;
|
|
d2h_fis <= 0;
|
end
|
end
|
else begin
|
else begin
|
//in order to set all the detect_* high when the actual fis is detected send this strobe
|
//in order to set all the detect_* high when the actual fis is detected send this strobe
|
if(ll_read_finished) begin
|
if(ll_read_finished) begin
|
current_fis <= 0;
|
current_fis <= 0;
|
Line 280... |
Line 283... |
end
|
end
|
READ_FIS: begin
|
READ_FIS: begin
|
if (ll_read_strobe) begin
|
if (ll_read_strobe) begin
|
detect_fis <= 0;
|
detect_fis <= 0;
|
current_fis <= ll_read_data[7:0];
|
current_fis <= ll_read_data[7:0];
|
|
d2h_fis <= ll_read_data[7:0];
|
fis_id_state <= WAIT_FOR_END;
|
fis_id_state <= WAIT_FOR_END;
|
end
|
end
|
end
|
end
|
WAIT_FOR_END: begin
|
WAIT_FOR_END: begin
|
if (ll_read_finished) begin
|
if (ll_read_finished) begin
|
Line 345... |
Line 349... |
pio_direction <= 0;
|
pio_direction <= 0;
|
pio_response <= 0;
|
pio_response <= 0;
|
|
|
data_write_start <= 0;
|
data_write_start <= 0;
|
|
|
|
ll_write_finished_en <= 0;
|
end
|
end
|
else begin
|
else begin
|
//Strobed signals
|
//Strobed signals
|
if (phy_ready) begin
|
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;
|
data_write_start <= 0;
|
reg_write_start <= 0;
|
reg_write_start <= 0;
|
end
|
end
|
|
|
d2h_reg_stb <= 0;
|
d2h_reg_stb <= 0;
|
Line 386... |
Line 391... |
//Always attempt to get the incomming buffer
|
//Always attempt to get the incomming buffer
|
if (cl_if_ready && !cl_if_activate) begin
|
if (cl_if_ready && !cl_if_activate) begin
|
cl_if_activate <= 1;
|
cl_if_activate <= 1;
|
end
|
end
|
|
|
|
if (ll_write_finished) begin
|
|
ll_write_finished_en <= 1;
|
|
end
|
|
|
case (state)
|
case (state)
|
IDLE: begin
|
IDLE: begin
|
register_fis_ptr <= 0;
|
register_fis_ptr <= 0;
|
reg_read_count <= 0;
|
reg_read_count <= 0;
|
cmd_bit <= 0;
|
cmd_bit <= 0;
|
|
ll_write_finished_en <= 0;
|
//Detect a FIS
|
//Detect a FIS
|
if(ll_read_start) begin
|
if(ll_read_start) begin
|
//detect the start of a frame
|
//detect the start of a frame
|
state <= CHECK_FIS_TYPE;
|
state <= CHECK_FIS_TYPE;
|
//Clear Errors when a new transaction starts
|
//Clear Errors when a new transaction starts
|
Line 422... |
Line 432... |
end
|
end
|
end
|
end
|
CHECK_FIS_TYPE: begin
|
CHECK_FIS_TYPE: begin
|
if (detect_dma_setup) begin
|
if (detect_dma_setup) begin
|
//XXX: Future work!
|
//XXX: Future work!
|
reg_read_count <= reg_read_count + 1;
|
reg_read_count <= reg_read_count + 8'h1;
|
state <= IDLE;
|
state <= IDLE;
|
end
|
end
|
else if (detect_dma_activate) begin
|
else if (detect_dma_activate) begin
|
//hard drive is ready to receive data
|
//hard drive is ready to receive data
|
state <= DMA_ACTIVATE;
|
state <= DMA_ACTIVATE;
|
reg_read_count <= reg_read_count + 1;
|
reg_read_count <= reg_read_count + 8'h1;
|
//state <= IDLE;
|
//state <= IDLE;
|
end
|
end
|
else if (detect_d2h_data) begin
|
else if (detect_d2h_data) begin
|
//incomming data, because the out FIFO is directly connected to the output during a read
|
//incomming data, because the out FIFO is directly connected to the output during a read
|
state <= READ_DATA;
|
state <= READ_DATA;
|
Line 443... |
Line 453... |
d2h_error <= ll_read_data[31:24];
|
d2h_error <= ll_read_data[31:24];
|
d2h_interrupt <= ll_read_data[14];
|
d2h_interrupt <= ll_read_data[14];
|
d2h_port_mult <= ll_read_data[11:8];
|
d2h_port_mult <= ll_read_data[11:8];
|
|
|
state <= READ_D2H_REG;
|
state <= READ_D2H_REG;
|
reg_read_count <= reg_read_count + 1;
|
reg_read_count <= reg_read_count + 8'h1;
|
end
|
end
|
else if (detect_pio_setup) begin
|
else if (detect_pio_setup) begin
|
//store the error, status, direction interrupt from this read
|
//store the error, status, direction interrupt from this read
|
pio_response <= 1;
|
pio_response <= 1;
|
|
|
Line 456... |
Line 466... |
d2h_interrupt <= ll_read_data[14];
|
d2h_interrupt <= ll_read_data[14];
|
pio_direction <= ll_read_data[13];
|
pio_direction <= ll_read_data[13];
|
d2h_port_mult <= ll_read_data[11:8];
|
d2h_port_mult <= ll_read_data[11:8];
|
|
|
state <= READ_PIO_SETUP;
|
state <= READ_PIO_SETUP;
|
reg_read_count <= reg_read_count + 1;
|
reg_read_count <= reg_read_count + 8'h1;
|
end
|
end
|
else if (detect_set_device_bits) begin
|
else if (detect_set_device_bits) begin
|
//store the error, a subset of the status bit and the interrupt
|
//store the error, a subset of the status bit and the interrupt
|
state <= IDLE;
|
state <= IDLE;
|
d2h_status[6:4] <= ll_read_data[22:20];
|
d2h_status[6:4] <= ll_read_data[22:20];
|
Line 478... |
Line 488... |
end
|
end
|
end
|
end
|
WRITE_H2D_REG: begin
|
WRITE_H2D_REG: begin
|
if (register_fis_ptr < `FIS_H2D_REG_SIZE) begin
|
if (register_fis_ptr < `FIS_H2D_REG_SIZE) begin
|
if (reg_write_strobe) begin
|
if (reg_write_strobe) begin
|
register_fis_ptr <= register_fis_ptr + 1;
|
register_fis_ptr <= register_fis_ptr + 8'h1;
|
end
|
end
|
end
|
end
|
if (ll_write_finished) begin
|
if (ll_write_finished_en) begin
|
if (ll_xmit_error) begin
|
if (ll_xmit_error) begin
|
state <= RETRY;
|
state <= RETRY;
|
end
|
end
|
else begin
|
else begin
|
state <= IDLE;
|
state <= IDLE;
|
end
|
end
|
end
|
end
|
end
|
end
|
RETRY: begin
|
RETRY: begin
|
if (link_layer_ready) begin
|
if (link_layer_ready) begin
|
|
ll_write_finished_en <= 0;
|
reg_write_start <= 1;
|
reg_write_start <= 1;
|
register_fis_ptr <= 0;
|
register_fis_ptr <= 0;
|
state <= WRITE_H2D_REG;
|
state <= WRITE_H2D_REG;
|
end
|
end
|
end
|
end
|
Line 515... |
Line 526... |
end
|
end
|
default: begin
|
default: begin
|
end
|
end
|
endcase
|
endcase
|
if (reg_read_stb) begin
|
if (reg_read_stb) begin
|
reg_read_count <= reg_read_count + 1;
|
reg_read_count <= reg_read_count + 8'h1;
|
end
|
end
|
if (ll_read_finished) begin
|
if (ll_read_finished) begin
|
d2h_reg_stb <= 1;
|
d2h_reg_stb <= 1;
|
state <= IDLE;
|
state <= IDLE;
|
end
|
end
|
Line 542... |
Line 553... |
end
|
end
|
default: begin
|
default: begin
|
end
|
end
|
endcase
|
endcase
|
if (reg_read_stb) begin
|
if (reg_read_stb) begin
|
reg_read_count <= reg_read_count + 1;
|
reg_read_count <= reg_read_count + 8'h1;
|
end
|
end
|
if (ll_read_finished) begin
|
if (ll_read_finished) begin
|
pio_setup_stb <= 1;
|
pio_setup_stb <= 1;
|
state <= IDLE;
|
state <= IDLE;
|
end
|
end
|
Line 561... |
Line 572... |
end
|
end
|
SEND_DATA: begin
|
SEND_DATA: begin
|
if (ll_write_strobe && send_data_fis_id) begin
|
if (ll_write_strobe && send_data_fis_id) begin
|
send_data_fis_id <= 0;
|
send_data_fis_id <= 0;
|
end
|
end
|
if (ll_write_finished) begin
|
if (ll_write_finished_en) begin
|
cl_if_activate <= 0;
|
cl_if_activate <= 0;
|
state <= IDLE;
|
state <= IDLE;
|
if (pio_response) begin
|
if (pio_response) begin
|
//write the end status to the status pin
|
//write the end status to the status pin
|
d2h_status <= pio_e_status;
|
d2h_status <= pio_e_status;
|