Commit 0e25833e authored by Alexey Grebenkin's avatar Alexey Grebenkin

temporary Ashwin\'s sata host added

parent 65abe0b4
//--------------------------------------------------------------------------------
// Entity mux_21
// Version: 1.0
// Author: Ashwin Mendon
// Description: 2 bit 2:1 Multiplexer
//--------------------------------------------------------------------------------
// Copyright (C) 2012
// Ashwin A. Mendon
//
// This file is part of SATA2 core.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
module mux_21
(
input wire [1:0] a,
input wire [1:0] b,
input wire sel,
output reg [1:0] o
);
always @ (a or b or sel)
begin
case (sel)
1'b0:
o = a;
1'b1:
o = b;
endcase
end
endmodule
//--------------------------------------------------------------------------------
// Entity mux_21
// Version: 1.0
// Author: Ashwin Mendon
// Description: 32 bit 4:1 Multiplexer
//--------------------------------------------------------------------------------
// Copyright (C) 2012
// Ashwin A. Mendon
//
// This file is part of SATA2 core.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
module mux_41
(
input wire [31:0] a,
input wire [31:0] b,
input wire [31:0] c,
input wire [31:0] d,
input wire [1:0] sel,
output reg [31:0] o
);
always @ (a or b or c or d or sel)
begin
case (sel)
2'b00:
o = a;
2'b01:
o = b;
2'b10:
o = c;
2'b11:
o = d;
endcase
end
endmodule
//*****************************************************************************/
// Module : OOB_control
// Version: 1.0
// Author: Ashwin Mendon
// Description: This module handles the Out-Of-Band (OOB) sinaling requirements
// for link initialization and synchronization
// It has been modified from Xilinx XAPP870 to support Virtex 6 GTX
// transceivers
//*****************************************************************************/
module OOB_control (
clk, // Clock
reset, // reset
oob_control_ila_control,
/**** GTX ****/
rxreset, // GTX PCS reset
rx_locked, // GTX PLL is locked
gen2, // Generation 2 speed
txcominit, // TX OOB issue RESET/INIT
txcomwake, // TX OOB issue WAKE
cominitdet, // RX OOB detect INIT
comwakedet, // RX OOB detect WAKE
rxelecidle, // RX electrical idle
txelecidle_out,// TX electircal idel
rxbyteisaligned,// RX byte alignment completed
tx_dataout, // Outgoing TX data to GTX
tx_charisk_out,// TX byted is K character
rx_datain, // Data from GTX
rx_charisk_in, // K character from GTX
/**** GTX ****/
/**** LINK LAYER ****/
// INPUT
tx_datain, // Incoming TX data from SATA Link Layer
tx_charisk_in, // K character indicator
// OUTPUT
rx_dataout, // Data to SATA Link Layer
rx_charisk_out,
linkup, // SATA link is established
linkup_led_out, // LINKUP LED output
align_en_out,
CurrentState_out // Current state for Chipscope
/**** LINK LAYER ****/
);
parameter CHIPSCOPE = "FALSE";
input clk;
input reset;
input [35:0] oob_control_ila_control;
input rx_locked;
input gen2;
// Added for GTX
input cominitdet;
input comwakedet;
// Added for GTX
input rxelecidle;
input rxbyteisaligned;
input [31:0] tx_datain;
input tx_charisk_in;
input [3:0] rx_charisk_in;
input [31:0] rx_datain; //changed for GTX
output rxreset;
// Added for GTX
output txcominit;
output txcomwake;
// Added for GTX
output txelecidle_out;
output [31:0] tx_dataout; //changed for GTX
output tx_charisk_out;
output [31:0] rx_dataout;
output [3:0] rx_charisk_out;
output linkup;
output linkup_led_out;
output align_en_out;
output [7:0] CurrentState_out;
parameter [3:0]
host_comreset = 8'h00,
wait_dev_cominit = 8'h01,
host_comwake = 8'h02,
wait_dev_comwake = 8'h03,
wait_after_comwake = 8'h04,
wait_after_comwake1 = 8'h05,
host_d10_2 = 8'h06,
host_send_align = 8'h07,
link_ready = 8'h08,
link_idle = 8'h09;
// Primitves
parameter ALIGN = 4'b00;
parameter SYNC = 4'b01;
parameter DIAL = 4'b10;
//parameter R_RDY = 4'b11;
parameter LINK_LAYER = 4'b11;
reg [7:0] CurrentState, NextState;
reg [17:0] count;
reg [3:0] align_char_cnt_reg;
reg align_char_cnt_rst, align_char_cnt_inc;
reg count_en;
reg tx_charisk, tx_charisk_next;
reg txelecidle, txelecidle_next;
reg linkup_r, linkup_r_next;
reg rxreset;
reg [31:0] tx_datain_r;
wire [31:0] tx_dataout_i;
reg [31:0] rx_dataout_i;
wire [31:0] tx_align, tx_sync, tx_dial, tx_r_rdy;
reg [3:0] rx_charisk_r;
reg txcominit_r, txcomwake_r;
wire [1:0] align_count_mux_out;
reg [8:0] align_count;
reg [1:0] prim_type, prim_type_next;
wire align_det, sync_det, cont_det, sof_det, eof_det, x_rdy_det, r_err_det, r_ok_det;
reg align_en, align_en_r;
reg rxelecidle_r;
reg [31:0] rx_datain_r;
reg [3:0] rx_charisk_in_r;
reg rxbyteisaligned_r;
reg comwakedet_r, cominitdet_r;
// OOB FSM Logic Process
always @ ( CurrentState or count or rxelecidle_r or rx_locked or rx_datain_r or
cominitdet_r or comwakedet_r or
align_det or sync_det or cont_det or
tx_charisk_in )
begin : Comb_FSM
count_en = 1'b0;
NextState = host_comreset;
linkup_r_next = linkup_r;
txcominit_r =1'b0;
txcomwake_r = 1'b0;
rxreset = 1'b0;
txelecidle_next = txelecidle;
prim_type_next = prim_type;
tx_charisk_next = tx_charisk;
rx_dataout_i = 32'b0;
rx_charisk_r = 4'b0;
case (CurrentState)
host_comreset :
begin
txelecidle_next = 1'b1;
prim_type_next = ALIGN;
if (rx_locked)
begin
if ((~gen2 && count == 18'h00051) || (gen2 && count == 18'h000A2))
begin
txcominit_r =1'b0;
NextState = wait_dev_cominit;
end
else //Issue COMRESET
begin
txcominit_r =1'b1;
count_en = 1'b1;
NextState = host_comreset;
end
end
else
begin
txcominit_r =1'b0;
NextState = host_comreset;
end
end
wait_dev_cominit : //1
begin
if (cominitdet_r == 1'b1) //device cominit detected
begin
NextState = host_comwake;
end
else
begin
`ifdef SIM
if(count == 18'h001ff)
`else
if(count == 18'h203AD) //restart comreset after no cominit for at least 880us
`endif
begin
count_en = 1'b0;
NextState = host_comreset;
end
else
begin
count_en = 1'b1;
NextState = wait_dev_cominit;
end
end
end
host_comwake : //2
begin
if ((~gen2 && count == 18'h0004E) || (gen2 && count == 18'h0009B))
begin
txcomwake_r =1'b0;
NextState = wait_dev_comwake;
end
else
begin
txcomwake_r =1'b1;
count_en = 1'b1;
NextState = host_comwake;
end
end
wait_dev_comwake : //3
begin
if (comwakedet_r == 1'b1) //device comwake detected
begin
NextState = wait_after_comwake;
end
else
begin
if(count == 18'h203AD) //restart comreset after no cominit for 880us
begin
count_en = 1'b0;
NextState = host_comreset;
end
else
begin
count_en = 1'b1;
NextState = wait_dev_comwake;
end
end
end
wait_after_comwake : // 4
begin
if (count == 6'h3F)
begin
NextState = wait_after_comwake1;
end
else
begin
count_en = 1'b1;
NextState = wait_after_comwake;
end
end
wait_after_comwake1 : //5
begin
if (rxelecidle_r == 1'b0)
begin
rxreset = 1'b1;
NextState = host_d10_2;
end
else
NextState = wait_after_comwake1;
end
host_d10_2 : //6
begin
txelecidle_next = 1'b0;
// D10.2-D10.2 "dial tone"
rx_dataout_i = rx_datain_r;
prim_type_next = DIAL;
tx_charisk_next = 1'b0;
if (align_det)
begin
NextState = host_send_align;
end
else
begin
if(count == 18'h203AD) // restart comreset after 880us
begin
count_en = 1'b0;
NextState = host_comreset;
end
else
begin
count_en = 1'b1;
NextState = host_d10_2;
end
end
end
host_send_align : //7
begin
rx_dataout_i = rx_datain_r;
// Send Align primitives. Align is
// K28.5, D10.2, D10.2, D27.3
prim_type_next = ALIGN;
tx_charisk_next = 1'b1;
if (sync_det) // SYNC detected
begin
linkup_r_next = 1'b1;
NextState = link_ready;
end
else
NextState = host_send_align;
end
link_ready : // 8
begin
if (rxelecidle_r == 1'b1)
begin
NextState = link_ready;
linkup_r_next = 1'b0;
end
else
begin
NextState = link_ready;
linkup_r_next = 1'b1;
rx_charisk_r = rx_charisk_in_r;
rx_dataout_i = rx_datain_r;
// Send LINK_LAYER DATA
prim_type_next = LINK_LAYER;
if (align_en)
tx_charisk_next = 1'b1;
else
tx_charisk_next = tx_charisk_in;
end
end
default : NextState = host_comreset;
endcase
end
// OOB FSM Synchronous Process
always@(posedge clk or posedge reset)
begin : Seq_FSM
if (reset)
begin
CurrentState <= host_comreset;
prim_type <= ALIGN;
tx_charisk <= 1'b0;
txelecidle <= 1'b1;
linkup_r <= 1'b0;
align_en_r <= 1'b0;
rxelecidle_r <= 1'b0;
rx_datain_r <= 32'b0;
rx_charisk_in_r <= 4'b0;
rxbyteisaligned_r <= 1'b0;
cominitdet_r <= 1'b0;
comwakedet_r <= 1'b0;
end
else
begin
CurrentState <= NextState;
prim_type <= prim_type_next;
tx_charisk <= tx_charisk_next;
txelecidle <= txelecidle_next;
linkup_r <= linkup_r_next;
align_en_r <= align_en;
rxelecidle_r <= rxelecidle;
rx_datain_r <= rx_datain;
rx_charisk_in_r <= rx_charisk_in;
rxbyteisaligned_r <= rxbyteisaligned;
cominitdet_r <= cominitdet;
comwakedet_r <= comwakedet;
end
end
always@(posedge clk or posedge reset)
begin : freecount
if (reset)
begin
count <= 18'b0;
end
else if (count_en)
begin
count <= count + 1;
end
else
begin
count <= 18'b0;
end
end
assign txcominit = txcominit_r;
assign txcomwake = txcomwake_r;
assign txelecidle_out = txelecidle;
//Primitive detection
// Changed for 32-bit GTX
assign align_det = (rx_datain_r == 32'h7B4A4ABC) && (rxbyteisaligned_r == 1'b1); //prevent invalid align at wrong speed
assign sync_det = (rx_datain_r == 32'hB5B5957C);
assign cont_det = (rx_datain_r == 32'h9999AA7C);
assign sof_det = (rx_datain_r == 32'h3737B57C);
assign eof_det = (rx_datain_r == 32'hD5D5B57C);
assign x_rdy_det = (rx_datain_r == 32'h5757B57C);
assign r_err_det = (rx_datain_r == 32'h5656B57C);
assign r_ok_det = (rx_datain_r == 32'h3535B57C);
assign linkup = linkup_r;
assign linkup_led_out = ((CurrentState == link_ready) && (rxelecidle_r == 1'b0)) ? 1'b1 : 1'b0;
assign CurrentState_out = CurrentState;
assign rx_charisk_out = rx_charisk_r;
assign tx_charisk_out = tx_charisk;
assign rx_dataout = rx_dataout_i;
// SATA Primitives
// ALIGN
assign tx_align = 32'h7B4A4ABC;
// SYNC
assign tx_sync = 32'hB5B5957C;
// Dial Tone
assign tx_dial = 32'h4A4A4A4A;
// R_RDY
assign tx_r_rdy = 32'h4A4A957C;
// Mux to switch between ALIGN and other primitives/data
mux_21 i_align_count
(
.a (prim_type),
.b (ALIGN),
.sel (align_en_r),
.o (align_count_mux_out)
);
// Output to Link Layer to Pause writing data frame
assign align_en_out = align_en;
//ALIGN Primitives transmitted every 256 DWORDS for speed alignment
always@(posedge clk or posedge reset)
begin : align_cnt
if (reset)
begin
align_count <= 9'b0;
end
else if (align_count < 9'h0FF) //255
begin
if (align_count == 9'h001) //de-assert after 2 ALIGN primitives
begin
align_en <= 1'b0;
end
align_count <= align_count + 1;
end
else
begin
align_count <= 9'b0;
align_en <= 1'b1;
end
end
//OUTPUT MUX
mux_41 i_tx_out
(
.a (tx_align),
.b (tx_sync),
.c (tx_dial),
//.d (tx_r_rdy),
.d (tx_datain),
.sel (align_count_mux_out),
.o (tx_dataout_i)
);
assign tx_dataout = tx_dataout_i;
// OOB ILA
wire [15:0] trig0;
wire [15:0] trig1;
wire [15:0] trig2;
wire [15:0] trig3;
wire [31:0] trig4;
wire [3:0] trig5;
wire [31:0] trig6;
wire [31:0] trig7;
wire [35:0] control;
/*
if (CHIPSCOPE == "TRUE") begin
oob_control_ila i_oob_control_ila
(
.control(oob_control_ila_control),
.clk(clk),
.trig0(trig0),
.trig1(trig1),
.trig2(trig2),
.trig3(trig3),
.trig4(trig4),
.trig5(trig5),
.trig6(trig6),
.trig7(trig7)
);
end
*/
assign trig0[0] = txcomwake_r;
assign trig0[1] = tx_charisk;
assign trig0[2] = rxbyteisaligned_r;
assign trig0[3] = count_en;
assign trig0[4] = tx_charisk_in;
assign trig0[5] = txelecidle;
assign trig0[6] = rx_locked;
assign trig0[7] = gen2;
assign trig0[11:8] = rx_charisk_in_r;
assign trig0[15:12] = 4'b0;
assign trig1[15:12] = prim_type;
assign trig1[11:10] = 2'b0;
assign trig1[9] = align_en_r;
assign trig1[8] = rxelecidle_r;
assign trig1[7:0] = CurrentState_out;
assign trig2[15:7] = align_count;
assign trig2[6:5] = 2'b0;
assign trig2[4] = cominitdet_r;
assign trig2[3] = comwakedet_r;
assign trig2[2] = align_det;
assign trig2[1] = sync_det;
assign trig2[0] = cont_det;
assign trig3[0] = sof_det;
assign trig3[1] = eof_det;
assign trig3[2] = x_rdy_det;
assign trig3[3] = r_err_det;
assign trig3[4] = r_ok_det;
assign trig3[15:5] = 11'b0;
assign trig4 = rx_datain_r;
assign trig5[0] = txcominit_r;
assign trig5[1] = linkup_r;
assign trig5[2] = align_en;
assign trig5[3] = 1'b0;
assign trig6 = tx_datain;
assign trig7 = tx_dataout_i;
endmodule
module oob_control_ila
(
control,
clk,
trig0,
trig1,
trig2,
trig3,
trig4,
trig5,
trig6,
trig7
);
input [35:0] control;
input clk;
input [15:0] trig0;
input [15:0] trig1;
input [15:0] trig2;
input [15:0] trig3;
input [31:0] trig4;
input [3:0] trig5;
input [31:0] trig6;
input [31:0] trig7;
endmodule
-- Copyright (C) 2012
-- Ashwin A. Mendon
--
-- This file is part of SATA2 core.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------------
-- ENTITY: command_layer
-- Version: 1.0
-- Author: Ashwin Mendon
-- Description: This sub-module implements the Command Layer of the SATA Protocol
-- The User Command parameters such as: cmd_type, sector_address, sector_count
-- are encoded into a command FIS according to the ATA format and passed to
-- the Transport Layer.
--
-- PORTS:
-----------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity command_layer is
generic(
CHIPSCOPE : boolean := false
);
port(
-- Clock and Reset Signals
clk : in std_logic;
sw_reset : in std_logic;
-- ChipScope ILA / Trigger Signals
cmd_layer_ila_control : in std_logic_vector(35 downto 0);
---------------------------------------
-- Signals from/to User Logic
new_cmd : in std_logic;
cmd_done : out std_logic;
cmd_type : in std_logic_vector(1 downto 0);
sector_count : in std_logic_vector(31 downto 0);
sector_addr : in std_logic_vector(31 downto 0);
user_din : in std_logic_vector(31 downto 0);
user_din_re_out : out std_logic;
user_dout : out std_logic_vector(31 downto 0);
user_dout_re : in std_logic;
user_fifo_empty : in std_logic;
user_fifo_full : in std_logic;
sector_timer_out : out std_logic_vector(31 downto 0);
-- Signals from/to Link Layer
write_fifo_full : in std_logic;
ll_ready_for_cmd : in std_logic;
ll_cmd_start : out std_logic;
ll_cmd_type : out std_logic_vector(1 downto 0);
ll_dout : out std_logic_vector(31 downto 0);
ll_dout_we : out std_logic;
ll_din : in std_logic_vector(31 downto 0);
ll_din_re : out std_logic
);
end command_layer;
-------------------------------------------------------------------------------
-- ARCHITECTURE
-------------------------------------------------------------------------------
architecture BEHAV of command_layer is
-------------------------------------------------------------------------------
-- COMMAND LAYER
-------------------------------------------------------------------------------
constant READ_DMA : std_logic_vector(7 downto 0) := x"25";
constant WRITE_DMA : std_logic_vector(7 downto 0) := x"35";
constant REG_FIS_VALUE : std_logic_vector(7 downto 0) := x"27";
constant DATA_FIS_VALUE : std_logic_vector(7 downto 0) := x"46";
constant DEVICE_REG : std_logic_vector(7 downto 0) := x"E0";
constant FEATURES : std_logic_vector(7 downto 0) := x"00";
constant READ_DMA_CMD : std_logic_vector(1 downto 0) := "01";
constant WRITE_DMA_CMD : std_logic_vector(1 downto 0) := "10";
constant DATA_FIS_HEADER : std_logic_vector(31 downto 0) := x"00000046";
constant NDWORDS_PER_DATA_FIS : std_logic_vector(15 downto 0) := conv_std_logic_vector(2048, 16);--128*16
constant SECTOR_NDWORDS : integer := 128; -- 128 DWORDS / 512 Byte Sector
component cmd_layer_ila
port (
control : in std_logic_vector(35 downto 0);
clk : in std_logic;
trig0 : in std_logic_vector(3 downto 0);
trig1 : in std_logic_vector(31 downto 0);
trig2 : in std_logic_vector(31 downto 0);
trig3 : in std_logic_vector(31 downto 0);
trig4 : in std_logic_vector(31 downto 0);
trig5 : in std_logic_vector(1 downto 0);
trig6 : in std_logic_vector(1 downto 0);
trig7 : in std_logic_vector(31 downto 0);
trig8 : in std_logic_vector(31 downto 0);
trig9 : in std_logic_vector(23 downto 0);
trig10 : in std_logic_vector(15 downto 0);
trig11 : in std_logic_vector(11 downto 0);
trig12 : in std_logic_vector(15 downto 0);
trig13 : in std_logic_vector(31 downto 0)
);
end component;
-----------------------------------------------------------------------------
-- Finite State Machine Declaration (curr and next states)
-----------------------------------------------------------------------------
type COMMAND_FSM_TYPE is (wait_for_cmd, build_REG_FIS, send_REG_FIS_DW1,
send_REG_FIS_DW2, send_REG_FIS_DW3, send_REG_FIS_DW4, send_REG_FIS_DW5,
send_DATA_FIS_HEADER, send_write_data, send_cmd_start, wait_for_cmd_start,
wait_for_cmd_done, dead
);
signal command_fsm_curr, command_fsm_next : COMMAND_FSM_TYPE := wait_for_cmd;
signal command_fsm_value : std_logic_vector (0 to 3);
signal ll_cmd_start_next : std_logic;
signal ll_cmd_start_out : std_logic;
signal cmd_done_next : std_logic;
signal cmd_done_out : std_logic;
signal read_fifo_empty : std_logic;
signal ll_dout_next : std_logic_vector(0 to 31);
signal ll_dout_we_next : std_logic;
signal ll_dout_out : std_logic_vector(0 to 31);
signal ll_dout_we_out : std_logic;
signal ll_cmd_type_next : std_logic_vector(0 to 1);
signal ll_cmd_type_out : std_logic_vector(0 to 1);
signal dword_count : std_logic_vector(0 to 15);
signal dword_count_next : std_logic_vector(0 to 15);
signal write_data_count : std_logic_vector(0 to 31);
signal write_data_count_next : std_logic_vector(0 to 31);
signal user_din_re : std_logic;
signal sector_count_int : integer;
--- ILA signals ----
signal user_dout_ila : std_logic_vector(0 to 31);
signal ll_din_re_ila : std_logic;
--- Timer ----
signal sector_timer : std_logic_vector(31 downto 0);
--signal sata_timer : std_logic_vector(31 downto 0);
type reg_fis_type is
record
FIS_type : std_logic_vector(7 downto 0);
pad_8 : std_logic_vector(7 downto 0);
command : std_logic_vector(7 downto 0);
features : std_logic_vector(7 downto 0);
LBA : std_logic_vector(23 downto 0);
device : std_logic_vector(7 downto 0);
LBA_exp : std_logic_vector(23 downto 0);
features_exp : std_logic_vector(7 downto 0);
sector_count : std_logic_vector(15 downto 0);
pad_16 : std_logic_vector(15 downto 0);
pad_32 : std_logic_vector(31 downto 0);
end record;
signal reg_fis : reg_fis_type;
signal reg_fis_next : reg_fis_type;
-------------------------------------------------------------------------------
-- BEGIN
-------------------------------------------------------------------------------
begin
-------------------------------------------------------------------------------
-- LINK LAYER
-------------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- PROCESS: COMMAND_FSM_VALUE_PROC
-- PURPOSE: ChipScope State Indicator Signal
-----------------------------------------------------------------------------
COMMAND_FSM_VALUE_PROC : process (command_fsm_curr) is
begin
case (command_fsm_curr) is
when wait_for_cmd => command_fsm_value <= x"0";
when build_REG_FIS => command_fsm_value <= x"1";
when send_REG_FIS_DW1 => command_fsm_value <= x"2";
when send_REG_FIS_DW2 => command_fsm_value <= x"3";
when send_REG_FIS_DW3 => command_fsm_value <= x"4";
when send_REG_FIS_DW4 => command_fsm_value <= x"5";
when send_REG_FIS_DW5 => command_fsm_value <= x"6";
when send_DATA_FIS_HEADER => command_fsm_value <= x"7";
when send_write_data => command_fsm_value <= x"8";
when send_cmd_start => command_fsm_value <= x"9";
when wait_for_cmd_start => command_fsm_value <= x"A";
when wait_for_cmd_done => command_fsm_value <= x"B";
when dead => command_fsm_value <= x"C";
when others => command_fsm_value <= x"D";
end case;
end process COMMAND_FSM_VALUE_PROC;
-----------------------------------------------------------------------------
-- PROCESS: COMMAND_FSM_STATE_PROC
-- PURPOSE: Registering Signals and Next State
-----------------------------------------------------------------------------
COMMAND_FSM_STATE_PROC: process (clk)
begin
if ((clk'event) and (clk = '1')) then
if (sw_reset = '1') then
--Initializing internal signals
command_fsm_curr <= wait_for_cmd;
cmd_done_out <= '0';
ll_cmd_start_out <= '0';
ll_dout_we_out <= '0';
ll_dout_out <= (others => '0');
ll_cmd_type_out <= (others => '0');
write_data_count <= (others => '0');
dword_count <= (others => '0');
reg_fis.FIS_type <= (others => '0');
reg_fis.pad_8 <= (others => '0');
reg_fis.command <= (others => '0');
reg_fis.features <= (others => '0');
reg_fis.LBA <= (others => '0');
reg_fis.device <= (others => '0');
reg_fis.LBA_exp <= (others => '0');
reg_fis.features_exp <= (others => '0');
reg_fis.sector_count <= (others => '0');
reg_fis.pad_16 <= (others => '0');
reg_fis.pad_32 <= (others => '0');
else
-- Register all Current Signals to their _next Signals
command_fsm_curr <= command_fsm_next;
cmd_done_out <= cmd_done_next;
ll_cmd_start_out <= ll_cmd_start_next;
ll_dout_we_out <= ll_dout_we_next;
ll_dout_out <= ll_dout_next;
ll_cmd_type_out <= ll_cmd_type_next;
dword_count <= dword_count_next;
write_data_count <= write_data_count_next;
reg_fis.FIS_type <= reg_fis_next.FIS_type ;
reg_fis.pad_8 <= reg_fis_next.pad_8;
reg_fis.command <= reg_fis_next.command;
reg_fis.features <= reg_fis_next.features;
reg_fis.LBA <= reg_fis_next.LBA;
reg_fis.device <= reg_fis_next.device;
reg_fis.LBA_exp <= reg_fis_next.LBA_exp;
reg_fis.features_exp <= reg_fis_next.features_exp;
reg_fis.sector_count <= reg_fis_next.sector_count;
reg_fis.pad_16 <= reg_fis_next.pad_16;
reg_fis.pad_32 <= reg_fis_next.pad_32;
end if;
end if;
end process COMMAND_FSM_STATE_PROC;
-----------------------------------------------------------------------------
-- PROCESS: COMMAND_FSM_LOGIC_PROC
-- PURPOSE: Registering Signals and Next State
-----------------------------------------------------------------------------
COMMAND_FSM_LOGIC_PROC : process (command_fsm_curr, new_cmd, cmd_type,
ll_cmd_start_out, ll_dout_we_out,
ll_dout_out, dword_count, write_data_count
) is
begin
-- Register _next to current signals
command_fsm_next <= command_fsm_curr;
cmd_done_next <= cmd_done_out;
ll_cmd_start_next <= ll_cmd_start_out;
ll_dout_we_next <= ll_dout_we_out;
ll_dout_next <= ll_dout_out;
ll_cmd_type_next <= cmd_type;
user_din_re <= '0';
dword_count_next <= dword_count;
write_data_count_next <= write_data_count;
reg_fis_next.FIS_type <= reg_fis.FIS_type ;
reg_fis_next.pad_8 <= reg_fis.pad_8;
reg_fis_next.command <= reg_fis.command;
reg_fis_next.features <= reg_fis.features;
reg_fis_next.LBA <= reg_fis.LBA;
reg_fis_next.device <= reg_fis.device;
reg_fis_next.LBA_exp <= reg_fis.LBA_exp;
reg_fis_next.features_exp <= reg_fis.features_exp;
reg_fis_next.sector_count <= reg_fis.sector_count;
reg_fis_next.pad_16 <= reg_fis.pad_16;
reg_fis_next.pad_32 <= reg_fis.pad_32;
---------------------------------------------------------------------------
-- Finite State Machine
---------------------------------------------------------------------------
case (command_fsm_curr) is
-- x0
when wait_for_cmd =>
cmd_done_next <= '1';
ll_cmd_start_next <= '0';
ll_dout_we_next <= '0';
ll_dout_next <= (others => '0');
if (new_cmd = '1') then
cmd_done_next <= '0';
command_fsm_next <= build_REG_FIS;
end if;
-- x1
when build_REG_FIS =>
reg_fis_next.FIS_type <= REG_FIS_VALUE;
reg_fis_next.pad_8 <= x"80";
if (cmd_type = READ_DMA_CMD) then
reg_fis_next.command <= READ_DMA;
else
reg_fis_next.command <= WRITE_DMA;
end if;
reg_fis_next.features <= FEATURES;
reg_fis_next.LBA <= sector_addr(23 downto 0);
reg_fis_next.device <= DEVICE_REG;
reg_fis_next.LBA_exp <= (others => '0');
reg_fis_next.features_exp <= FEATURES;
reg_fis_next.sector_count <= sector_count(15 downto 0);
reg_fis_next.pad_16 <= (others => '0');
reg_fis_next.pad_32 <= (others => '0');
command_fsm_next <= send_REG_FIS_DW1;
-- x2
when send_REG_FIS_DW1 =>
ll_dout_next <= reg_fis.FEATURES & reg_fis.command & reg_fis.pad_8 & reg_fis.FIS_type;
ll_dout_we_next <= '1';
command_fsm_next <= send_REG_FIS_DW2;
-- x3
when send_REG_FIS_DW2 =>
ll_dout_next <= reg_fis.device & reg_fis.LBA;
ll_dout_we_next <= '1';
command_fsm_next <= send_REG_FIS_DW3;
-- x4
when send_REG_FIS_DW3 =>
ll_dout_next <= reg_fis.features_exp & reg_fis.LBA_exp;
ll_dout_we_next <= '1';
command_fsm_next <= send_REG_FIS_DW4;
-- x5
when send_REG_FIS_DW4 =>
ll_dout_next <= reg_fis.pad_16 & reg_fis.sector_count ;
ll_dout_we_next <= '1';
command_fsm_next <= send_REG_FIS_DW5;
-- x6
when send_REG_FIS_DW5 =>
ll_dout_next <= reg_fis.pad_32;
ll_dout_we_next <= '1';
command_fsm_next <= send_cmd_start;
-- x7
when send_DATA_FIS_HEADER =>
if (user_fifo_full = '1') then
ll_dout_next <= DATA_FIS_HEADER;
ll_dout_we_next <= '1';
command_fsm_next <= send_write_data;
end if;
-- x8
when send_write_data =>
if(dword_count >= NDWORDS_PER_DATA_FIS) then
user_din_re <= '0';
ll_dout_we_next <= '0';
ll_dout_next <= (others => '0');
dword_count_next <= (others => '0');
command_fsm_next <= send_DATA_FIS_HEADER;
elsif (write_fifo_full = '1' or user_fifo_empty = '1') then
user_din_re <= '0';
ll_dout_we_next <= '0';
ll_dout_next <= (others => '0');
else
write_data_count_next <= write_data_count + 1;
dword_count_next <= dword_count + 1;
user_din_re <= '1';
ll_dout_next <= user_din;
ll_dout_we_next <= '1';
end if;
if (write_data_count = (SECTOR_NDWORDS*sector_count_int)) then
write_data_count_next <= (others => '0');
dword_count_next <= (others => '0');
user_din_re <= '0';
ll_dout_we_next <= '0';
ll_dout_next <= (others => '0');
command_fsm_next <= wait_for_cmd_done;
end if;
-- x9
when send_cmd_start =>
ll_dout_we_next <= '0';
ll_dout_next <= (others => '0');
if (ll_ready_for_cmd = '1') then
ll_cmd_start_next <= '1';
command_fsm_next <= wait_for_cmd_start;
end if;
-- xA
when wait_for_cmd_start =>
ll_cmd_start_next <= '0';
if (ll_ready_for_cmd = '0') then
if (cmd_type = READ_DMA_CMD) then
command_fsm_next <= wait_for_cmd_done;
else
command_fsm_next <= send_DATA_FIS_HEADER;
end if;
end if;
-- xB
when wait_for_cmd_done =>
if (ll_ready_for_cmd = '1') then
cmd_done_next <= '1';
command_fsm_next <= wait_for_cmd;
end if;
-- xC
when dead =>
command_fsm_next <= dead;
-- xD
when others =>
command_fsm_next <= dead;
end case;
end process COMMAND_FSM_LOGIC_PROC;
cmd_done <= cmd_done_out;
ll_cmd_start <= ll_cmd_start_out;
ll_cmd_type <= ll_cmd_type_out;
user_din_re_out <= user_din_re;
user_dout_ila <= ll_din;
user_dout <= user_dout_ila;
ll_dout <= ll_dout_out;
ll_dout_we <= ll_dout_we_out;
ll_din_re_ila <= user_dout_re;
ll_din_re <= ll_din_re_ila;
sector_count_int <= conv_integer(sector_count);
-----------------------------------------------------------------------------
-- PROCESS: TIMER PROCESS
-- PURPOSE: Count time to read a sector
-----------------------------------------------------------------------------
TIMER_PROC: process (clk)
begin
if ((clk'event) and (clk = '1')) then
if (sw_reset = '1') then
sector_timer <= (others => '0');
-- sata_timer <= (others => '0');
--elsif ((command_fsm_curr = wait_for_cmd_done) and (ready_for_cmd = '1')) then
--sata_timer <= sata_timer + sector_timer;
elsif (command_fsm_curr = wait_for_cmd) then
if (new_cmd = '1') then
sector_timer <= (others => '0');
else
sector_timer <= sector_timer;
end if;
else
sector_timer <= sector_timer + '1';
end if;
end if;
end process TIMER_PROC;
sector_timer_out <= sector_timer;
chipscope_gen_ila : if (CHIPSCOPE) generate
CMD_LAYER_ILA_i : cmd_layer_ila
port map (
control => cmd_layer_ila_control,
clk => clk,
trig0 => command_fsm_value,
trig1 => user_din,
trig2 => user_dout_ila,
trig3 => ll_din,
trig4 => ll_dout_out,
trig5 => cmd_type,
trig6 => ll_cmd_type_out,
trig7 => sector_timer,
trig8 => sector_addr,
trig9 => reg_fis.LBA,
trig10 => reg_fis.sector_count,
trig11(0) => new_cmd,
trig11(1) => user_din_re,
trig11(2) => user_dout_re,
trig11(3) => ll_ready_for_cmd,
trig11(4) => ll_cmd_start_out,
trig11(5) => ll_dout_we_out,
trig11(6) => ll_din_re_ila,
trig11(7) => cmd_done_out,
trig11(8) => '0',
trig11(9) => write_fifo_full,
trig11(10) => user_fifo_empty,
trig11(11) => user_fifo_full,
trig12 => dword_count,
trig13 => write_data_count
);
end generate chipscope_gen_ila;
end BEHAV;
-- Copyright (C) 2012
-- Ashwin A. Mendon
--
-- This file is part of SATA2 core.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------------
-- ENTITY: crc
-- Version: 1.0
-- Author: Ashwin Mendon
-- Description: This sub-module implements the CRC Circuit for the SATA Protocol
-- The code takes 32-bit data word inputs and calculates the CRC for the stream
-- The generator polynomial used is
-- 32 26 23 22 16 12 11 10 8 7 5 4 2
-- G(x) = x + x + x + x + x + x + x + x + x + x + x + x + x + x + 1
-- The CRC value is initialized to 0x52325032 as defined in the Serial ATA
-- specification
-- PORTS:
-----------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity crc is
generic(
CHIPSCOPE : boolean := false
);
port(
-- Clock and Reset Signals
clk : in std_logic;
reset : in std_logic;
-- ChipScope ILA / Trigger Signals
--crc_ila_control : in std_logic_vector(35 downto 0);
---------------------------------------
-- Signals from/to Sata Link Layer
crc_en : in std_logic;
data_in : in std_logic_vector(0 to 31);
data_out : out std_logic_vector(0 to 31)
);
end crc;
-------------------------------------------------------------------------------
-- ARCHITECTURE
-------------------------------------------------------------------------------
architecture BEHAV of crc is
-------------------------------------------------------------------------------
-- Constants
-------------------------------------------------------------------------------
constant CRC_INIT : std_logic_vector(0 to 31) := x"52325032";
signal crc : std_logic_vector (31 downto 0);
signal crc_next : std_logic_vector (31 downto 0);
signal crc_new : std_logic_vector (31 downto 0);
signal data_out_ila : std_logic_vector (31 downto 0);
-------------------------------------------------------------------------------
-- BEGIN
-------------------------------------------------------------------------------
begin
-----------------------------------------------------------------------------
-- PROCESS: CRC_PROC
-- PURPOSE: Registering Signals and Next State
-----------------------------------------------------------------------------
CRC_PROC : process (clk)
begin
if ((clk'event) and (clk = '1')) then
if (reset = '1') then
--Initializing internal signals
crc <= CRC_INIT;
elsif (crc_en = '1') then
-- Register all Current Signals to their _next Signals
crc <= crc_next;
else
crc <= crc;
end if;
end if;
end process CRC_PROC ;
crc_new <= crc xor data_in;
crc_next(31) <= crc_new(31) xor crc_new(30) xor crc_new(29) xor crc_new(28) xor crc_new(27) xor crc_new(25) xor crc_new(24) xor
crc_new(23) xor crc_new(15) xor crc_new(11) xor crc_new(9) xor crc_new(8) xor crc_new(5);
crc_next(30) <= crc_new(30) xor crc_new(29) xor crc_new(28) xor crc_new(27) xor crc_new(26) xor crc_new(24) xor crc_new(23) xor
crc_new(22) xor crc_new(14) xor crc_new(10) xor crc_new(8) xor crc_new(7) xor crc_new(4);
crc_next(29) <= crc_new(31) xor crc_new(29) xor crc_new(28) xor crc_new(27) xor crc_new(26) xor crc_new(25) xor crc_new(23) xor
crc_new(22) xor crc_new(21) xor crc_new(13) xor crc_new(9) xor crc_new(7) xor crc_new(6) xor crc_new(3);
crc_next(28) <= crc_new(30) xor crc_new(28) xor crc_new(27) xor crc_new(26) xor crc_new(25) xor crc_new(24) xor crc_new(22) xor
crc_new(21) xor crc_new(20) xor crc_new(12) xor crc_new(8) xor crc_new(6) xor crc_new(5) xor crc_new(2);
crc_next(27) <= crc_new(29) xor crc_new(27) xor crc_new(26) xor crc_new(25) xor crc_new(24) xor crc_new(23) xor crc_new(21) xor
crc_new(20) xor crc_new(19) xor crc_new(11) xor crc_new(7) xor crc_new(5) xor crc_new(4) xor crc_new(1);
crc_next(26) <= crc_new(31) xor crc_new(28) xor crc_new(26) xor crc_new(25) xor crc_new(24) xor crc_new(23) xor crc_new(22) xor
crc_new(20) xor crc_new(19) xor crc_new(18) xor crc_new(10) xor crc_new(6) xor crc_new(4) xor crc_new(3) xor
crc_new(0);
crc_next(25) <= crc_new(31) xor crc_new(29) xor crc_new(28) xor crc_new(22) xor crc_new(21) xor crc_new(19) xor crc_new(18) xor
crc_new(17) xor crc_new(15) xor crc_new(11) xor crc_new(8) xor crc_new(3) xor crc_new(2);
crc_next(24) <= crc_new(30) xor crc_new(28) xor crc_new(27) xor crc_new(21) xor crc_new(20) xor crc_new(18) xor crc_new(17) xor
crc_new(16) xor crc_new(14) xor crc_new(10) xor crc_new(7) xor crc_new(2) xor crc_new(1);
crc_next(23) <= crc_new(31) xor crc_new(29) xor crc_new(27) xor crc_new(26) xor crc_new(20) xor crc_new(19) xor crc_new(17) xor
crc_new(16) xor crc_new(15) xor crc_new(13) xor crc_new(9) xor crc_new(6) xor crc_new(1) xor crc_new(0);
crc_next(22) <= crc_new(31) xor crc_new(29) xor crc_new(27) xor crc_new(26) xor crc_new(24) xor crc_new(23) xor crc_new(19) xor
crc_new(18) xor crc_new(16) xor crc_new(14) xor crc_new(12) xor crc_new(11) xor crc_new(9) xor crc_new(0);
crc_next(21) <= crc_new(31) xor crc_new(29) xor crc_new(27) xor crc_new(26) xor crc_new(24) xor crc_new(22) xor crc_new(18) xor
crc_new(17) xor crc_new(13) xor crc_new(10) xor crc_new(9) xor crc_new(5);
crc_next(20) <= crc_new(30) xor crc_new(28) xor crc_new(26) xor crc_new(25) xor crc_new(23) xor crc_new(21) xor crc_new(17) xor
crc_new(16) xor crc_new(12) xor crc_new(9) xor crc_new(8) xor crc_new(4);
crc_next(19) <= crc_new(29) xor crc_new(27) xor crc_new(25) xor crc_new(24) xor crc_new(22) xor crc_new(20) xor crc_new(16) xor
crc_new(15) xor crc_new(11) xor crc_new(8) xor crc_new(7) xor crc_new(3);
crc_next(18) <= crc_new(31) xor crc_new(28) xor crc_new(26) xor crc_new(24) xor crc_new(23) xor crc_new(21) xor crc_new(19) xor
crc_new(15) xor crc_new(14) xor crc_new(10) xor crc_new(7) xor crc_new(6) xor crc_new(2);
crc_next(17) <= crc_new(31) xor crc_new(30) xor crc_new(27) xor crc_new(25) xor crc_new(23) xor crc_new(22) xor crc_new(20) xor
crc_new(18) xor crc_new(14) xor crc_new(13) xor crc_new(9) xor crc_new(6) xor crc_new(5) xor crc_new(1);
crc_next(16) <= crc_new(30) xor crc_new(29) xor crc_new(26) xor crc_new(24) xor crc_new(22) xor crc_new(21) xor crc_new(19) xor
crc_new(17) xor crc_new(13) xor crc_new(12) xor crc_new(8) xor crc_new(5) xor crc_new(4) xor crc_new(0);
crc_next(15) <= crc_new(30) xor crc_new(27) xor crc_new(24) xor crc_new(21) xor crc_new(20) xor crc_new(18) xor crc_new(16) xor
crc_new(15) xor crc_new(12) xor crc_new(9) xor crc_new(8) xor crc_new(7) xor crc_new(5) xor crc_new(4) xor
crc_new(3);
crc_next(14) <= crc_new(29) xor crc_new(26) xor crc_new(23) xor crc_new(20) xor crc_new(19) xor crc_new(17) xor crc_new(15) xor
crc_new(14) xor crc_new(11) xor crc_new(8) xor crc_new(7) xor crc_new(6) xor crc_new(4) xor crc_new(3) xor
crc_new(2);
crc_next(13) <= crc_new(31) xor crc_new(28) xor crc_new(25) xor crc_new(22) xor crc_new(19) xor crc_new(18) xor crc_new(16) xor
crc_new(14) xor crc_new(13) xor crc_new(10) xor crc_new(7) xor crc_new(6) xor crc_new(5) xor crc_new(3) xor
crc_new(2) xor crc_new(1);
crc_next(12) <= crc_new(31) xor crc_new(30) xor crc_new(27) xor crc_new(24) xor crc_new(21) xor crc_new(18) xor crc_new(17) xor
crc_new(15) xor crc_new(13) xor crc_new(12) xor crc_new(9) xor crc_new(6) xor crc_new(5) xor crc_new(4) xor
crc_new(2) xor crc_new(1) xor crc_new(0);
crc_next(11) <= crc_new(31) xor crc_new(28) xor crc_new(27) xor crc_new(26) xor crc_new(25) xor crc_new(24) xor crc_new(20) xor
crc_new(17) xor crc_new(16) xor crc_new(15) xor crc_new(14) xor crc_new(12) xor crc_new(9) xor crc_new(4) xor
crc_new(3) xor crc_new(1) xor crc_new(0);
crc_next(10) <= crc_new(31) xor crc_new(29) xor crc_new(28) xor crc_new(26) xor crc_new(19) xor crc_new(16) xor crc_new(14) xor
crc_new(13) xor crc_new(9) xor crc_new(5) xor crc_new(3) xor crc_new(2) xor crc_new(0);
crc_next(9) <= crc_new(29) xor crc_new(24) xor crc_new(23) xor crc_new(18) xor crc_new(13) xor crc_new(12) xor crc_new(11) xor
crc_new(9) xor crc_new(5) xor crc_new(4) xor crc_new(2) xor crc_new(1);
crc_next(8) <= crc_new(31) xor crc_new(28) xor crc_new(23) xor crc_new(22) xor crc_new(17) xor crc_new(12) xor crc_new(11) xor
crc_new(10) xor crc_new(8) xor crc_new(4) xor crc_new(3) xor crc_new(1) xor crc_new(0);
crc_next(7) <= crc_new(29) xor crc_new(28) xor crc_new(25) xor crc_new(24) xor crc_new(23) xor crc_new(22) xor crc_new(21) xor
crc_new(16) xor crc_new(15) xor crc_new(10) xor crc_new(8) xor crc_new(7) xor crc_new(5) xor crc_new(3) xor
crc_new(2) xor crc_new(0);
crc_next(6) <= crc_new(30) xor crc_new(29) xor crc_new(25) xor crc_new(22) xor crc_new(21) xor crc_new(20) xor crc_new(14) xor
crc_new(11) xor crc_new(8) xor crc_new(7) xor crc_new(6) xor crc_new(5) xor crc_new(4) xor crc_new(2) xor
crc_new(1);
crc_next(5) <= crc_new(29) xor crc_new(28) xor crc_new(24) xor crc_new(21) xor crc_new(20) xor crc_new(19) xor crc_new(13) xor
crc_new(10) xor crc_new(7) xor crc_new(6) xor crc_new(5) xor crc_new(4) xor crc_new(3) xor crc_new(1) xor
crc_new(0);
crc_next(4) <= crc_new(31) xor crc_new(30) xor crc_new(29) xor crc_new(25) xor crc_new(24) xor crc_new(20) xor crc_new(19) xor
crc_new(18) xor crc_new(15) xor crc_new(12) xor crc_new(11) xor crc_new(8) xor crc_new(6) xor crc_new(4) xor
crc_new(3) xor crc_new(2) xor crc_new(0);
crc_next(3) <= crc_new(31) xor crc_new(27) xor crc_new(25) xor crc_new(19) xor crc_new(18) xor crc_new(17) xor crc_new(15) xor
crc_new(14) xor crc_new(10) xor crc_new(9) xor crc_new(8) xor crc_new(7) xor crc_new(3) xor crc_new(2) xor
crc_new(1);
crc_next(2) <= crc_new(31) xor crc_new(30) xor crc_new(26) xor crc_new(24) xor crc_new(18) xor crc_new(17) xor crc_new(16) xor
crc_new(14) xor crc_new(13) xor crc_new(9) xor crc_new(8) xor crc_new(7) xor crc_new(6) xor crc_new(2) xor
crc_new(1) xor crc_new(0);
crc_next(1) <= crc_new(28) xor crc_new(27) xor crc_new(24) xor crc_new(17) xor crc_new(16) xor crc_new(13) xor crc_new(12) xor
crc_new(11) xor crc_new(9) xor crc_new(7) xor crc_new(6) xor crc_new(1) xor crc_new(0);
crc_next(0) <= crc_new(31) xor crc_new(30) xor crc_new(29) xor crc_new(28) xor crc_new(26) xor crc_new(25) xor crc_new(24) xor
crc_new(16) xor crc_new(12) xor crc_new(10) xor crc_new(9) xor crc_new(6) xor crc_new(0);
data_out_ila <= crc_next;
--data_out_ila <= crc;
-----------------------------------------------------------------------------
-- ILA Instantiation
-----------------------------------------------------------------------------
data_out <= data_out_ila;
end BEHAV;
-- Copyright (C) 2012
-- Ashwin A. Mendon
--
-- This file is part of SATA2 core.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------
-- Entity mux_161
-- Version: 1.0
-- Author: Ashwin Mendon
-- Description: 32 bit 16:1 Multiplexer
--
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity mux_161 is
generic(
DATA_WIDTH: natural := 32
);
port(
a : in std_logic_vector(DATA_WIDTH-1 downto 0);
b : in std_logic_vector(DATA_WIDTH-1 downto 0);
c : in std_logic_vector(DATA_WIDTH-1 downto 0);
d : in std_logic_vector(DATA_WIDTH-1 downto 0);
e : in std_logic_vector(DATA_WIDTH-1 downto 0);
f : in std_logic_vector(DATA_WIDTH-1 downto 0);
g : in std_logic_vector(DATA_WIDTH-1 downto 0);
h : in std_logic_vector(DATA_WIDTH-1 downto 0);
i : in std_logic_vector(DATA_WIDTH-1 downto 0);
j : in std_logic_vector(DATA_WIDTH-1 downto 0);
k : in std_logic_vector(DATA_WIDTH-1 downto 0);
l : in std_logic_vector(DATA_WIDTH-1 downto 0);
m : in std_logic_vector(DATA_WIDTH-1 downto 0);
n : in std_logic_vector(DATA_WIDTH-1 downto 0);
o : in std_logic_vector(DATA_WIDTH-1 downto 0);
p : in std_logic_vector(DATA_WIDTH-1 downto 0);
sel : in std_logic_vector(3 downto 0);
output : out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end mux_161;
architecture mux_behav of mux_161 is
begin
process(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,sel)
begin
case (sel) is
when "0000" =>
output <= a;
when "0001" =>
output <= b;
when "0010" =>
output <= c;
when "0011" =>
output <= d;
when "0100" =>
output <= e;
when "0101" =>
output <= f;
when "0110" =>
output <= g;
when "0111" =>
output <= h;
when "1000" =>
output <= i;
when "1001" =>
output <= j;
when "1010" =>
output <= k;
when "1011" =>
output <= l;
when "1100" =>
output <= m;
when "1101" =>
output <= n;
when "1110" =>
output <= o;
when others =>
output <= p;
end case;
end process;
end mux_behav;
-- Copyright (C) 2012
-- Ashwin A. Mendon
--
-- This file is part of SATA2 core.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------------
-- ENTITY: sata_core
-- Version: 1.0
-- Author: Ashwin Mendon
-- Description: The SATA core implements the Command, Transport and Link Layers of
-- the SATA protocol and provides a Physical Layer Wrapper for the GTX
-- transceivers. The Physical Layer Wrapper also includes an Out of Band
-- Signaling (OOB) controller state machine which deals with initialization
-- and synchronization of the SATA link. It can interface with SATA 2
-- Winchester style Hard Disks as well as Flash-based Solid State Drives
-- The core provides a simple interface to issue READ/WRITE sector commands.
-- The DATA interface is 32-bit FIFO like.
-- A 150 MHz input reference clock is needed for the GTX transceivers.
-- The output data is delivered 4 bytes @ 75 MHz (user output clock)
-- for a theoretical peak bandwidth of 300 MB/s (SATA 2).
--
--
-- PORTS:
-- Command, Control and Status --
-- ready_for_cmd : When asserted, SATA core is ready to execute new command.
-- This signal goes low after new_cmd is asserted.
-- It also serves as the command done signal
-- new_cmd : Asserted for one clock cycle to start a request
-- cmd_type : "01" for READ request and "10" for WRITE request
-- sector_count : Number of sectors requested by user
-- sector_addr : Starting address of request
-- Data and User Clock --
-- sata_din : Data from user to Write to Disk
-- sata_din_we : Write Enable to SATA Core when FULL is low
-- sata_core_full : SATA Core Full- de-assert WE
-- sata_dout : Data output from SATA Core
-- sata_dout_re : Read Enable from SATA asserted when EMPTY is low
-- sata_core_empty : SATA Core Empty- de-assert RE
-- SATA_USER_DATA_CLK_IN : SATA Core Write Clock
-- SATA_USER_DATA_CLK_OUT : SATA Core Read Clock
-- sata_timer : SATA core timer output to check performance
--PHY Signals--
-- CLKIN_150 : 150 Mhz input reference clock for the GTX transceivers
-- reset : Resets GTX and SATA core; can be tied to a software reset
-- LINKUP : Indicates Link Initialization done (OOB) and SATA link is up
--GTX transmit/receive pins: Connected to the FMC_HPC pins on a ML605 board
-- TXP0_OUT, TXN0_OUT, RXP0_IN, RXN0_IN
-----------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity sata_core is
generic(
CHIPSCOPE : boolean := false;
DATA_WIDTH : natural := 32
);
port(
-- ChipScope ILA / Trigger Signals
sata_rx_frame_ila_control : in std_logic_vector(35 downto 0);
sata_tx_frame_ila_control : in std_logic_vector(35 downto 0);
sata_phy_ila_control : in std_logic_vector(35 downto 0);
oob_control_ila_control : in std_logic_vector(35 downto 0);
cmd_layer_ila_control : in std_logic_vector(35 downto 0);
scrambler_ila_control : in std_logic_vector(35 downto 0);
descrambler_ila_control : in std_logic_vector(35 downto 0);
---------------------------------------
-- SATA Interface -----
-- Command, Control and Status --
ready_for_cmd : out std_logic;
new_cmd : in std_logic;
cmd_type : in std_logic_vector(1 downto 0);
sector_count : in std_logic_vector(31 downto 0);
sector_addr : in std_logic_vector(31 downto 0);
-- Data and User Clock --
sata_din : in std_logic_vector(31 downto 0);
sata_din_we : in std_logic;
sata_core_full : out std_logic;
sata_dout : out std_logic_vector(31 downto 0);
sata_dout_re : in std_logic;
sata_core_empty : out std_logic;
SATA_USER_DATA_CLK_IN : in std_logic;
SATA_USER_DATA_CLK_OUT : out std_logic;
-- Timer --
sata_timer : out std_logic_vector(31 downto 0);
-- PHY Signals
-- Clock and Reset Signals
CLKIN_150 : in std_logic;
reset : in std_logic;
LINKUP : out std_logic;
TXP0_OUT : out std_logic;
TXN0_OUT : out std_logic;
RXP0_IN : in std_logic;
RXN0_IN : in std_logic;
PLLLKDET_OUT_N : out std_logic;
DCMLOCKED_OUT : out std_logic
);
end sata_core;
-------------------------------------------------------------------------------
-- ARCHITECTURE
-------------------------------------------------------------------------------
architecture BEHAV of sata_core is
-- Sata Phy
signal sata_user_clk : std_logic;
--signal GTXRESET : std_logic;
signal LINKUP_i : std_logic;
-- Sata Phy
signal REFCLK_PAD_P_IN_i : std_logic;
signal REFCLK_PAD_N_IN_i : std_logic;
-- COMMAND LAYER / LINK LAYER SIGNALS
signal ll_ready_for_cmd_i : std_logic;
signal sata_ready_for_cmd_i : std_logic;
signal ll_cmd_start : std_logic;
signal ll_cmd_type : std_logic_vector(1 downto 0);
signal ll_dout : std_logic_vector(31 downto 0);
signal ll_dout_we : std_logic;
signal ll_din : std_logic_vector(31 downto 0);
signal ll_din_re : std_logic;
signal sector_count_int : integer;
-- User FIFO signals
signal user_din_re : std_logic;
signal user_fifo_dout : std_logic_vector(31 downto 0);
signal user_fifo_full : std_logic;
signal user_fifo_prog_full : std_logic;
signal user_fifo_empty : std_logic;
signal write_fifo_full_i : std_logic;
signal read_fifo_empty : std_logic;
-- USER FIFO DECLARATION
component user_fifo
port (
rst: IN std_logic;
wr_clk: IN std_logic;
din: IN std_logic_VECTOR(31 downto 0);
wr_en: IN std_logic;
rd_clk: IN std_logic;
rd_en: IN std_logic;
dout: OUT std_logic_VECTOR(31 downto 0);
full: OUT std_logic;
prog_full: OUT std_logic;
empty: OUT std_logic);
end component;
-------------------------------------------------------------------------------
-- BEGIN
-------------------------------------------------------------------------------
begin
--- User Logic Fifo for writing data ---
USER_FIFO_i : user_fifo
port map (
rst => reset,
wr_clk => SATA_USER_DATA_CLK_IN,
din => sata_din,
wr_en => sata_din_we,
rd_clk => sata_user_clk,
dout => user_fifo_dout,
rd_en => user_din_re,
full => user_fifo_full,
prog_full => user_fifo_prog_full,
empty => user_fifo_empty);
-- SATA Core Output Signals
ready_for_cmd <= sata_ready_for_cmd_i;
--sata_core_full <= write_fifo_full_i;
sata_core_full <= user_fifo_prog_full;
sata_core_empty <= read_fifo_empty;
SATA_USER_DATA_CLK_OUT <= sata_user_clk;
LINKUP <= LINKUP_i;
-----------------------------------------------------------------------------
-- Command Layer Instance
-----------------------------------------------------------------------------
COMMAND_LAYER_i : entity work.command_layer
generic map
(
CHIPSCOPE => CHIPSCOPE
)
port map
(
-- ChipScope Signal
cmd_layer_ila_control => cmd_layer_ila_control,
-- Clock and Reset Signals
sw_reset => reset,
clk => sata_user_clk,
new_cmd => new_cmd,
cmd_done => sata_ready_for_cmd_i,
cmd_type => cmd_type,
sector_count => sector_count,
sector_addr => sector_addr,
user_din => user_fifo_dout,
user_din_re_out => user_din_re,
user_dout => sata_dout,
user_dout_re => sata_dout_re,
write_fifo_full => write_fifo_full_i,
user_fifo_empty => user_fifo_empty,
user_fifo_full => user_fifo_prog_full,
sector_timer_out => sata_timer,
-- Signals from/to Link Layer
ll_ready_for_cmd => ll_ready_for_cmd_i,
ll_cmd_start => ll_cmd_start,
ll_cmd_type => ll_cmd_type,
ll_dout => ll_dout,
ll_dout_we => ll_dout_we,
ll_din => ll_din,
ll_din_re => ll_din_re
);
------------------------------------------
-- Sata Link Layer Module Instance
------------------------------------------
sector_count_int <= conv_integer(sector_count);
SATA_LINK_LAYER_i: entity work.sata_link_layer
generic map(
CHIPSCOPE => CHIPSCOPE,
DATA_WIDTH => DATA_WIDTH
)
port map(
-- Clock and Reset Signals
CLKIN_150 => CLKIN_150,
sw_reset => reset,
-- ChipScope ILA / Trigger Signals
sata_rx_frame_ila_control => sata_rx_frame_ila_control ,
sata_tx_frame_ila_control => sata_tx_frame_ila_control ,
oob_control_ila_control => oob_control_ila_control,
sata_phy_ila_control => sata_phy_ila_control,
scrambler_ila_control => scrambler_ila_control,
descrambler_ila_control => descrambler_ila_control,
---------------------------------------
-- Ports from/to User Logic
read_fifo_empty => read_fifo_empty,
write_fifo_full => write_fifo_full_i,
GTX_RESET_IN => reset,
sector_count => sector_count_int,
sata_user_clk_out => sata_user_clk,
-- Ports from/to Command Layer
ready_for_cmd_out => ll_ready_for_cmd_i,
new_cmd_in => ll_cmd_start,
cmd_type => ll_cmd_type,
sata_din => ll_dout,
sata_din_we => ll_dout_we,
sata_dout => ll_din,
sata_dout_re => ll_din_re,
---------------------------------------
-- Ports to SATA PHY
REFCLK_PAD_P_IN => REFCLK_PAD_P_IN_i,
REFCLK_PAD_N_IN => REFCLK_PAD_N_IN_i,
TXP0_OUT => TXP0_OUT,
TXN0_OUT => TXN0_OUT,
RXP0_IN => RXP0_IN,
RXN0_IN => RXN0_IN,
PLLLKDET_OUT_N => PLLLKDET_OUT_N,
DCMLOCKED_OUT => DCMLOCKED_OUT,
LINKUP_led => LINKUP_i
);
end BEHAV;
-- Copyright (C) 2012
-- Ashwin A. Mendon
--
-- This file is part of SATA2 core.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------------
-- ENTITY: sata_link_layer
-- Version: 1.0
-- Author: Ashwin Mendon
-- Description: This sub-module implements the Transport and Link Layers of the SATA Protocol
-- It is the heart of the SATA Core where the major functions of sending/receiving
-- sequences of Frame Information Structures (FIS), packing them into
-- Frames and sending/receiving Frames are accomplished.
-- The Master FSM deals with the Transport Layer functions of sending receiving FISs
-- using the TX and RX FSMs.
-- The TX and RX FSMs use the crc, scrambler and primitive muxes to construct and
-- deconstruct Frames. They also implement a Frame transmission/reception protocol.
-- PORTS:
-----------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity sata_link_layer is
generic(
CHIPSCOPE : boolean := false;
DATA_WIDTH : natural := 32
);
port(
-- Clock and Reset Signals
--clk : in std_logic;
sw_reset : in std_logic;
-- ChipScope ILA / Trigger Signals
sata_rx_frame_ila_control : in std_logic_vector(35 downto 0);
sata_tx_frame_ila_control : in std_logic_vector(35 downto 0);
--master_fsm_ila_control : in std_logic_vector(35 downto 0);
oob_control_ila_control : in std_logic_vector(35 downto 0);
sata_phy_ila_control : in std_logic_vector(35 downto 0);
scrambler_ila_control : in std_logic_vector (35 downto 0);
descrambler_ila_control : in std_logic_vector (35 downto 0);
---------------------------------------
-- Signals from/to User Logic
sata_user_clk_out : out std_logic;
GTX_RESET_IN : in std_logic;
ready_for_cmd_out : out std_logic;
new_cmd_in : in std_logic;
cmd_type : in std_logic_vector(1 downto 0);
sector_count : in integer;
sata_din : in std_logic_vector(DATA_WIDTH-1 downto 0);
sata_din_we : in std_logic;
sata_dout : out std_logic_vector(DATA_WIDTH-1 downto 0);
sata_dout_re : in std_logic;
read_fifo_empty : out std_logic;
write_fifo_full : out std_logic;
---------------------------------------
-- Ports from/to SATA PHY
REFCLK_PAD_P_IN : in std_logic; -- MGTCLKA, clocks GTP_X0Y0-2
REFCLK_PAD_N_IN : in std_logic; -- MGTCLKA
TXP0_OUT : out std_logic;
TXN0_OUT : out std_logic;
RXP0_IN : in std_logic;
RXN0_IN : in std_logic;
PLLLKDET_OUT_N : out std_logic;
DCMLOCKED_OUT : out std_logic;
LINKUP_led : out std_logic;
--GEN2_led : out std_logic;
CLKIN_150 : in std_logic
);
end sata_link_layer;
-------------------------------------------------------------------------------
-- ARCHITECTURE
-------------------------------------------------------------------------------
architecture BEHAV of sata_link_layer is
-------------------------------------------------------------------------------
-- LINK LAYER
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Constants
-------------------------------------------------------------------------------
--Commands
constant IDEN_DEV : std_logic_vector(1 downto 0) := "00";
constant READ_DMA : std_logic_vector(1 downto 0) := "01";
constant WRITE_DMA : std_logic_vector(1 downto 0) := "10";
constant SET_FEATURES : std_logic_vector(1 downto 0) := "11";
--Primitves
constant SYNC : std_logic_vector(3 downto 0) := "0000";
constant R_RDY : std_logic_vector(3 downto 0) := "0001";
constant R_IP : std_logic_vector(3 downto 0) := "0010";
constant R_OK : std_logic_vector(3 downto 0) := "0011";
constant R_ERR : std_logic_vector(3 downto 0) := "0100";
constant X_RDY : std_logic_vector(3 downto 0) := "0101";
constant WTRM : std_logic_vector(3 downto 0) := "0110";
constant HOLD : std_logic_vector(3 downto 0) := "0111";
constant HOLD_ACK : std_logic_vector(3 downto 0) := "1000";
constant CONT : std_logic_vector(3 downto 0) := "1001";
constant SOF : std_logic_vector(3 downto 0) := "1010";
constant EOF : std_logic_vector(3 downto 0) := "1011";
constant FIS : std_logic_vector(3 downto 0) := "1100";
constant PRIM_SCRM : std_logic_vector(3 downto 0) := "1101";
constant COMMAND_FIS : std_logic_vector(15 downto 0) := conv_std_logic_vector(5, 16); -- (6DWORDS: 5 + 1CRC)
--constant DATA_FIS : std_logic_vector(15 downto 0) := conv_std_logic_vector(259, 16); -- 260 WORDS (130DWORDS: 1FIS_TYPE + 128DATA + 1CRC)
constant REG_FIS_NDWORDS : std_logic_vector(15 downto 0) := conv_std_logic_vector(6, 16); -- (6DWORDS: 5 + 1CRC)
constant DATA_FIS_NDWORDS : integer := 130;
constant SECTOR_NDWORDS : integer := 128; -- 256 WORDS / 512 Byte Sector
constant NDWORDS_PER_DATA_FIS : std_logic_vector(15 downto 0) := conv_std_logic_vector(2048, 16);--128*16
constant NDWORDS_PER_DATA_FIS_32 : std_logic_vector(31 downto 0) := conv_std_logic_vector(2048, 32);--128*16
constant SYNC_COUNT_VALUE : std_logic_vector(7 downto 0) := conv_std_logic_vector(30, 8); -- 50 WORDS
-----------------------------------------------------------------------------
-- Finite State Machine Declaration (curr and next states)
-----------------------------------------------------------------------------
type MASTER_FSM_TYPE is (idle, capture_dev_sign, wait_for_cmd, H2D_REG_FIS, D2H_DMA_ACT_FIS,
H2D_DATA_FIS, D2H_REG_FIS, D2H_DATA_FIS, D2H_PIO_SETUP, dead
);
signal master_fsm_curr, master_fsm_next : MASTER_FSM_TYPE := idle;
signal master_fsm_value : std_logic_vector (0 to 3);
type RX_FRAME_FSM_TYPE is (idle, send_R_RDY, send_R_IP, send_HOLD_ACK, send_R_OK,
send_SYNC, wait_for_X_RDY, dead
);
signal rx_frame_curr, rx_frame_next : RX_FRAME_FSM_TYPE := idle;
signal rx_frame_value : std_logic_vector (0 to 3);
type TX_FRAME_FSM_TYPE is (idle, send_X_RDY, send_SOF, send_FIS, send_EOF, send_WTRM,
send_SYNC, send_HOLD_ACK, send_HOLD, dead
);
signal tx_frame_curr, tx_frame_next : TX_FRAME_FSM_TYPE := idle;
signal tx_frame_value : std_logic_vector (0 to 3);
-----------------------------------------------------------------------------
-- Finite State Machine Declaration (curr and next states)
-----------------------------------------------------------------------------
signal new_cmd : std_logic;
signal FIS_word_count, FIS_word_count_next : std_logic_vector(0 to 15); --Counter for FIS WORD Count (WRITE)
signal FIS_count_value, FIS_count_value_next : std_logic_vector(0 to 15); --Counter LIMIT for FIS WORD Count (WRITE)
signal rx_sector_count : std_logic_vector(0 to 15); --Counter for number of received sectors
signal tx_sector_count, tx_sector_count_next : std_logic_vector(0 to 15); --Counter for number of transmitted sectors
signal dword_count : std_logic_vector(0 to 7); --Counter for DWORDS in each received sector
signal DATA_FIS_dword_count : std_logic_vector(0 to 15); --Counter for DWORDS in each received DATA FIS
signal dword_count_init_value : std_logic_vector(0 to 31);
signal dword_count_value : std_logic_vector(0 to 15);
signal start_rx, start_tx, rx_done, tx_done : std_logic;
signal start_rx_next, start_tx_next, rx_done_next, tx_done_next : std_logic;
signal prim_type_rx, prim_type_tx, prim_type : std_logic_vector (0 to 3);
signal prim_type_rx_next, prim_type_tx_next : std_logic_vector (0 to 3);
signal rx_tx_state_sel, rx_tx_state_sel_next : std_logic;
signal sync_count_rx, sync_count_rx_next : std_logic_vector (0 to 7);
signal sync_count_tx, sync_count_tx_next : std_logic_vector (0 to 7);
signal ready_for_cmd_next : std_logic;
signal ready_for_cmd : std_logic;
signal frame_err, frame_err_next : std_logic;
signal tx_err, tx_err_next : std_logic;
signal tx_r_rdy, tx_r_ip, tx_r_ok, tx_r_err : std_logic_vector(0 to DATA_WIDTH-1);
signal tx_x_rdy, tx_wtrm, tx_sof, tx_eof, tx_sync : std_logic_vector(0 to DATA_WIDTH-1);
signal tx_hold, tx_hold_ack, tx_cont : std_logic_vector(0 to DATA_WIDTH-1);
signal tx_dataout : std_logic_vector(0 to DATA_WIDTH-1);
signal tx_charisk_out : std_logic;
signal tx_charisk_RX_FRAME, tx_charisk_TX_FRAME: std_logic;
signal output_mux_sel : std_logic_vector(0 to 3);
signal align_en_out : std_logic;
-- Primitive Detectors
signal SYNC_det : std_logic;
signal R_RDY_det : std_logic;
signal R_IP_det : std_logic;
signal R_OK_det : std_logic;
signal R_ERR_det : std_logic;
signal SOF_det : std_logic;
signal EOF_det : std_logic;
signal X_RDY_det : std_logic;
signal WTRM_det : std_logic;
signal CONT_det : std_logic;
signal HOLD_det : std_logic;
signal HOLD_det_r : std_logic;
signal HOLD_det_r2 : std_logic;
signal HOLD_det_r3 : std_logic;
signal HOLD_det_r4 : std_logic;
signal HOLD_start_det : std_logic;
signal HOLD_stop_det : std_logic;
signal HOLD_stop_after_ALIGN_det : std_logic;
signal CORNER_CASE_HOLD : std_logic;
signal HOLD_ACK_det : std_logic;
signal ALIGN_det : std_logic;
signal ALIGN_det_r : std_logic;
signal ALIGN_det_r2 : std_logic;
signal TWO_HOLD_det : std_logic;
signal TWO_HOLD_det_r : std_logic;
-----------------------------------------------------------------------------
-- Internal Signals
-----------------------------------------------------------------------------
signal sata_user_clk : std_logic;
signal rx_datain : std_logic_vector(0 to DATA_WIDTH-1);
signal rxelecidle : std_logic;
signal rx_charisk_in : std_logic_vector(3 downto 0);
-- Debugging OOB
signal OOB_state : std_logic_vector (0 to 7);
signal LINKUP : std_logic;
signal GEN2_led_i : std_logic;
-- Scrambler/DeScrambler
signal scrambler_din : std_logic_vector(0 to DATA_WIDTH-1);
signal scrambler_dout : std_logic_vector(0 to DATA_WIDTH-1);
signal scrambler_en, scrambler_en_r : std_logic;
signal scrambler_din_re, scrambler_din_re_r : std_logic;
signal scrambler_dout_we : std_logic;
signal scrambler_reset : std_logic;
signal scrambler_reset_after_FIS : std_logic;
signal descrambler_din : std_logic_vector(0 to DATA_WIDTH-1);
signal descrambler_dout : std_logic_vector(0 to DATA_WIDTH-1);
signal descrambler_en : std_logic;
signal descrambler_din_re, descrambler_din_re_r : std_logic;
signal descrambler_dout_we : std_logic;
signal descrambler_reset : std_logic;
signal scrambler_count : std_logic_vector(0 to 15);
signal scrambler_count_init_value : std_logic_vector(0 to 31);
signal scrambler_count_value : std_logic_vector(0 to 15);
signal scrambler_count_en_reg_fis : std_logic;
signal scrambler_count_en_data_fis : std_logic;
-- CRC
signal crc_reset : std_logic;
signal crc_din : std_logic_vector(0 to DATA_WIDTH-1);
signal crc_dout : std_logic_vector(0 to DATA_WIDTH-1);
signal crc_dout_r : std_logic_vector(0 to DATA_WIDTH-1);
signal crc_en : std_logic;
-----------------------------------------------------------------------------
-- Post-DeScramble Read FIFO to Command Layer
-----------------------------------------------------------------------------
signal read_fifo_re : std_logic;
signal read_fifo_we : std_logic;
signal read_fifo_empty_i : std_logic;
signal read_fifo_almost_empty : std_logic;
signal read_fifo_full : std_logic;
signal read_fifo_prog_full : std_logic;
signal read_fifo_din : std_logic_vector(0 to DATA_WIDTH-1);
signal read_fifo_dout : std_logic_vector(0 to DATA_WIDTH-1);
-----------------------------------------------------------------------------
-- Pre-DeScramble RX FIFO from PHY Layer
-----------------------------------------------------------------------------
signal rx_fifo_we : std_logic;
signal rx_fifo_we_next : std_logic;
signal rx_fifo_re : std_logic;
signal rx_fifo_empty : std_logic;
signal rx_fifo_almost_empty : std_logic;
signal rx_fifo_full : std_logic;
signal rx_fifo_prog_full : std_logic;
signal rx_fifo_din : std_logic_vector(0 to DATA_WIDTH-1);
signal rx_fifo_dout : std_logic_vector(0 to DATA_WIDTH-1);
signal rx_fifo_data_count : std_logic_vector(0 to 9);
signal rx_fifo_reset : std_logic;
-----------------------------------------------------------------------------
-- Pre-Scramble Write FIFO from Command Layer
-----------------------------------------------------------------------------
signal write_fifo_we : std_logic;
signal write_fifo_re : std_logic;
signal write_fifo_empty : std_logic;
signal write_fifo_almost_empty : std_logic;
signal write_fifo_full_i : std_logic;
signal write_fifo_prog_full : std_logic;
signal write_fifo_din : std_logic_vector(0 to DATA_WIDTH-1);
signal write_fifo_dout : std_logic_vector(0 to DATA_WIDTH-1);
-----------------------------------------------------------------------------
-- Post-Scramble TX FIFO to PHY Layer
-----------------------------------------------------------------------------
signal tx_fifo_re : std_logic;
signal tx_fifo_re_next : std_logic;
signal tx_fifo_we : std_logic;
signal tx_fifo_empty : std_logic;
signal tx_fifo_almost_empty : std_logic;
signal tx_fifo_full : std_logic;
signal tx_fifo_prog_full : std_logic;
signal tx_fifo_din : std_logic_vector(0 to DATA_WIDTH-1);
signal tx_fifo_dout : std_logic_vector(0 to DATA_WIDTH-1);
signal tx_fifo_data_count : std_logic_vector(0 to 9);
-----------------------------------------------------------------------------
-- Replay FIFO Signals
-----------------------------------------------------------------------------
signal replay_buffer_clear : std_logic;
signal replay_buffer_clear_next: std_logic;
-----------------------------------------------------------------------------
-- FIFO Declarations
-----------------------------------------------------------------------------
component read_write_fifo
port (
clk: IN std_logic;
rst: IN std_logic;
rd_en: IN std_logic;
din: IN std_logic_VECTOR(31 downto 0);
wr_en: IN std_logic;
dout: OUT std_logic_VECTOR(31 downto 0);
almost_empty: OUT std_logic;
empty: OUT std_logic;
full: OUT std_logic;
prog_full: OUT std_logic
);
end component;
component rx_tx_fifo
port (
clk: IN std_logic;
rst: IN std_logic;
rd_en: IN std_logic;
din: IN std_logic_VECTOR(31 downto 0);
wr_en: IN std_logic;
dout: OUT std_logic_VECTOR(31 downto 0);
almost_empty: OUT std_logic;
empty: OUT std_logic;
full: OUT std_logic;
prog_full: OUT std_logic;
data_count: OUT std_logic_vector(9 downto 0)
);
end component;
-----------------------------------------------------------------------------
-- SATA PHY Declaration
-----------------------------------------------------------------------------
component sata_phy
port (
oob_control_ila_control: in std_logic_vector(35 downto 0);
sata_phy_ila_control : in std_logic_vector(35 downto 0);
REFCLK_PAD_P_IN : in std_logic; -- MGTCLKA, clocks GTP_X0Y0-2
REFCLK_PAD_N_IN : in std_logic; -- MGTCLKA
GTXRESET_IN : in std_logic; -- GTP initialization
PLLLKDET_OUT_N : out std_logic;
TXP0_OUT : out std_logic;
TXN0_OUT : out std_logic;
RXP0_IN : in std_logic;
RXN0_IN : in std_logic;
DCMLOCKED_OUT : out std_logic;
LINKUP : out std_logic;
LINKUP_led : out std_logic;
sata_user_clk : out std_logic;
GEN2_led : out std_logic;
align_en_out : out std_logic;
tx_datain : in std_logic_vector(DATA_WIDTH-1 downto 0);
tx_charisk_in : in std_logic;
rx_dataout : out std_logic_vector(DATA_WIDTH-1 downto 0);
rx_charisk_out : out std_logic_vector(3 downto 0);
CurrentState_out : out std_logic_vector(7 downto 0);
rxelecidle_out : out std_logic;
CLKIN_150 : in std_logic
);
end component;
component sata_rx_frame_ila
port (
control : in std_logic_vector(35 downto 0);
clk : in std_logic;
trig0 : in std_logic_vector(3 downto 0);
trig1 : in std_logic_vector(31 downto 0);
trig2 : in std_logic_vector(7 downto 0);
trig3 : in std_logic_vector(3 downto 0);
trig4 : in std_logic_vector(3 downto 0);
trig5 : in std_logic_vector(7 downto 0);
trig6 : in std_logic_vector(31 downto 0);
trig7 : in std_logic_vector(31 downto 0);
trig8 : in std_logic_vector(31 downto 0);
trig9 : in std_logic_vector(31 downto 0);
trig10 : in std_logic_vector(31 downto 0);
trig11 : in std_logic_vector(7 downto 0);
trig12 : in std_logic_vector(15 downto 0);
trig13 : in std_logic_vector(15 downto 0);
trig14 : in std_logic_vector(15 downto 0);
trig15 : in std_logic_vector(31 downto 0)
);
end component;
component sata_tx_frame_ila
port (
control : in std_logic_vector(35 downto 0);
clk : in std_logic;
trig0 : in std_logic_vector(3 downto 0);
trig1 : in std_logic_vector(31 downto 0);
trig2 : in std_logic_vector(31 downto 0);
trig3 : in std_logic_vector(31 downto 0);
trig4 : in std_logic_vector(3 downto 0);
trig5 : in std_logic_vector(31 downto 0);
trig6 : in std_logic_vector(31 downto 0);
trig7 : in std_logic_vector(31 downto 0);
trig8 : in std_logic_vector(15 downto 0);
trig9 : in std_logic_vector(15 downto 0);
trig10 : in std_logic_vector(31 downto 0);
trig11 : in std_logic_vector(31 downto 0);
trig12 : in std_logic_vector(31 downto 0);
trig13 : in std_logic_vector(15 downto 0);
trig14 : in std_logic_vector(15 downto 0);
trig15 : in std_logic_vector(9 downto 0)
);
end component;
-------------------------------------------------------------------------------
-- BEGIN
-------------------------------------------------------------------------------
begin
-------------------------------------------------------------------------------
-- LINK LAYER
-------------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- PROCESS: MASTER_FSM_VALUE_PROC
-- PURPOSE: ChipScope State Indicator Signal
-----------------------------------------------------------------------------
MASTER_FSM_VALUE_PROC : process (master_fsm_curr) is
begin
case (master_fsm_curr) is
when idle => master_fsm_value <= x"0";
when capture_dev_sign => master_fsm_value <= x"1";
when wait_for_cmd => master_fsm_value <= x"2";
when H2D_REG_FIS => master_fsm_value <= x"3";
when D2H_DMA_ACT_FIS => master_fsm_value <= x"4";
when H2D_DATA_FIS => master_fsm_value <= x"5";
when D2H_DATA_FIS => master_fsm_value <= x"6";
when D2H_REG_FIS => master_fsm_value <= x"7";
when D2H_PIO_SETUP => master_fsm_value <= x"8";
when dead => master_fsm_value <= x"9";
when others => master_fsm_value <= x"A";
end case;
end process MASTER_FSM_VALUE_PROC;
-----------------------------------------------------------------------------
-- PROCESS: MASTER_FSM_STATE_PROC
-- PURPOSE: Registering Signals and Next State
-----------------------------------------------------------------------------
MASTER_FSM_STATE_PROC : process (sata_user_clk)
begin
if ((sata_user_clk'event) and (sata_user_clk = '1')) then
if (sw_reset = '1') then
--Initializing internal signals
master_fsm_curr <= idle;
FIS_count_value <= (others => '0');
start_rx <= '0';
start_tx <= '0';
new_cmd <= '0';
ready_for_cmd <= '0';
else
-- Register all Current Signals to their _next Signals
master_fsm_curr <= master_fsm_next;
FIS_count_value <= FIS_count_value_next;
start_rx <= start_rx_next;
start_tx <= start_tx_next;
ready_for_cmd <= ready_for_cmd_next;
if (new_cmd_in = '1') then
new_cmd <= '1';
else
new_cmd <= '0';
end if;
end if;
end if;
end process MASTER_FSM_STATE_PROC;
-----------------------------------------------------------------------------
-- PROCESS: MASTER_FSM_LOGIC_PROC
-- PURPOSE: Implements a Sequence of FIS transfers for sending READ/WRITE sector
-- command. (Transport Layer)
-----------------------------------------------------------------------------
MASTER_FSM_LOGIC_PROC : process (master_fsm_curr, rx_done, tx_done, tx_err,
LINKUP, new_cmd, tx_sector_count
) is
begin
-- Register _next to current signals
master_fsm_next <= master_fsm_curr;
FIS_count_value_next <= (others => '0');
start_rx_next <= start_rx;
start_tx_next <= start_tx;
---------------------------------------------------------------------------
-- Finite State Machine
---------------------------------------------------------------------------
case (master_fsm_curr) is
-- x0
when idle =>
if (LINKUP = '1') then
start_rx_next <= '1';
master_fsm_next <= capture_dev_sign;
end if;
-- x1
when capture_dev_sign =>
start_rx_next <= '0';
if (rx_done = '1') then
master_fsm_next <= wait_for_cmd;
end if;
-- x2
when wait_for_cmd =>
if (new_cmd = '1') then
start_tx_next <= '1';
master_fsm_next <= H2D_REG_FIS;
end if;
-- x3
when H2D_REG_FIS =>
FIS_count_value_next <= COMMAND_FIS;
start_tx_next <= '0';
if (tx_done = '1') then
start_rx_next <= '1';
case (cmd_type) is
when IDEN_DEV =>
master_fsm_next <= D2H_PIO_SETUP;
when READ_DMA =>
master_fsm_next <= D2H_DATA_FIS;
when WRITE_DMA =>
master_fsm_next <= D2H_DMA_ACT_FIS;
when others =>
master_fsm_next <= D2H_REG_FIS;
end case;
end if;
if(tx_err = '1') then
start_tx_next <= '1';
master_fsm_next <= H2D_REG_FIS;
end if;
-- x4
when D2H_DMA_ACT_FIS =>
start_rx_next <= '0';
if (rx_done = '1') then
start_tx_next <= '1';
master_fsm_next <= H2D_DATA_FIS;
end if;
-- x5
when H2D_DATA_FIS =>
--FIS_count_value_next <= conv_std_logic_vector(((SECTOR_NDWORDS * sector_count) + 1), 16);
FIS_count_value_next <= (NDWORDS_PER_DATA_FIS + 1);
start_tx_next <= '0';
if ((tx_done = '1') or (tx_err = '1')) then
start_rx_next <= '1';
if (tx_sector_count >= conv_std_logic_vector(sector_count, 16)) then
master_fsm_next <= D2H_REG_FIS;
else
master_fsm_next <= D2H_DMA_ACT_FIS;
end if;
end if;
-- x6
when D2H_DATA_FIS =>
start_rx_next <= '0';
if (rx_done = '1') then
if (cmd_type = READ_DMA) then
start_rx_next <= '1';
master_fsm_next <= D2H_REG_FIS;
else
master_fsm_next <= wait_for_cmd;
end if;
end if;
-- x7
when D2H_REG_FIS =>
start_rx_next <= '0';
if (rx_done = '1') then
master_fsm_next <= wait_for_cmd;
end if;
-- x8
when D2H_PIO_SETUP =>
start_rx_next <= '0';
if (rx_done = '1') then
start_rx_next <= '1';
master_fsm_next <= D2H_DATA_FIS;
end if;
-- x9
when dead =>
master_fsm_next <= dead;
-- xA
when others =>
master_fsm_next <= dead;
end case;
end process MASTER_FSM_LOGIC_PROC;
ready_for_cmd_next <= '1' when (master_fsm_curr = wait_for_cmd) else '0';
ready_for_cmd_out <= ready_for_cmd;
-----------------------------------------------------------------------------
-- PROCESS: RX_FRAME_VALUE_PROC
-- PURPOSE: ChipScope State Indicator Signal
-----------------------------------------------------------------------------
RX_FRAME_VALUE_PROC : process (rx_frame_curr) is
begin
case (rx_frame_curr) is
when idle => rx_frame_value <= x"0";
when send_R_RDY => rx_frame_value <= x"1";
when send_R_IP => rx_frame_value <= x"2";
when send_HOLD_ACK => rx_frame_value <= x"3";
when send_R_OK => rx_frame_value <= x"4";
when send_SYNC => rx_frame_value <= x"5";
when wait_for_X_RDY => rx_frame_value <= x"6";
when dead => rx_frame_value <= x"7";
when others => rx_frame_value <= x"8";
end case;
end process RX_FRAME_VALUE_PROC;
-----------------------------------------------------------------------------
-- PROCESS: RX_FRAME_STATE_PROC
-- PURPOSE: Registering Signals and Next State
-----------------------------------------------------------------------------
RX_FRAME_STATE_PROC : process (sata_user_clk)
begin
if ((sata_user_clk'event) and (sata_user_clk = '1')) then
if (sw_reset = '1') then
--Initializing internal signals
rx_frame_curr <= idle;
sync_count_rx <= (others => '0');
rx_done <= '0';
rx_fifo_we <= '0';
prim_type_rx <= (others => '0');
ALIGN_det_r <= '0';
ALIGN_det_r2 <= '0';
HOLD_det_r <= '0';
HOLD_det_r2 <= '0';
HOLD_det_r3 <= '0';
HOLD_det_r4 <= '0';
TWO_HOLD_det_r <= '0';
else
-- Register all Current Signals to their _next Signals
rx_frame_curr <= rx_frame_next;
sync_count_rx <= sync_count_rx_next;
rx_done <= rx_done_next;
rx_fifo_we <= rx_fifo_we_next;
prim_type_rx <= prim_type_rx_next;
ALIGN_det_r <= ALIGN_det;
ALIGN_det_r2 <= ALIGN_det_r;
HOLD_det_r <= HOLD_det;
HOLD_det_r2 <= HOLD_det_r;
HOLD_det_r3 <= HOLD_det_r2;
HOLD_det_r4 <= HOLD_det_r3;
TWO_HOLD_det_r <= TWO_HOLD_det;
end if;
end if;
end process RX_FRAME_STATE_PROC;
-----------------------------------------------------------------------------
-- PROCESS: RX_FRAME_LOGIC_PROC
-- PURPOSE: Receive FRAME from disk and unpack the FIS
-----------------------------------------------------------------------------
RX_FRAME_LOGIC_PROC : process (rx_frame_curr, sync_count_rx, ALIGN_det, HOLD_det,
HOLD_stop_after_ALIGN_det,
SOF_det, EOF_det, HOLD_start_det, HOLD_stop_det, SYNC_det,
start_rx, LINKUP, rx_datain, rx_sector_count, sector_count
) is
begin
-- Register _next to current signals
rx_frame_next <= rx_frame_curr;
sync_count_rx_next <= sync_count_rx;
rx_done_next <= rx_done;
prim_type_rx_next <= prim_type_rx;
rx_fifo_we_next <= '0';
---------------------------------------------------------------------------
-- Finite State Machine
---------------------------------------------------------------------------
case (rx_frame_curr) is
-- x0
when idle =>
rx_done_next <= '0';
prim_type_rx_next <= SYNC;
if (start_rx = '1') then
--if (master_fsm_curr = capture_dev_sign) then
rx_frame_next <= send_R_RDY;
--else
-- rx_frame_next <= wait_for_X_RDY;
--end if;
end if;
-- x6
--Wait for X_RDY before sending R_RDY
when wait_for_X_RDY =>
prim_type_rx_next <= SYNC;
if (X_RDY_det = '1') then
rx_frame_next <= send_R_RDY;
end if;
-- x1
when send_R_RDY =>
--Send R_RDY to get device signature
prim_type_rx_next <= R_RDY;
if (SOF_det = '1') then
rx_frame_next <= send_R_IP;
end if;
-- x2
when send_R_IP =>
--Send R_IP to indicate Reception in Progress
prim_type_rx_next <= R_IP;
rx_fifo_we_next <= '1';
if (ALIGN_det = '1' or HOLD_det = '1') then
rx_fifo_we_next <= '0';
end if;
if (EOF_det = '1') then
rx_fifo_we_next <= '0';
rx_frame_next <= send_R_OK;
end if;
-- Check for 2 HOLD primitives followed by CONT which indicates FIS pause
if (HOLD_start_det = '1') then
rx_fifo_we_next <= '0';
rx_frame_next <= send_HOLD_ACK;
end if;
-- x3
when send_HOLD_ACK =>
-- Send HOLD ACK to Acknowledge FIS pause
prim_type_rx_next <= HOLD_ACK;
if (HOLD_stop_after_ALIGN_det = '1') then
rx_fifo_we_next <= '1';
rx_frame_next <= send_R_IP;
end if;
if (HOLD_stop_det = '1') then
rx_frame_next <= send_R_IP;
end if;
-- x4
when send_R_OK =>
-- Send R_OK to indicate good frame
prim_type_rx_next <= R_OK;
if (SYNC_det = '1') then
if (master_fsm_curr = D2H_DATA_FIS) then
if (rx_sector_count < conv_std_logic_vector(sector_count,16)) then
rx_frame_next <= send_R_RDY;
else
rx_done_next <= '1';
rx_frame_next <= idle;
end if;
else
rx_frame_next <= send_SYNC;
end if;
end if;
-- x5
when send_SYNC =>
-- Send SYNC to indicate host idle
prim_type_rx_next <= SYNC;
if (sync_count_rx = SYNC_COUNT_VALUE) then
rx_done_next <= '1';
sync_count_rx_next <= (others => '0');
rx_frame_next <= idle;
else
sync_count_rx_next <= sync_count_rx + 1;
end if;
-- x6
when dead =>
rx_frame_next <= dead;
-- x7
when others =>
rx_frame_next <= dead;
end case;
end process RX_FRAME_LOGIC_PROC;
-- Counter for number of received sectors (used when number of RX sectors exceeds max 16 in one data FIS)
RX_SECTOR_CNT: process(sata_user_clk) is
begin
if ((sata_user_clk'event) and (sata_user_clk = '1')) then
if (sw_reset = '1' or new_cmd = '1') then
dword_count <= (others => '0');
rx_sector_count <= (others => '0');
elsif ((dword_count < (SECTOR_NDWORDS-1)) and (master_fsm_curr = D2H_DATA_FIS) and (rx_fifo_we_next = '1')) then
dword_count <= dword_count + 1;
elsif (dword_count = (SECTOR_NDWORDS-1)) then
dword_count <= (others => '0');
rx_sector_count <= rx_sector_count + 1;
elsif (EOF_det = '1') then
dword_count <= (others => '0');
else
dword_count <= dword_count;
rx_sector_count <= rx_sector_count;
end if;
end if;
end process RX_SECTOR_CNT;
-- DATA FIS DWORD Counter for stripping off DATA FIS header and CRC
DATA_FIS_DWORD_CNT: process(sata_user_clk) is
begin
if ((sata_user_clk'event) and (sata_user_clk = '1')) then
if (sw_reset = '1') then
DATA_FIS_dword_count <= (others => '0');
dword_count_init_value <= (others => '0');
elsif ((master_fsm_curr = D2H_DATA_FIS) and (DATA_FIS_dword_count < dword_count_value)) then
if (descrambler_dout_we = '1') then
DATA_FIS_dword_count <= DATA_FIS_dword_count + 1;
else
DATA_FIS_dword_count <= DATA_FIS_dword_count;
end if;
elsif ((DATA_FIS_dword_count = dword_count_value) and (master_fsm_curr = D2H_DATA_FIS)) then
if(dword_count_init_value >= NDWORDS_PER_DATA_FIS_32) then
dword_count_init_value <= (dword_count_init_value - NDWORDS_PER_DATA_FIS_32);
end if;
DATA_FIS_dword_count <= (others => '0');
else
DATA_FIS_dword_count <= (others => '0');
end if;
if(new_cmd = '1') then
dword_count_init_value <= conv_std_logic_vector((SECTOR_NDWORDS * sector_count), 32);
dword_count_value <= (others => '0');
elsif(dword_count_init_value < NDWORDS_PER_DATA_FIS_32) then
dword_count_value <= dword_count_init_value(16 to 31) + conv_std_logic_vector(1,16);
elsif(dword_count_init_value >= NDWORDS_PER_DATA_FIS_32) then
dword_count_value <= NDWORDS_PER_DATA_FIS + 1;
end if;
end if;
end process DATA_FIS_DWORD_CNT;
-----------------------------------------------------------------------------
-- PROCESS: TX_FRAME_VALUE_PROC
-- PURPOSE: ChipScope State Indicator Signal
-----------------------------------------------------------------------------
TX_FRAME_VALUE_PROC : process (tx_frame_curr) is
begin
case (tx_frame_curr) is
when idle => tx_frame_value <= x"0";
when send_X_RDY => tx_frame_value <= x"1";
when send_SOF => tx_frame_value <= x"2";
when send_FIS => tx_frame_value <= x"3";
when send_EOF => tx_frame_value <= x"4";
when send_WTRM => tx_frame_value <= x"5";
when send_SYNC => tx_frame_value <= x"6";
when send_HOLD_ACK => tx_frame_value <= x"7";
when send_HOLD => tx_frame_value <= x"8";
when dead => tx_frame_value <= x"9";
when others => tx_frame_value <= x"A";
end case;
end process TX_FRAME_VALUE_PROC;
-----------------------------------------------------------------------------
-- PROCESS: TX_FRAME_STATE_PROC
-- PURPOSE: Registering Signals and Next State
-----------------------------------------------------------------------------
TX_FRAME_STATE_PROC : process (sata_user_clk)
begin
if ((sata_user_clk'event) and (sata_user_clk = '1')) then
if (sw_reset = '1') then
--Initializing internal signals
tx_frame_curr <= idle;
sync_count_tx <= (others => '0');
rx_tx_state_sel <= '0';
tx_done <= '0';
tx_fifo_re <= '0';
frame_err <= '0';
tx_err <= '0';
replay_buffer_clear <= '0';
prim_type_tx <= (others => '0');
FIS_word_count <= (others => '0');
tx_sector_count <= (others => '0');
elsif(new_cmd = '1') then
tx_sector_count <= (others => '0');
else
-- Register all Current Signals to their _next Signals
tx_frame_curr <= tx_frame_next;
sync_count_tx <= sync_count_tx_next;
rx_tx_state_sel <= rx_tx_state_sel_next;
tx_done <= tx_done_next;
tx_fifo_re <= tx_fifo_re_next;
frame_err <= frame_err_next;
tx_err <= tx_err_next;
replay_buffer_clear <= replay_buffer_clear_next;
prim_type_tx <= prim_type_tx_next;
FIS_word_count <= FIS_word_count_next;
tx_sector_count <= tx_sector_count_next;
end if;
end if;
end process TX_FRAME_STATE_PROC;
-----------------------------------------------------------------------------
-- PROCESS: TX_FRAME_LOGIC_PROC
-- PURPOSE: Next State and Output Logic
-----------------------------------------------------------------------------
TX_FRAME_LOGIC_PROC : process (tx_frame_curr, FIS_word_count, sector_count,
tx_sector_count,
R_RDY_det, R_OK_det, sync_count_tx, start_tx,
LINKUP, frame_err
) is
begin
-- Register _next to current signals
tx_frame_next <= tx_frame_curr;
sync_count_tx_next <= sync_count_tx;
rx_tx_state_sel_next <= rx_tx_state_sel;
tx_fifo_re_next <= tx_fifo_re;
tx_done_next <= tx_done;
frame_err_next <= frame_err;
tx_err_next <= tx_err;
replay_buffer_clear_next <= replay_buffer_clear;
prim_type_tx_next <= prim_type_tx;
FIS_word_count_next <= FIS_word_count;
tx_sector_count_next <= tx_sector_count;
tx_charisk_TX_FRAME <= '1';
---------------------------------------------------------------------------
-- Finite State Machine
---------------------------------------------------------------------------
case (tx_frame_curr) is
-- x0
when idle =>
tx_done_next <= '0';
tx_err_next <= '0';
replay_buffer_clear_next <= '0';
prim_type_tx_next <= SYNC;
FIS_word_count_next <= (others => '0');
if (start_tx = '1') then
rx_tx_state_sel_next <= '1';
tx_frame_next <= send_X_RDY;
end if;
-- x1
when send_X_RDY =>
-- Send X_RDY to indicate host ready to transmit
prim_type_tx_next <= X_RDY;
if (R_RDY_det = '1') then
tx_frame_next <= send_SOF;
end if;
-- x2
when send_SOF =>
--Send SOF to indicate start of new FRAME
prim_type_tx_next <= SOF;
if (align_en_out = '0') then
tx_frame_next <= send_FIS;
end if;
-- x3
when send_FIS =>
tx_charisk_TX_FRAME <= '0';
--Send FIS data
prim_type_tx_next <= FIS;
-- ALIGN primitives after 256 DWORDS
if (align_en_out = '1' or tx_fifo_almost_empty = '1') then
FIS_word_count_next <= FIS_word_count;
tx_fifo_re_next <= '0';
else
FIS_word_count_next <= FIS_word_count + '1';
tx_fifo_re_next <= '1';
end if;
-- Receive buffer empty condition
if (HOLD_start_det = '1') then
tx_frame_next <= send_HOLD_ACK;
end if;
-- Transmit buffer empty condition
if (tx_fifo_almost_empty = '1') then
if (align_en_out = '0') then
tx_charisk_TX_FRAME <= '1';
prim_type_tx_next <= HOLD;
tx_frame_next <= send_HOLD;
end if;
end if;
-- Transmitted sector count
if(((conv_integer(FIS_word_count) mod SECTOR_NDWORDS)=0) and (conv_integer(FIS_word_count)>0) and (align_en_out='0') and (tx_fifo_almost_empty='0')) then
tx_sector_count_next <= tx_sector_count + 1;
else
tx_sector_count_next <= tx_sector_count;
end if;
if ((tx_sector_count >= conv_std_logic_vector(sector_count, 16)) or (FIS_word_count >= FIS_count_value)) then
if (align_en_out = '0') then
tx_charisk_TX_FRAME <= '0';
FIS_word_count_next <= (others => '0');
tx_fifo_re_next <= '1';
prim_type_tx_next <= FIS;
tx_frame_next <= send_EOF;
end if;
end if;
-- x7
when send_HOLD_ACK =>
-- Send HOLD ACK to Acknowledge FIS pause
prim_type_tx_next <= HOLD_ACK;
tx_fifo_re_next <= '0';
--if (HOLD_stop_det = '1') then
if (R_IP_det = '1') then
tx_frame_next <= send_FIS;
end if;
-- x8
when send_HOLD =>
-- Send HOLD to indicate transmit buffer empty
prim_type_tx_next <= HOLD;
tx_fifo_re_next <= '0';
if (tx_fifo_empty = '0') then
tx_frame_next <= send_FIS;
end if;
-- x4
when send_EOF =>
--Send EOF to indicate end of FRAME
tx_fifo_re_next <= '0';
prim_type_tx_next <= EOF;
if (align_en_out = '0') then
tx_frame_next <= send_WTRM;
end if;
-- x5
when send_WTRM =>
-- Send WTRM to indicate Waiting for Frame Termination
prim_type_tx_next <= WTRM;
if (R_OK_det = '1' or R_ERR_det = '1' or SYNC_det = '1') then
if (R_ERR_det = '1' or SYNC_det = '1') then
if (master_fsm_curr = H2D_REG_FIS) then
frame_err_next <= '1';
else
frame_err_next <= '0';
end if;
end if;
if (R_OK_det = '1') then
replay_buffer_clear_next <= '1';
frame_err_next <= '0';
end if;
tx_frame_next <= send_SYNC;
end if;
-- x6
when send_SYNC =>
-- Send SYNC to indicate host idle
prim_type_tx_next <= SYNC;
if (sync_count_tx = SYNC_COUNT_VALUE) then
sync_count_tx_next <= (others => '0');
if (frame_err = '1') then
tx_err_next <= '1';
else
tx_done_next <= '1';
end if;
rx_tx_state_sel_next <= '0';
tx_frame_next <= idle;
else
sync_count_tx_next <= sync_count_tx + 1;
end if;
-- x8
when dead =>
tx_frame_next <= dead;
-- x9
when others =>
tx_frame_next <= dead;
end case;
end process TX_FRAME_LOGIC_PROC;
-- ASYNCHRONOUS MUXES
tx_charisk_RX_FRAME <= '1';
--tx_charisk_TX_FRAME <= '0' when (((tx_frame_curr = send_FIS) and (tx_fifo_almost_empty = '0')) or ((tx_frame_curr=send_FIS) and
-- (tx_fifo_almost_empty = '1') and (master_fsm_curr = H2D_REG_FIS))) else '1';
--tx_charisk_out <= '0' when ((tx_frame_curr = send_FIS) or (prim_type_tx = PRIM_SCRM)) else tx_charisk_RX_FRAME when (rx_tx_state_sel = '0') else tx_charisk_TX_FRAME;
tx_charisk_out <= tx_charisk_RX_FRAME when (rx_tx_state_sel = '0') else tx_charisk_TX_FRAME;
prim_type <= prim_type_rx when (rx_tx_state_sel = '0') else prim_type_tx;
-- ASYNCHRONOUS MUXES
-- Primitive detection
ALIGN_det <= '1' when (rx_datain = x"7B4A4ABC") else '0';
SYNC_det <= '1' when (rx_datain = x"B5B5957C") else '0';
R_RDY_det <= '1' when (rx_datain = x"4A4A957C") else '0';
R_IP_det <= '1' when (rx_datain = x"5555B57C") else '0';
R_OK_det <= '1' when (rx_datain = x"3535B57C") else '0';
R_ERR_det <= '1' when (rx_datain = x"5656B57C") else '0';
SOF_det <= '1' when (rx_datain = x"3737B57C") else '0';
EOF_det <= '1' when (rx_datain = x"D5D5B57C") else '0';
X_RDY_det <= '1' when (rx_datain = x"5757B57C") else '0';
WTRM_det <= '1' when (rx_datain = x"5858B57C") else '0';
CONT_det <= '1' when (rx_datain = x"9999AA7C") else '0';
HOLD_det <= '1' when (rx_datain = x"D5D5AA7C") else '0';
HOLD_start_det <= '1' when (((TWO_HOLD_det_r = '1') and (CONT_det = '1')) or (CORNER_CASE_HOLD = '1')) else '0';
TWO_HOLD_det <= '1' when ((rx_datain = x"D5D5AA7C") and (HOLD_det_r = '1')) else '0';
HOLD_stop_det <= '1' when ((rx_datain = x"D5D5AA7C") and (ALIGN_det_r = '0') and (TWO_HOLD_det = '0')) else '0';
HOLD_stop_after_ALIGN_det <= '1' when ((HOLD_det_r = '1') and (ALIGN_det_r2 = '1') and (ALIGN_det_r = '0') and (TWO_HOLD_det = '0')) or ((TWO_HOLD_det_r = '1') and (CONT_det = '0')) else '0';
-- Corner Case
-- ALIGN primitives are received between two HOLD primitives or between 2 HOLD and a CONT primitive
CORNER_CASE_HOLD <= '1' when ((CONT_det = '1') and (HOLD_det_r4 = '1')) else '0';
-- SATA Primitives
-- SYNC
tx_sync <= x"B5B5957C";
-- R_RDY
tx_r_rdy <= x"4A4A957C";
-- R_OK
tx_r_ok <= x"3535B57C";
-- R_ERR
tx_r_err <= x"5656B57C";
-- R_IP
tx_r_ip <= x"5555B57C";
-- X_RDY
tx_x_rdy <= x"5757B57C";
-- CONT
tx_cont <= x"9999AA7C";
-- WTRM
tx_wtrm <= x"5858B57C";
-- SOF
tx_sof <= x"3737B57C";
-- EOF
tx_eof <= x"D5D5B57C";
-- HOLD
tx_hold <= x"D5D5AA7C";
-- HOLD_ACK
tx_hold_ack <= x"9595AA7C";
-- Output Mux
OUTPUT_MUX_i: entity work.mux_161
generic map
(
DATA_WIDTH => 32
)
port map
(
a => tx_sync,
b => tx_r_rdy,
c => tx_r_ip,
d => tx_r_ok,
e => tx_r_err,
f => tx_x_rdy,
g => tx_wtrm,
h => tx_hold,
i => tx_hold_ack,
j => tx_cont,
k => tx_sof,
l => tx_eof,
m => tx_fifo_dout,
--n => tx_prim_scrm,
n => (others => '0'),
o => (others => '0'),
p => (others => '0'),
sel=> output_mux_sel,
output=> tx_dataout
);
output_mux_sel <= prim_type;
-------------------------------------------------------------------------------
-- LINK LAYER
-------------------------------------------------------------------------------
---------------------------------------------------------------------------
-- Pre-DeScramble RX FIFO from PHY Layer
---------------------------------------------------------------------------
rx_fifo_din <= rx_datain;
rx_fifo_re <= descrambler_din_re_r;
rx_fifo_reset <= sw_reset or descrambler_reset;
RX_FIFO : rx_tx_fifo
port map (
clk => sata_user_clk,
rst => rx_fifo_reset,
rd_en => rx_fifo_re,
din => rx_fifo_din,
wr_en => rx_fifo_we_next,
dout => rx_fifo_dout,
almost_empty => rx_fifo_almost_empty,
empty => rx_fifo_empty,
full => rx_fifo_full,
prog_full => rx_fifo_prog_full,
data_count => rx_fifo_data_count
);
---------------------------------------------------------------------------
-- DESCRAMBLER
---------------------------------------------------------------------------
--descrambler_din(0 to 15) <= rx_fifo_dout(16 to 31);
--descrambler_din(16 to 31) <= rx_fifo_dout(0 to 15);
descrambler_din <= rx_fifo_dout;
descrambler_en <= not(rx_fifo_almost_empty);
descrambler_reset <= '1' when ((start_rx='1') or ((rx_frame_curr = send_R_OK) and (SYNC_det = '1'))) else '0';
DESCRAMBLER_i: entity work.scrambler
generic map(
CHIPSCOPE => FALSE
)
port map(
-- Clock and Reset Signals
clk => sata_user_clk,
reset => descrambler_reset,
-- ChipScope ILA / Trigger Signals
scrambler_ila_control => descrambler_ila_control,
---------------------------------------
-- Signals from/to Sata Link Layer FIFOs
prim_scrambler => '0',
scrambler_en => descrambler_en,
din_re => descrambler_din_re,
data_in => descrambler_din,
data_out => descrambler_dout,
dout_we => descrambler_dout_we
);
---------------------------------------------------------------------------
-- Post-DeScramble Read FIFO to Command Layer
---------------------------------------------------------------------------
read_fifo_din <= descrambler_dout;
read_fifo_we <= descrambler_dout_we when ((master_fsm_curr = D2H_DATA_FIS) and (DATA_FIS_dword_count > 0) and (DATA_FIS_dword_count < dword_count_value)) else '0';
READ_FIFO_i : read_write_fifo
port map (
clk => sata_user_clk,
rst => sw_reset,
rd_en => read_fifo_re,
din => read_fifo_din,
wr_en => read_fifo_we,
dout => read_fifo_dout,
almost_empty => read_fifo_almost_empty,
empty => read_fifo_empty_i,
full => read_fifo_full,
prog_full => read_fifo_prog_full
);
-- Data Output to Command Layer
sata_dout <= read_fifo_dout;
-- Input from Command Layer
read_fifo_re <= sata_dout_re;
read_fifo_empty <= read_fifo_empty_i;
---------------------------------------------------------------------------
-- Pre-Scramble Write FIFO from Command Layer
---------------------------------------------------------------------------
write_fifo_we <= sata_din_we;
write_fifo_din <= sata_din;
write_fifo_full <= write_fifo_prog_full;
--write_fifo_re <= scrambler_din_re_r when (scrambler_en = '1') else '0';
write_fifo_re <= scrambler_din_re_r when ((scrambler_en='1') and (scrambler_count_en_reg_fis='1')) or ((scrambler_count < scrambler_count_value) and (scrambler_count_en_data_fis = '1') and (write_fifo_empty = '0')) else '0';
WRITE_FIFO_i : read_write_fifo
port map (
clk => sata_user_clk,
rst => sw_reset,
din => write_fifo_din,
wr_en => write_fifo_we,
dout => write_fifo_dout,
rd_en => write_fifo_re,
almost_empty => write_fifo_almost_empty,
empty => write_fifo_empty,
full => write_fifo_full_i,
prog_full => write_fifo_prog_full
);
---------------------------------------------------------------------------
-- CRC
---------------------------------------------------------------------------
crc_reset <= scrambler_reset;
crc_en <= scrambler_dout_we;
crc_din <= write_fifo_dout;
CRC_i : entity work.crc
generic map (
CHIPSCOPE => FALSE
)
port map (
clk => sata_user_clk,
reset => crc_reset,
--crc_ila_control => crc_ila_control,
crc_en => crc_en,
data_in => crc_din,
data_out => crc_dout
);
---------------------------------------------------------------------------
-- SCRAMBLER
---------------------------------------------------------------------------
REGISTER_PROCESS : process(sata_user_clk) is
begin
if sata_user_clk'event and sata_user_clk = '1' then
if sw_reset = '1' then
scrambler_din_re_r <= '0';
descrambler_din_re_r <= '0';
crc_dout_r <= (others => '0');
else
scrambler_din_re_r <= scrambler_din_re;
descrambler_din_re_r <= descrambler_din_re;
crc_dout_r <= crc_dout;
end if;
end if;
end process REGISTER_PROCESS;
scrambler_count_en_reg_fis <= '1' when (master_fsm_curr = H2D_REG_FIS) else '0';
scrambler_count_en_data_fis <= '1' when ((master_fsm_curr = H2D_DATA_FIS) or ((master_fsm_curr = D2H_DMA_ACT_FIS) and (tx_sector_count > 0))) else '0';
-- To disable scrambler after the REG FIS
SCRAMBLER_CNT: process(sata_user_clk) is
begin
if ((sata_user_clk'event) and (sata_user_clk = '1')) then
if (sw_reset = '1') then
scrambler_count <= (others => '0');
scrambler_count_init_value <= (others => '0');
scrambler_count_value <= (others => '0');
scrambler_reset_after_FIS <= '0';
elsif ((scrambler_count < (REG_FIS_NDWORDS)) and (scrambler_count_en_reg_fis = '1')) then
scrambler_count <= scrambler_count + 1;
elsif ((scrambler_count < scrambler_count_value) and (scrambler_count_en_data_fis = '1') and (tx_fifo_we = '1') and (write_fifo_empty = '0')) then
scrambler_count <= scrambler_count + 1;
if (scrambler_count = NDWORDS_PER_DATA_FIS) then
scrambler_reset_after_FIS <= '1';
end if;
elsif (( scrambler_count = (NDWORDS_PER_DATA_FIS+1)) and (scrambler_count_en_data_fis = '1')) then
scrambler_count_init_value <= (scrambler_count_init_value - NDWORDS_PER_DATA_FIS_32);
scrambler_count <= (others => '0');
scrambler_reset_after_FIS <= '0';
else
scrambler_count <= scrambler_count;
end if;
if (scrambler_reset = '1') then
scrambler_count <= (others => '0');
scrambler_reset_after_FIS <= '0';
end if;
if(new_cmd = '1') then
scrambler_count_init_value <= conv_std_logic_vector((SECTOR_NDWORDS * sector_count), 32);
scrambler_count_value <= (others => '0');
elsif(scrambler_count_init_value < NDWORDS_PER_DATA_FIS_32) then
scrambler_count_value <= scrambler_count_init_value(16 to 31) + conv_std_logic_vector(1,16);
elsif(scrambler_count_init_value >= NDWORDS_PER_DATA_FIS_32) then
scrambler_count_value <= NDWORDS_PER_DATA_FIS + 1;
end if;
end if;
end process SCRAMBLER_CNT;
scrambler_reset <= (sw_reset or new_cmd or scrambler_reset_after_FIS or (tx_done and scrambler_count_en_reg_fis)) ;
scrambler_din <= crc_dout_r when ((scrambler_count = REG_FIS_NDWORDS) and (scrambler_count_en_reg_fis = '1')) or ((scrambler_count = scrambler_count_value) and (scrambler_count_en_data_fis = '1')) else write_fifo_dout;
scrambler_en <= not(write_fifo_empty) when (((scrambler_count_en_reg_fis = '1') and (scrambler_count < REG_FIS_NDWORDS))
--or ((scrambler_count_en_data_fis = '1') and (scrambler_count = NDWORDS_PER_DATA_FIS) and (tx_fifo_prog_full = '1'))
or ((scrambler_count_en_data_fis = '1') and (scrambler_count = (scrambler_count_value - '1'))))
else not(write_fifo_almost_empty) when ((scrambler_count_en_data_fis = '1') and (scrambler_count < scrambler_count_value) and (tx_fifo_prog_full = '0'))
else '0';
-- Corner Case: tx_fifo_almost_full goes high when (scrambler_count = NDWORDS_PER_DATA_FIS)
SCRAMBLER_i: entity work.scrambler
generic map(
CHIPSCOPE => FALSE
)
port map(
-- Clock and Reset Signals
clk => sata_user_clk,
reset => scrambler_reset,
-- ChipScope ILA / Trigger Signals
scrambler_ila_control => scrambler_ila_control,
---------------------------------------
-- Signals from/to Sata Link Layer FIFOs
prim_scrambler => '0',
scrambler_en => scrambler_en,
din_re => scrambler_din_re,
data_in => scrambler_din,
data_out => scrambler_dout,
dout_we => scrambler_dout_we
);
---------------------------------------------------------------------------
-- Post-Scramble TX FIFO to PHY Layer
---------------------------------------------------------------------------
-- Input Signals from User Logic
tx_fifo_din <= scrambler_dout;
tx_fifo_we <= scrambler_dout_we;
TX_FIFO: rx_tx_fifo
port map (
clk => sata_user_clk,
rst => sw_reset,
rd_en => tx_fifo_re,
din => tx_fifo_din,
wr_en => tx_fifo_we,
dout => tx_fifo_dout,
almost_empty => tx_fifo_almost_empty,
empty => tx_fifo_empty,
full => tx_fifo_full,
prog_full => tx_fifo_prog_full,
data_count => tx_fifo_data_count
);
---------------------------------------------------------------------------
-- Sata Phy Instantiation
---------------------------------------------------------------------------
SATA_PHY_i : sata_phy
port map (
oob_control_ila_control=> oob_control_ila_control,
sata_phy_ila_control => sata_phy_ila_control,
REFCLK_PAD_P_IN => REFCLK_PAD_P_IN ,
REFCLK_PAD_N_IN => REFCLK_PAD_N_IN ,
GTXRESET_IN => GTX_RESET_IN ,
PLLLKDET_OUT_N => PLLLKDET_OUT_N ,
TXP0_OUT => TXP0_OUT,
TXN0_OUT => TXN0_OUT,
RXP0_IN => RXP0_IN ,
RXN0_IN => RXN0_IN ,
DCMLOCKED_OUT => DCMLOCKED_OUT,
LINKUP => LINKUP ,
LINKUP_led => LINKUP_led ,
sata_user_clk => sata_user_clk ,
GEN2_led => GEN2_led_i ,
align_en_out => align_en_out,
tx_datain => tx_dataout,
tx_charisk_in => tx_charisk_out,
rx_dataout => rx_datain,
rx_charisk_out => rx_charisk_in,
CurrentState_out => OOB_state,
rxelecidle_out => rxelecidle,
CLKIN_150 => CLKIN_150
);
sata_user_clk_out <= sata_user_clk;
-----------------------------------------------------------------------------
-- ILA Instantiations
-----------------------------------------------------------------------------
chipscope_gen_ila : if (CHIPSCOPE) generate
SATA_RX_FRAME_ILA_i : sata_rx_frame_ila
port map (
control => sata_rx_frame_ila_control,
clk => sata_user_clk,
trig0 => rx_frame_value,
trig1 => tx_dataout,
trig2 => sync_count_rx,
trig3 => master_fsm_value,
trig4 => rx_charisk_in,
trig5 => OOB_state,
trig6 => rx_datain,
trig7 => rx_fifo_dout,
trig8 => read_fifo_din,
trig9 => read_fifo_dout,
trig10(0) => SOF_det,
trig10(1) => EOF_det,
trig10(2) => X_RDY_det,
trig10(3) => WTRM_det,
trig10(4) => HOLD_start_det,
trig10(5) => HOLD_stop_det,
trig10(6) => SYNC_det,
trig10(7) => CONT_det,
trig10(8) => ALIGN_det,
trig10(9) => new_cmd,
trig10(10) => start_rx,
trig10(11) => rx_done,
trig10(12) => descrambler_dout_we,
trig10(13) => tx_charisk_out,
trig10(14) => sw_reset,
trig10(15) => LINKUP,
trig10(16) => rx_fifo_we_next,
trig10(17) => rx_fifo_re,
trig10(18) => rx_fifo_empty,
trig10(19) => descrambler_reset,
trig10(20) => descrambler_en,
trig10(21) => read_fifo_we,
trig10(22) => read_fifo_re,
trig10(23) => rx_fifo_almost_empty,
trig10(24) => HOLD_det_r,
trig10(25) => ALIGN_det_r,
trig10(26) => TWO_HOLD_det,
trig10(27) => read_fifo_empty_i,
trig10(28) => TWO_HOLD_det_r,
trig10(29) => HOLD_det,
trig10(30) => HOLD_stop_after_ALIGN_det,
trig10(31) => ALIGN_det_r2,
trig11 => dword_count,
trig12 => rx_sector_count,
trig13 => DATA_FIS_dword_count,
trig14 => dword_count_value,
trig15 => dword_count_init_value
);
SATA_TX_FRAME_ILA_i : sata_tx_frame_ila
port map (
control => sata_tx_frame_ila_control,
clk => sata_user_clk,
trig0 => tx_frame_value,
trig1 => tx_dataout,
trig2 => rx_datain,
trig3 => tx_fifo_dout,
trig4 => master_fsm_value,
trig5 => tx_fifo_din,
trig6 => write_fifo_din,
trig7 => write_fifo_dout,
trig8 => FIS_word_count,
trig9 => scrambler_count,
trig10(0) => tx_fifo_we,
trig10(1) => tx_fifo_re,
trig10(2) => tx_fifo_full,
trig10(3) => align_en_out,
trig10(4) => SYNC_det,
trig10(5) => R_RDY_det,
trig10(6) => R_IP_det,
trig10(7) => R_OK_det,
trig10(8) => R_ERR_det,
trig10(9) => start_tx,
trig10(10) => tx_done,
trig10(11) => tx_fifo_almost_empty,
trig10(12) => tx_charisk_out,
trig10(13) => tx_fifo_empty,
trig10(14) => scrambler_din_re,
trig10(15) => ALIGN_det,
trig10(16) => HOLD_start_det,
trig10(17) => HOLD_stop_det,
trig10(18) => CONT_det,
trig10(19) => write_fifo_prog_full,
trig10(20) => tx_err,
trig10(21) => write_fifo_almost_empty,
trig10(22) => new_cmd,
trig10(23) => scrambler_reset_after_FIS,
trig10(24) => write_fifo_we,
trig10(25) => write_fifo_re,
trig10(26) => write_fifo_empty,
trig10(27) => scrambler_en,
trig10(28) => tx_fifo_prog_full,
trig10(29) => scrambler_count_en_data_fis,
trig10(30) => scrambler_reset,
trig10(31) => crc_en,
trig11 => scrambler_din,
trig12 => crc_dout,
trig13 => tx_sector_count,
trig14 => scrambler_count_value,
trig15 => tx_fifo_data_count
);
--trig14 => scrambler_count_init_value,
end generate chipscope_gen_ila;
end BEHAV;
-- Copyright (C) 2012
-- Ashwin A. Mendon
--
-- This file is part of SATA2 core.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------------
-- ENTITY: scrambler
-- Version: 1.0
-- Author: Ashwin Mendon
-- Description: This sub-module implements the Scrambler Circuit for the SATA Protocol
-- The code provides a parallel implementation of the following
-- generator polynomial
-- 16 15 13 4
-- G(x) = x + x + x + x + 1
-- The output of this scrambler is then XORed with the input data DWORD
-- The scrambler is initialized to a value of 0xF0F6.
-- The first DWORD output of the implementation is equal to 0xC2D2768D
-- PORTS:
-----------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity scrambler is
generic(
CHIPSCOPE : boolean := false
);
port(
-- Clock and Reset Signals
clk : in std_logic;
reset : in std_logic;
-- ChipScope ILA / Trigger Signals
scrambler_ila_control : in std_logic_vector(35 downto 0);
---------------------------------------
-- Signals from/to Sata Link Layer
scrambler_en : in std_logic;
prim_scrambler : in std_logic;
din_re : out std_logic;
data_in : in std_logic_vector(0 to 31);
data_out : out std_logic_vector(0 to 31);
dout_we : out std_logic
);
end scrambler;
-------------------------------------------------------------------------------
-- ARCHITECTURE
-------------------------------------------------------------------------------
architecture BEHAV of scrambler is
-------------------------------------------------------------------------------
-- Constants
-------------------------------------------------------------------------------
constant SCRAMBLER_INIT : std_logic_vector(0 to 15) := x"F0F6";
signal context : std_logic_vector (15 downto 0);
signal context_next : std_logic_vector (31 downto 0);
signal context_reg : std_logic_vector (31 downto 0);
signal data_out_ila : std_logic_vector (31 downto 0);
signal dout_we_reg : std_logic;
signal dout_we_ila : std_logic;
signal din_re_ila : std_logic;
-----------------------------------------------------------------------------
-- ILA Declaration
-----------------------------------------------------------------------------
component scrambler_ila
port (
control : in std_logic_vector(35 downto 0);
clk : in std_logic;
trig0 : in std_logic_vector(31 downto 0);
trig1 : in std_logic_vector(31 downto 0);
trig2 : in std_logic_vector(31 downto 0);
trig3 : in std_logic_vector(31 downto 0);
trig4 : in std_logic_vector(15 downto 0);
trig5 : in std_logic_vector(3 downto 0)
);
end component;
-------------------------------------------------------------------------------
-- BEGIN
-------------------------------------------------------------------------------
begin
-----------------------------------------------------------------------------
-- PROCESS: SCRAMBLER_PROC
-- PURPOSE: Registering Signals and Next State
-----------------------------------------------------------------------------
SCRAMBLER_PROC : process (clk)
begin
if ((clk'event) and (clk = '1')) then
if (reset = '1') then
--Initializing internal signals
context <= SCRAMBLER_INIT;
context_reg <= (others => '0');
dout_we_reg <= '0';
elsif (scrambler_en = '1') then
-- Register all Current Signals to their _next Signals
context <= context_next(31 downto 16);
context_reg <= context_next;
dout_we_reg <= '1';
else
context <= context;
context_reg <= context_reg;
dout_we_reg <= '0';
end if;
end if;
end process SCRAMBLER_PROC ;
context_next(31) <= context(12) xor context(10) xor context(7) xor context(3) xor context(1) xor context(0);
context_next(30) <= context(15) xor context(14) xor context(12) xor context(11) xor context(9) xor context(6) xor context(3) xor context(2) xor context(0);
context_next(29) <= context(15) xor context(13) xor context(12) xor context(11) xor context(10) xor context(8) xor context(5) xor context(3) xor context(2) xor context(1);
context_next(28) <= context(14) xor context(12) xor context(11) xor context(10) xor context(9) xor context(7) xor context(4) xor context(2) xor context(1) xor context(0);
context_next(27) <= context(15) xor context(14) xor context(13) xor context(12) xor context(11) xor context(10) xor context(9) xor context(8) xor context(6) xor context(1) xor context(0);
context_next(26) <= context(15) xor context(13) xor context(11) xor context(10) xor context(9) xor context(8) xor context(7) xor context(5) xor context(3) xor context(0);
context_next(25) <= context(15) xor context(10) xor context(9) xor context(8) xor context(7) xor context(6) xor context(4) xor context(3) xor context(2);
context_next(24) <= context(14) xor context(9) xor context(8) xor context(7) xor context(6) xor context(5) xor context(3) xor context(2) xor context(1);
context_next(23) <= context(13) xor context(8) xor context(7) xor context(6) xor context(5) xor context(4) xor context(2) xor context(1) xor context(0);
context_next(22) <= context(15) xor context(14) xor context(7) xor context(6) xor context(5) xor context(4) xor context(1) xor context(0);
context_next(21) <= context(15) xor context(13) xor context(12) xor context(6) xor context(5) xor context(4) xor context(0);
context_next(20) <= context(15) xor context(11) xor context(5) xor context(4);
context_next(19) <= context(14) xor context(10) xor context(4) xor context(3);
context_next(18) <= context(13) xor context(9) xor context(3) xor context(2);
context_next(17) <= context(12) xor context(8) xor context(2) xor context(1);
context_next(16) <= context(11) xor context(7) xor context(1) xor context(0);
context_next(15) <= context(15) xor context(14) xor context(12) xor context(10) xor context(6) xor context(3) xor context(0);
context_next(14) <= context(15) xor context(13) xor context(12) xor context(11) xor context(9) xor context(5) xor context(3) xor context(2);
context_next(13) <= context(14) xor context(12) xor context(11) xor context(10) xor context(8) xor context(4) xor context(2) xor context(1);
context_next(12) <= context(13) xor context(11) xor context(10) xor context(9) xor context(7) xor context(3) xor context(1) xor context(0);
context_next(11) <= context(15) xor context(14) xor context(10) xor context(9) xor context(8) xor context(6) xor context(3) xor context(2) xor context(0);
context_next(10) <= context(15) xor context(13) xor context(12) xor context(9) xor context(8) xor context(7) xor context(5) xor context(3) xor context(2) xor context(1);
context_next(9) <= context(14) xor context(12) xor context(11) xor context(8) xor context(7) xor context(6) xor context(4) xor context(2) xor context(1) xor context(0);
context_next(8) <= context(15) xor context(14) xor context(13) xor context(12) xor context(11) xor context(10) xor context(7) xor context(6) xor context(5) xor context(1) xor context(0);
context_next(7) <= context(15) xor context(13) xor context(11) xor context(10) xor context(9) xor context(6) xor context(5) xor context(4) xor context(3) xor context(0);
context_next(6) <= context(15) xor context(10) xor context(9) xor context(8) xor context(5) xor context(4) xor context(2);
context_next(5) <= context(14) xor context(9) xor context(8) xor context(7) xor context(4) xor context(3) xor context(1);
context_next(4) <= context(13) xor context(8) xor context(7) xor context(6) xor context(3) xor context(2) xor context(0);
context_next(3) <= context(15) xor context(14) xor context(7) xor context(6) xor context(5) xor context(3) xor context(2) xor context(1);
context_next(2) <= context(14) xor context(13) xor context(6) xor context(5) xor context(4) xor context(2) xor context(1) xor context(0);
context_next(1) <= context(15) xor context(14) xor context(13) xor context(5) xor context(4) xor context(1) xor context(0);
context_next(0) <= context(15) xor context(13) xor context(4) xor context(0);
data_out_ila <= (context_reg xor data_in) when prim_scrambler = '0' else (context_reg);
--dout_we_ila <= dout_we_reg when scrambler_en = '1' else '0';
dout_we_ila <= dout_we_reg;
din_re_ila <= '1' when scrambler_en = '1' else '0';
-----------------------------------------------------------------------------
-- ILA Instantiation
-----------------------------------------------------------------------------
data_out <= data_out_ila;
dout_we <= dout_we_ila;
din_re <= din_re_ila;
chipscope_gen_ila : if (CHIPSCOPE) generate
SCRAMBLER_ILA_i : scrambler_ila
port map (
control => scrambler_ila_control,
clk => clk,
trig0 => data_in,
trig1 => data_out_ila,
trig2 => context_reg,
trig3 => context_next,
trig4 => context,
trig5(0) => scrambler_en,
trig5(1) => din_re_ila,
trig5(2) => dout_we_ila,
trig5(3) => reset
);
end generate chipscope_gen_ila;
end BEHAV;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment