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

Subversion Repositories sata_phy

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 11 to Rev 12
    Reverse comparison

Rev 11 → Rev 12

/sata_phy/trunk/hdl/sata_phy_host_ctrl_x6series.v
0,0 → 1,602
////////////////////////////////////////////////////////////
//
// This confidential and proprietary software may be used
// only as authorized by a licensing agreement from
// Bean Digital Ltd
// In the event of publication, the following notice is
// applicable:
//
// (C)COPYRIGHT 2012 BEAN DIGITAL LTD.
// ALL RIGHTS RESERVED
//
// The entire notice above must be reproduced on all
// authorized copies.
//
// File : sata_phy_host_ctrl_x6series.v
// Author : J.Bean
// Date : Mar 2012
// Description : SATA PHY Layer Host Control Xilinx 6 Series
////////////////////////////////////////////////////////////
 
`resetall
`timescale 1ns/10ps
 
`include "sata_constants.v"
 
module sata_phy_host_ctrl_x6series
#(parameter SATA_REV = 1)( // SATA Revision (1, 2, 3)
input wire clk_phy, // Clock PHY
input wire rst_n, // Reset
output reg link_up_o, // Link Up
// Transceiver
input wire gt_rst_done_i, // GT Reset Done
output reg [31:0] gt_tx_data_o, // GT Transmit Data
output reg [3:0] gt_tx_charisk_o, // GT Transmit K/D
output reg gt_tx_com_strt_o, // GT Transmit COM Start
output reg gt_tx_com_type_o, // GT Transmit COM Type
output reg gt_tx_elec_idle_o, // GT Transmit Electrical Idle
input wire [31:0] gt_rx_data_i, // GT Receive Data
input wire [2:0] gt_rx_status_i, // GT Receive Status
input wire gt_rx_elec_idle_i // GT Receive Electrical Idle
);
 
////////////////////////////////////////////////////////////
// Parameters
////////////////////////////////////////////////////////////
 
// Time delays
parameter SATA1_10MS = 750000; // 75MHz * 750000
parameter SATA2_10MS = 1500000; // 150MHz * 1500000
parameter SATA3_10MS = 3000000; // 300MHz * 3000000
parameter SATA1_873US = 65535; // 75MHz * 65535
parameter SATA2_873US = 131070; // 150MHz * 131070
parameter SATA3_873US = 262140; // 300MHz * 262140
 
// State machine states
parameter HP1_RESET = 0;
parameter HP2_AWAIT_COMINIT = 1;
parameter HP2B_AWAIT_NO_COMINIT = 2;
parameter HP3_CALIBRATE = 3;
parameter HP4_COMWAKE = 4;
parameter HP5_AWAIT_COMWAKE = 5;
parameter HP5B_AWAIT_NO_COMWAKE = 6;
parameter HP6_AWAIT_ALIGN = 7;
parameter HP7_SEND_ALIGN = 8;
parameter HP8_READY = 9;
 
////////////////////////////////////////////////////////////
// Signals
////////////////////////////////////////////////////////////
 
reg [3:0] state_cs; // Current state
reg [3:0] state_ns; // Next state
reg [199:0] state_ascii; // ASCII state
wire phy_ctrl_strt; // PHY Control Start
reg [31:0] align_timeout_cnt; // ALIGN Timeout Count
reg [31:0] retry_cnt; // Retry Count
wire cominit_detect; // COMINIT Detect
wire comwake_detect; // COMWAKE Detect
wire align_detect; // ALIGN Detected
wire align_timeout; // ALIGN Timeout
reg [1:0] non_align_cnt; // Non ALIGN Count
reg tx_com_strt; // Transmit COM Start
wire tx_com_strt_pedge; // Transmit COM Start Positive Edge
reg tx_com_done; // Transmit COM Done
 
////////////////////////////////////////////////////////////
// Instance : Transmit Com Start Pos Edge
// Description : Detect positive edge on com start signal.
////////////////////////////////////////////////////////////
 
det_pos_edge U_tx_com_strt_pedge(
.clk (clk_phy),
.rst_n (rst_n),
.d (tx_com_strt),
.q (tx_com_strt_pedge));
 
////////////////////////////////////////////////////////////
// Comb Assign : PHY Control Start
// Description : Starts the control.
////////////////////////////////////////////////////////////
 
assign phy_ctrl_strt = gt_rst_done_i;
 
////////////////////////////////////////////////////////////
// Comb Assign : COMWAKE Detect
// Description :
////////////////////////////////////////////////////////////
 
assign comwake_detect = gt_rx_status_i[1];
 
////////////////////////////////////////////////////////////
// Comb Assign : COMINIT Detect
// Description :
////////////////////////////////////////////////////////////
 
assign cominit_detect = gt_rx_status_i[2];
 
////////////////////////////////////////////////////////////
// Comb Assign : ALIGN Timeout
// Description :
////////////////////////////////////////////////////////////
 
assign align_timeout = (align_timeout_cnt == 0);
 
////////////////////////////////////////////////////////////
// Comb Assign : ALIGN primitive detect
// Description :
////////////////////////////////////////////////////////////
 
assign align_detect = (gt_rx_data_i == 32'h7B4A4ABC);
 
////////////////////////////////////////////////////////////
// Seq Block : State machine seq logic
// Description : Sets the current state to the next state.
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
state_cs <= HP1_RESET;
end else begin
state_cs <= state_ns;
end
end
 
////////////////////////////////////////////////////////////
// Comb Block : State machine ascii
// Description : Converts the state to ascii for debug.
////////////////////////////////////////////////////////////
 
always @(*)
begin
case (state_cs)
HP1_RESET: state_ascii = "HP1_RESET";
HP2_AWAIT_COMINIT: state_ascii = "HP2_AWAIT_COMINIT";
HP2B_AWAIT_NO_COMINIT: state_ascii = "HP2B_AWAIT_NO_COMINIT";
HP3_CALIBRATE: state_ascii = "HP3_CALIBRATE";
HP4_COMWAKE: state_ascii = "HP4_COMWAKE";
HP5_AWAIT_COMWAKE: state_ascii = "HP5_AWAIT_COMWAKE";
HP5B_AWAIT_NO_COMWAKE: state_ascii = "HP5B_AWAIT_NO_COMWAKE";
HP6_AWAIT_ALIGN: state_ascii = "HP6_AWAIT_ALIGN";
HP7_SEND_ALIGN: state_ascii = "HP7_SEND_ALIGN";
HP8_READY: state_ascii = "HP8_READY";
endcase
end
 
////////////////////////////////////////////////////////////
// Comb Block : State machine comb logic
// Description : Assigns the next state.
////////////////////////////////////////////////////////////
 
always @(*)
begin
state_ns = state_cs;
 
case (state_cs)
// HP1_RESET - Interface quiescent
HP1_RESET: begin
if ((phy_ctrl_strt == 1) && (tx_com_done == 1) && (cominit_detect == 0)) begin
state_ns = HP2_AWAIT_COMINIT;
end
end
// HP2_AWAIT_COMINIT - Wait for COMINIT to be detected
HP2_AWAIT_COMINIT: begin
if (cominit_detect == 1) begin
state_ns = HP2B_AWAIT_NO_COMINIT;
end else begin
// Test if need to send COMRESET again
if (retry_cnt == 0) begin
state_ns = HP1_RESET;
end
end
end
 
// HP2B_AWAIT_NO_COMINIT - Wait for COMINIT to finish
HP2B_AWAIT_NO_COMINIT: begin
if (cominit_detect == 0) begin
state_ns = HP3_CALIBRATE;
end
end
// HP3_CALIBRATE
HP3_CALIBRATE: begin
state_ns = HP4_COMWAKE;
end
// HP4_COMWAKE - Send COMWAKE
HP4_COMWAKE: begin
if (tx_com_done == 1) begin
state_ns = HP5_AWAIT_COMWAKE;
end
end
// HP5_AWAIT_COMWAKE - Wait for COMWAKE to be detected
HP5_AWAIT_COMWAKE: begin
if (comwake_detect == 1) begin
state_ns = HP5B_AWAIT_NO_COMWAKE;
end else begin
// Test if need to send COMRESET again
if (retry_cnt == 0) begin
state_ns = HP1_RESET;
end
end
end
// HP5B_AWAIT_NO_COMWAKE - Wait for COMWAKE to finish
HP5B_AWAIT_NO_COMWAKE: begin
if (comwake_detect == 0) begin
state_ns = HP6_AWAIT_ALIGN;
end
end
// HP6_AWAIT_ALIGN - Wait for ALIGN to be detected
HP6_AWAIT_ALIGN: begin
casez({align_detect, align_timeout})
2'b10: state_ns = HP7_SEND_ALIGN;
2'b01: state_ns = HP1_RESET;
default: state_ns = HP6_AWAIT_ALIGN;
endcase
end
// HP7_SEND_ALIGN - Send ALIGN
HP7_SEND_ALIGN: begin
if (non_align_cnt == 3) begin
state_ns = HP8_READY;
end
end
// HP8_READY - Link ready
HP8_READY: begin
if (gt_rx_elec_idle_i == 1) begin
state_ns = HP1_RESET;
end
end
default: begin
state_ns = 'bx;
end
endcase
end
 
////////////////////////////////////////////////////////////
// Seq Block : Link Up
// Description : Set when communication has been established
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
link_up_o <= 0;
end else begin
case (state_cs)
// HP8_READY - Link ready
HP8_READY: begin
link_up_o <= 1;
end
default: begin
link_up_o <= 0;
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : GT Transmit COM Start
// Description : Transmits the selected COM signal.
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
gt_tx_com_strt_o <= 0;
end else begin
gt_tx_com_strt_o <= tx_com_strt_pedge;
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : GT Transmit COM Type
// Description : 0 = COMRESET/COMINIT, 1 = COMWAKE
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
gt_tx_com_type_o <= 0;
end else begin
case (state_cs)
// HP1_RESET - Interface quiescent
HP1_RESET: begin
if (phy_ctrl_strt == 1) begin
gt_tx_com_type_o <= 0;
end
end
// HP4_COMWAKE - Send COMWAKE
HP4_COMWAKE: begin
gt_tx_com_type_o <= 1;
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : GT Transmit Electrical Idle
// Description :
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
gt_tx_elec_idle_o <= 0;
end else begin
case (state_cs)
// HP5B_AWAIT_NO_COMWAKE - Wait for COMWAKE to finish
HP5B_AWAIT_NO_COMWAKE: begin
if (comwake_detect == 0) begin
gt_tx_elec_idle_o <= 0;
end
end
// HP6_AWAIT_ALIGN - Wait for ALIGN to be detected
HP6_AWAIT_ALIGN: begin
gt_tx_elec_idle_o <= 0;
end
// HP7_SEND_ALIGN - Send ALIGN
HP7_SEND_ALIGN: begin
gt_tx_elec_idle_o <= 0;
end
// HP8_READY - Link ready
HP8_READY: begin
gt_tx_elec_idle_o <= 0;
end
default: begin
gt_tx_elec_idle_o <= 1;
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : GT Transmit Data
// Description :
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
gt_tx_data_o <= 0;
end else begin
case (state_cs)
// HP6_AWAIT_ALIGN - Wait for ALIGN to be detected
HP6_AWAIT_ALIGN: begin
gt_tx_data_o <= 32'h4A4A4A4A; // D10.2
end
// HP7_SEND_ALIGN - Send ALIGN
HP7_SEND_ALIGN: begin
gt_tx_data_o <= `ALIGN_VAL; // ALIGN;
end
// HP8_READY - Link ready
HP8_READY: begin
gt_tx_data_o <= `SYNC_VAL; // SYNC;
end
default: begin
gt_tx_data_o <= 0;
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : GT Transmit K/D
// Description :
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
gt_tx_charisk_o <= 0;
end else begin
case (state_cs)
// HP6_AWAIT_ALIGN - Wait for ALIGN to be detected
HP6_AWAIT_ALIGN: begin
gt_tx_charisk_o <= 4'b0000; // D10.2
end
// HP7_SEND_ALIGN - Send ALIGN
HP7_SEND_ALIGN: begin
gt_tx_charisk_o <= 4'b0001; // ALIGN;
end
// HP8_READY - Link ready
HP8_READY: begin
gt_tx_charisk_o <= 4'b0001; // SYNC;
end
default: begin
gt_tx_charisk_o <= 0;
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : Transmit COM Start
// Description : Starts transmission of a COM sequence.
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
tx_com_strt <= 0;
end else begin
case (state_cs)
// HP1_RESET - Interface quiescent
HP1_RESET: begin
if (phy_ctrl_strt == 1) begin
tx_com_strt <= 1;
end else begin
tx_com_strt <= 0;
end
end
// HP4_COMWAKE - Send COMWAKE
HP4_COMWAKE: begin
tx_com_strt <= 1;
end
default: begin
tx_com_strt <= 0;
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : Transmit COM Done
// Description : Detects when COM signal has been sent.
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
tx_com_done <= 0;
end else begin
case (state_cs)
// HP1_RESET - Interface quiescent
HP1_RESET: begin
if ((phy_ctrl_strt == 1) && (tx_com_done == 1) && (cominit_detect == 0)) begin
tx_com_done <= 0;
end else begin
if (gt_rx_status_i[0] == 1) begin
tx_com_done <= 1;
end
end
end
// HP4_COMWAKE - Send COMWAKE
HP4_COMWAKE: begin
if (tx_com_done == 1) begin
tx_com_done <= 0;
end else begin
if (gt_rx_status_i[0] == 1) begin
tx_com_done <= 1;
end
end
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : ALIGN Timeout Count
// Description : Used to send COMRESET if ALIGN primitives
// are not detected within 873.8us.
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
align_timeout_cnt <= 0;
end else begin
case (state_cs)
// HP1_RESET - Interface quiescent
HP1_RESET: begin
case (SATA_REV)
1: align_timeout_cnt <= SATA1_873US;
2: align_timeout_cnt <= SATA2_873US;
3: align_timeout_cnt <= SATA3_873US;
default: align_timeout_cnt <= SATA1_873US;
endcase
end
// HP6_AWAIT_ALIGN - Wait for ALIGN to be detected
HP6_AWAIT_ALIGN: begin
align_timeout_cnt <= align_timeout_cnt - 1;
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : Retry Count
// Description : Used to for async signal recovery (10 ms)
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
retry_cnt <= 0;
end else begin
case (state_cs)
// HP1_RESET - Interface quiescent
HP1_RESET: begin
case (SATA_REV)
1: retry_cnt <= SATA1_10MS;
2: retry_cnt <= SATA2_10MS;
3: retry_cnt <= SATA3_10MS;
default: retry_cnt <= SATA1_10MS;
endcase
end
// HP2_AWAIT_COMINIT - Wait for COMINIT to be detected
HP2_AWAIT_COMINIT: begin
retry_cnt <= retry_cnt - 1;
end
// HP2B_AWAIT_NO_COMINIT - Wait for COMINIT to finish
HP2B_AWAIT_NO_COMINIT: begin
case (SATA_REV)
1: retry_cnt <= SATA1_10MS;
2: retry_cnt <= SATA2_10MS;
3: retry_cnt <= SATA3_10MS;
default: retry_cnt <= SATA1_10MS;
endcase
end
// HP5_AWAIT_COMWAKE - Wait for COMWAKE to be detected
HP5_AWAIT_COMWAKE: begin
retry_cnt <= retry_cnt - 1;
end
endcase
end
end
 
////////////////////////////////////////////////////////////
// Seq Block : Non ALIGN Count
// Description : Counts 3 non ALIGN primitives.
////////////////////////////////////////////////////////////
 
always @(negedge rst_n or posedge clk_phy)
begin
if (rst_n == 0) begin
non_align_cnt <= 0;
end else begin
case (state_cs)
// HP7_SEND_ALIGN - Send ALIGN
HP7_SEND_ALIGN: begin
// Look for K28.3
if (gt_rx_data_i[7:0] == 8'hbc) begin
non_align_cnt <= non_align_cnt + 1;
end else begin
non_align_cnt <= 0;
end
end
default: begin
non_align_cnt <= 0;
end
endcase
end
end
 
endmodule

powered by: WebSVN 2.1.0

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