Commit e4a8fdeb authored by Alexey Grebenkin's avatar Alexey Grebenkin

Major update

parent 740156c0
......@@ -3,7 +3,13 @@ SATA controller for x393 camera
Board: Zynq 7z30
FPGA: Kintex-7
# Current step:
Connecting Ashwin's core (slow interface to the system is almost done, have to completely rewrite phy-level). Feels like making the phy works is going to require a lot of effort
Testing basic functionallity of a host.
Trying out pio access.
Fullfilling device-side drivers and monitors via tasks.
Tests are mostly manual, relied on a common sense and waveforms instpection. Still, complatible both with gtx-gpl and unisims/gtx
# Going to do afterwards:
Complete and test the 'current step'. Write host controller with ~same functionallity, check if it works with previously verified higher-level code.
And then to spin out the full-compatible functionallity (ideally somewhere to the level of ahci)
Test dma functionallity of the host.
Make cocotb testbench - gtx-gpl only - random payload high-level verification testing purposes.
Create a base of regression tests, containing lower-level tests - both gtx-gpl and unisims/gtx.
Improve an implementation of DMA control module.
Finally decide what to do with a driver and modify application level (actally, write it from scrap) correspodning to driver's interfaces.
/*******************************************************************************
* Module: dev_phy
* Date: 2015-07-11
* Author: Alexey
* Description: sata device phy level
*
* Copyright (c) 2015 Elphel, Inc.
* dev_phy.v 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.
*
* dev_phy.v file 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/> .
*******************************************************************************/
/*
* Has minor differences from host's phy. After host would be rewritten all differences
* shall be eliminated.
* Despite having phy-level, the device for now is planned to be simulation purposes only.
*/
module sata_phy(
input wire RXP0_IN, // Receiver input
input wire RXN0_IN, // Receiver input
input wire GTXRESET_IN, // Main reset
input wire CLKIN_150, // external 150 mhz clock input
// Input from Link Layer
input wire [31:0] tx_datain,
input wire [3:0] tx_charisk_in,
output wire DCMLOCKED_OUT, // DCM locked
output wire PLLLKDET_OUT_N, // PLL Lock Detect
output wire TXP0_OUT,
output wire TXN0_OUT,
output wire LINKUP,
output wire LINKUP_led,
output wire GEN2_led,
output wire align_en_out,
output wire sata_user_clk,
// Outputs to Link Layer
output wire [31:0] rx_dataout,
output wire [3:0] rx_charisk_out,
output wire [7:0] CurrentState_out,
output wire rxelecidle_out,
// Rudiments
input wire [35:0] sata_phy_ila_control,
input wire [35:0] oob_control_ila_control
);
parameter CHIPSCOPE = "FALSE";
wire [31:0] txdata;
wire txcharisk;
wire [63:0] rxdata;
wire [7:0] rxcharisk;
wire [31:0] rxdata_out;
wire [3:0] rxcharisk_out;
wire linkup;
wire linkup_led;
wire rxcomwakedet;
wire rxcominitdet;
wire cplllock;
wire txcominit;
wire txcomwake;
wire rxreset;
wire rxelecidle;
wire txelecidle;
wire rxbyteisaligned;
OOB_control oob_control(
.oob_control_ila_control (36'h0),
//-------- GTX Ports --------/
.clk (sata_user_clk),
.reset (GTXRESET_IN),
.rxreset (/*rxreset*/),
.rx_locked (cplllock),
// OOB generation and detection signals from GTX
.txcominit (txcominit),
.txcomwake (txcomwake),
.cominitdet (rxcominitdet),
.comwakedet (rxcomwakedet),
.rxelecidle (rxelecidle),
.txelecidle_out (txelecidle),
.rxbyteisaligned (rxbyteisaligned),
.tx_dataout (txdata), // outgoing GTX data
.tx_charisk_out (txcharisk), // GTX charisk out
.rx_datain (rxdata[31:0]), // incoming GTX data
.rx_charisk_in (rxcharisk[3:0]), // GTX charisk in
.gen2 (1'b1), // for SATA Generation 2
//----- USER DATA PORTS---------//
.tx_datain (tx_datain), // User datain port
.tx_charisk_in (tx_charisk_in), // User charisk in port
.rx_dataout (rxdata_out), // User dataout port
.rx_charisk_out (rxcharisk_out), // User charisk out port
.linkup (linkup),
.linkup_led_out (linkup_led),
.align_en_out (align_en_out),
.CurrentState_out (CurrentState_out)
);
wire cplllockdetclk; // TODO
wire drpclk; // TODO
wire cpllreset;
wire gtrefclk;
wire rxresetdone;
wire txresetdone;
wire txreset;
wire txuserrdy;
wire rxuserrdy;
wire txusrclk;
wire txusrclk2;
wire rxusrclk;
wire rxusrclk2;
wire txp;
wire txn;
wire rxp;
wire rxn;
wire txoutclk;
wire txpmareset_done;
wire rxeyereset_done;
// tx reset sequence; waves @ ug476 p67
localparam TXPMARESET_TIME = 5'h1;
reg [2:0] txpmareset_cnt;
assign txpmareset_done = txpmareset_cnt == TXPMARESET_TIME;
always @ (posedge gtrefclk)
txpmareset_cnt <= txreset ? 3'h0 : txpmareset_done ? txpmareset_cnt : txpmareset_cnt + 1'b1;
// rx reset sequence; waves @ ug476 p77
localparam RXPMARESET_TIME = 5'h11;
localparam RXCDRPHRESET_TIME = 5'h1;
localparam RXCDRFREQRESET_TIME = 5'h1;
localparam RXDFELPMRESET_TIME = 7'hf;
localparam RXISCANRESET_TIME = 5'h1;
localparam RXEYERESET_TIME = 7'h0 + RXPMARESET_TIME + RXCDRPHRESET_TIME + RXCDRFREQRESET_TIME + RXDFELPMRESET_TIME + RXISCANRESET_TIME;
reg [6:0] rxeyereset_cnt;
assign rxeyereset_done = rxeyereset_cnt == RXEYERESET_TIME;
always @ (posedge gtrefclk)
rxeyereset_cnt <= rxreset ? 3'h0 : rxeyereset_done ? rxeyereset_cnt : rxeyereset_cnt + 1'b1;
/*
* Resets
*/
wire usrpll_locked;
assign cpllreset = GTXRESET_IN;
assign rxreset = ~cplllock | cpllreset;
assign txreset = ~cplllock | cpllreset;
assign rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done;
assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done;
/*
* USRCLKs generation. USRCLK @ 150MHz, same as TXOUTCLK; USRCLK2 @ 75Mhz -> sata_clk === sclk
* It's recommended to use MMCM instead of PLL, whatever
*/
wire usrpll_fb_clk;
wire usrclk;
wire usrclk2;
assign txusrclk = usrclk;
assign txusrclk2 = usrclk2;
assign rxusrclk = usrclk;
assign rxusrclk2 = usrclk2;
PLLE2_ADV #(
.BANDWIDTH ("OPTIMIZED"),
.CLKFBOUT_MULT (8),
.CLKFBOUT_PHASE (0.000),
.CLKIN1_PERIOD (6.666),
.CLKIN2_PERIOD (0.000),
.CLKOUT0_DIVIDE (8),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT0_PHASE (0.000),
.CLKOUT1_DIVIDE (16),
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT1_PHASE (0.000),
/* .CLKOUT2_DIVIDE = 1,
.CLKOUT2_DUTY_CYCLE = 0.500,
.CLKOUT2_PHASE = 0.000,
.CLKOUT3_DIVIDE = 1,
.CLKOUT3_DUTY_CYCLE = 0.500,
.CLKOUT3_PHASE = 0.000,
.CLKOUT4_DIVIDE = 1,
.CLKOUT4_DUTY_CYCLE = 0.500,
.CLKOUT4_PHASE = 0.000,
.CLKOUT5_DIVIDE = 1,
.CLKOUT5_DUTY_CYCLE = 0.500,
.CLKOUT5_PHASE = 0.000,*/
.COMPENSATION ("ZHOLD"),
.DIVCLK_DIVIDE (1),
.IS_CLKINSEL_INVERTED (1'b0),
.IS_PWRDWN_INVERTED (1'b0),
.IS_RST_INVERTED (1'b0),
.REF_JITTER1 (0.010),
.REF_JITTER2 (0.010),
.STARTUP_WAIT ("FALSE")
)
usrclk_pll(
.CLKFBOUT (usrpll_fb_clk),
.CLKOUT0 (usrclk),
.CLKOUT1 (usrclk2),
.CLKOUT2 (),
.CLKOUT3 (),
.CLKOUT4 (),
.CLKOUT5 (),
.DO (),
.DRDY (),
.LOCKED (usrpll_locked),
.CLKFBIN (usrpll_fb_clk),
.CLKIN1 (txoutclk),
.CLKIN2 (1'b0),
.CLKINSEL (1'b1),
.DADDR (7'h0),
.DCLK (drpclk),
.DEN (1'b0),
.DI (16'h0),
.DWE (1'b0),
.PWRDWN (1'b0),
.RST (~cplllock)
);
/*
* Padding for an external input clock @ 150 MHz
* TODO !!! Temporary moved to sata_top
*/
assign gtrefclk = CLKIN_150;
/*localparam [1:0] CLKSWING_CFG = 2'b11;
IBUFDS_GTE2 #(
.CLKRCV_TRST ("TRUE"),
.CLKCM_CFG ("TRUE"),
.CLKSWING_CFG (CLKSWING_CFG)
)
ext_clock_buf(
.I (REFCLK_PAD_P_IN),
.IB (REFCLK_PAD_N_IN),
.CEB (1'b0),
.O (gtrefclk),
.ODIV2 ()
);
*/
GTXE2_CHANNEL #(
.SIM_RECEIVER_DETECT_PASS ("TRUE"),
.SIM_TX_EIDLE_DRIVE_LEVEL ("X"),
.SIM_RESET_SPEEDUP ("FALSE"),
.SIM_CPLLREFCLK_SEL (3'b001),
.SIM_VERSION ("4.0"),
.ALIGN_COMMA_DOUBLE ("FALSE"),
.ALIGN_COMMA_ENABLE (10'b1111111111),
.ALIGN_COMMA_WORD (1),
.ALIGN_MCOMMA_DET ("TRUE"),
.ALIGN_MCOMMA_VALUE (10'b1010000011),
.ALIGN_PCOMMA_DET ("TRUE"),
.ALIGN_PCOMMA_VALUE (10'b0101111100),
.SHOW_REALIGN_COMMA ("TRUE"),
.RXSLIDE_AUTO_WAIT (7),
.RXSLIDE_MODE ("OFF"),
.RX_SIG_VALID_DLY (10),
.RX_DISPERR_SEQ_MATCH ("TRUE"),
.DEC_MCOMMA_DETECT ("TRUE"),
.DEC_PCOMMA_DETECT ("TRUE"),
.DEC_VALID_COMMA_ONLY ("FALSE"),
.CBCC_DATA_SOURCE_SEL ("DECODED"),
.CLK_COR_SEQ_2_USE ("FALSE"),
.CLK_COR_KEEP_IDLE ("FALSE"),
.CLK_COR_MAX_LAT (9),
.CLK_COR_MIN_LAT (7),
.CLK_COR_PRECEDENCE ("TRUE"),
.CLK_COR_REPEAT_WAIT (0),
.CLK_COR_SEQ_LEN (1),
.CLK_COR_SEQ_1_ENABLE (4'b1111),
.CLK_COR_SEQ_1_1 (10'b0100000000),
.CLK_COR_SEQ_1_2 (10'b0000000000),
.CLK_COR_SEQ_1_3 (10'b0000000000),
.CLK_COR_SEQ_1_4 (10'b0000000000),
.CLK_CORRECT_USE ("FALSE"),
.CLK_COR_SEQ_2_ENABLE (4'b1111),
.CLK_COR_SEQ_2_1 (10'b0100000000),
.CLK_COR_SEQ_2_2 (10'b0000000000),
.CLK_COR_SEQ_2_3 (10'b0000000000),
.CLK_COR_SEQ_2_4 (10'b0000000000),
.CHAN_BOND_KEEP_ALIGN ("FALSE"),
.CHAN_BOND_MAX_SKEW (1),
.CHAN_BOND_SEQ_LEN (1),
.CHAN_BOND_SEQ_1_1 (10'b0000000000),
.CHAN_BOND_SEQ_1_2 (10'b0000000000),
.CHAN_BOND_SEQ_1_3 (10'b0000000000),
.CHAN_BOND_SEQ_1_4 (10'b0000000000),
.CHAN_BOND_SEQ_1_ENABLE (4'b1111),
.CHAN_BOND_SEQ_2_1 (10'b0000000000),
.CHAN_BOND_SEQ_2_2 (10'b0000000000),
.CHAN_BOND_SEQ_2_3 (10'b0000000000),
.CHAN_BOND_SEQ_2_4 (10'b0000000000),
.CHAN_BOND_SEQ_2_ENABLE (4'b1111),
.CHAN_BOND_SEQ_2_USE ("FALSE"),
.FTS_DESKEW_SEQ_ENABLE (4'b1111),
.FTS_LANE_DESKEW_CFG (4'b1111),
.FTS_LANE_DESKEW_EN ("FALSE"),
.ES_CONTROL (6'b000000),
.ES_ERRDET_EN ("FALSE"),
.ES_EYE_SCAN_EN ("TRUE"),
.ES_HORZ_OFFSET (12'h000),
.ES_PMA_CFG (10'b0000000000),
.ES_PRESCALE (5'b00000),
.ES_QUALIFIER (80'h00000000000000000000),
.ES_QUAL_MASK (80'h00000000000000000000),
.ES_SDATA_MASK (80'h00000000000000000000),
.ES_VERT_OFFSET (9'b000000000),
.RX_DATA_WIDTH (20),
.OUTREFCLK_SEL_INV (2'b11),
.PMA_RSV (32'h00018480),
.PMA_RSV2 (16'h2050),
.PMA_RSV3 (2'b00),
.PMA_RSV4 (32'h00000000),
.RX_BIAS_CFG (12'b000000000100),
.DMONITOR_CFG (24'h000A00),
.RX_CM_SEL (2'b11),
.RX_CM_TRIM (3'b010),
.RX_DEBUG_CFG (12'b000000000000),
.RX_OS_CFG (13'b0000010000000),
.TERM_RCAL_CFG (5'b10000),
.TERM_RCAL_OVRD (1'b0),
.TST_RSV (32'h00000000),
.RX_CLK25_DIV (6),
.TX_CLK25_DIV (6),
.UCODEER_CLR (1'b0),
.PCS_PCIE_EN ("FALSE"),
.PCS_RSVD_ATTR (48'h0100),
.RXBUF_ADDR_MODE ("FAST"),
.RXBUF_EIDLE_HI_CNT (4'b1000),
.RXBUF_EIDLE_LO_CNT (4'b0000),
.RXBUF_EN ("TRUE"),
.RX_BUFFER_CFG (6'b000000),
.RXBUF_RESET_ON_CB_CHANGE ("TRUE"),
.RXBUF_RESET_ON_COMMAALIGN ("FALSE"),
.RXBUF_RESET_ON_EIDLE ("FALSE"),
.RXBUF_RESET_ON_RATE_CHANGE ("TRUE"),
.RXBUFRESET_TIME (5'b00001),
.RXBUF_THRESH_OVFLW (61),
.RXBUF_THRESH_OVRD ("FALSE"),
.RXBUF_THRESH_UNDFLW (4),
.RXDLY_CFG (16'h001F),
.RXDLY_LCFG (9'h030),
.RXDLY_TAP_CFG (16'h0000),
.RXPH_CFG (24'h000000),
.RXPHDLY_CFG (24'h084020),
.RXPH_MONITOR_SEL (5'b00000),
.RX_XCLK_SEL ("RXREC"),
.RX_DDI_SEL (6'b000000),
.RX_DEFER_RESET_BUF_EN ("TRUE"),
.RXCDR_CFG (72'h03000023ff10200020),
.RXCDR_FR_RESET_ON_EIDLE (1'b0),
.RXCDR_HOLD_DURING_EIDLE (1'b0),
.RXCDR_PH_RESET_ON_EIDLE (1'b0),
.RXCDR_LOCK_CFG (6'b010101),
.RXCDRFREQRESET_TIME (RXCDRFREQRESET_TIME),
.RXCDRPHRESET_TIME (RXCDRPHRESET_TIME),
.RXISCANRESET_TIME (RXISCANRESET_TIME),
.RXPCSRESET_TIME (5'b00001),
.RXPMARESET_TIME (RXPMARESET_TIME),
.RXOOB_CFG (7'b0000110),
.RXGEARBOX_EN ("FALSE"),
.GEARBOX_MODE (3'b000),
.RXPRBS_ERR_LOOPBACK (1'b0),
.PD_TRANS_TIME_FROM_P2 (12'h03c),
.PD_TRANS_TIME_NONE_P2 (8'h3c),
.PD_TRANS_TIME_TO_P2 (8'h64),
.SAS_MAX_COM (64),
.SAS_MIN_COM (36),
.SATA_BURST_SEQ_LEN (4'b0111),
.SATA_BURST_VAL (3'b110),
.SATA_EIDLE_VAL (3'b110),
.SATA_MAX_BURST (8),
.SATA_MAX_INIT (21),
.SATA_MAX_WAKE (7),
.SATA_MIN_BURST (4),
.SATA_MIN_INIT (12),
.SATA_MIN_WAKE (4),
.TRANS_TIME_RATE (8'h0E),
.TXBUF_EN ("TRUE"),
.TXBUF_RESET_ON_RATE_CHANGE ("TRUE"),
.TXDLY_CFG (16'h001F),
.TXDLY_LCFG (9'h030),
.TXDLY_TAP_CFG (16'h0000),
.TXPH_CFG (16'h0780),
.TXPHDLY_CFG (24'h084020),
.TXPH_MONITOR_SEL (5'b00000),
.TX_XCLK_SEL ("TXOUT"),
.TX_DATA_WIDTH (40),
.TX_DEEMPH0 (5'b00000),
.TX_DEEMPH1 (5'b00000),
.TX_EIDLE_ASSERT_DELAY (3'b110),
.TX_EIDLE_DEASSERT_DELAY (3'b100),
.TX_LOOPBACK_DRIVE_HIZ ("FALSE"),
.TX_MAINCURSOR_SEL (1'b0),
.TX_DRIVE_MODE ("DIRECT"),
.TX_MARGIN_FULL_0 (7'b1001110),
.TX_MARGIN_FULL_1 (7'b1001001),
.TX_MARGIN_FULL_2 (7'b1000101),
.TX_MARGIN_FULL_3 (7'b1000010),
.TX_MARGIN_FULL_4 (7'b1000000),
.TX_MARGIN_LOW_0 (7'b1000110),
.TX_MARGIN_LOW_1 (7'b1000100),
.TX_MARGIN_LOW_2 (7'b1000010),
.TX_MARGIN_LOW_3 (7'b1000000),
.TX_MARGIN_LOW_4 (7'b1000000),
.TXGEARBOX_EN ("FALSE"),
.TXPCSRESET_TIME (5'b00001),
.TXPMARESET_TIME (TXPMARESET_TIME),
.TX_RXDETECT_CFG (14'h1832),
.TX_RXDETECT_REF (3'b100),
.CPLL_CFG (24'hBC07DC),
.CPLL_FBDIV (4),
.CPLL_FBDIV_45 (5),
.CPLL_INIT_CFG (24'h00001E),
.CPLL_LOCK_CFG (16'h01E8),
.CPLL_REFCLK_DIV (1),
.RXOUT_DIV (2),
.TXOUT_DIV (2),
.SATA_CPLL_CFG ("VCO_3000MHZ"),
.RXDFELPMRESET_TIME (RXDFELPMRESET_TIME),
.RXLPM_HF_CFG (14'b00000011110000),
.RXLPM_LF_CFG (14'b00000011110000),
.RX_DFE_GAIN_CFG (23'h020FEA),
.RX_DFE_H2_CFG (12'b000000000000),
.RX_DFE_H3_CFG (12'b000001000000),
.RX_DFE_H4_CFG (11'b00011110000),
.RX_DFE_H5_CFG (11'b00011100000),
.RX_DFE_KL_CFG (13'b0000011111110),
.RX_DFE_LPM_CFG (16'h0954),
.RX_DFE_LPM_HOLD_DURING_EIDLE (1'b0),
.RX_DFE_UT_CFG (17'b10001111000000000),
.RX_DFE_VP_CFG (17'b00011111100000011),
.RX_CLKMUX_PD (1'b1),
.TX_CLKMUX_PD (1'b1),
.RX_INT_DATAWIDTH (0),
.TX_INT_DATAWIDTH (0),
.TX_QPI_STATUS_EN (1'b0),
.RX_DFE_KL_CFG2 (32'h301148AC),
.RX_DFE_XYD_CFG (13'b0000000000000),
.TX_PREDRIVER_MODE (1'b0)
)
dut(
.CPLLFBCLKLOST (),
.CPLLLOCK (cplllock),
.CPLLLOCKDETCLK (cplllockdetclk),
.CPLLLOCKEN (1'b1),
.CPLLPD (1'b0),
.CPLLREFCLKLOST (),
.CPLLREFCLKSEL (3'b001),
.CPLLRESET (cpllreset),
.GTRSVD (1'b0),
.PCSRSVDIN (1'b0),
.PCSRSVDIN2 (1'b0),
.PMARSVDIN (1'b0),
.PMARSVDIN2 (1'b0),
.TSTIN (1'b1),
.TSTOUT (),
.CLKRSVD (4'b0000),
.GTGREFCLK (1'b0),
.GTNORTHREFCLK0 (1'b0),
.GTNORTHREFCLK1 (1'b0),
.GTREFCLK0 (gtrefclk),
.GTREFCLK1 (1'b0),
.GTSOUTHREFCLK0 (1'b0),
.GTSOUTHREFCLK1 (1'b0),
.DRPADDR (9'b0),
.DRPCLK (drpclk),
.DRPDI (16'b0),
.DRPDO (),
.DRPEN (1'b0),
.DRPRDY (),
.DRPWE (1'b0),
.GTREFCLKMONITOR (),
.QPLLCLK (gtrefclk),
.QPLLREFCLK (gtrefclk),
.RXSYSCLKSEL (2'b00),
.TXSYSCLKSEL (2'b00),
.DMONITOROUT (),
.TX8B10BEN (1'b1),
.LOOPBACK (3'd0),
.PHYSTATUS (),
.RXRATE (3'd0),
.RXVALID (),
.RXPD (2'b00),
.TXPD (2'b00),
.SETERRSTATUS (1'b0),
.EYESCANRESET (1'b0),//rxreset), // p78
.RXUSERRDY (rxuserrdy),
.EYESCANDATAERROR (),
.EYESCANMODE (1'b0),
.EYESCANTRIGGER (1'b0),
.RXCDRFREQRESET (1'b0),
.RXCDRHOLD (1'b0),
.RXCDRLOCK (),
.RXCDROVRDEN (1'b0),
.RXCDRRESET (1'b0),
.RXCDRRESETRSV (1'b0),
.RXCLKCORCNT (),
.RX8B10BEN (1'b1),
.RXUSRCLK (rxusrclk),
.RXUSRCLK2 (rxusrclk2),
.RXDATA (rxdata),
.RXPRBSERR (),
.RXPRBSSEL (3'd0),
.RXPRBSCNTRESET (1'b0),
.RXDFEXYDEN (1'b1),
.RXDFEXYDHOLD (1'b0),
.RXDFEXYDOVRDEN (1'b0),
.RXDISPERR (),
.RXNOTINTABLE (),
.GTXRXP (rxp),
.GTXRXN (rxn),
.RXBUFRESET (1'b0),
.RXBUFSTATUS (),
.RXDDIEN (1'b0),
.RXDLYBYPASS (1'b1),
.RXDLYEN (1'b0),
.RXDLYOVRDEN (1'b0),
.RXDLYSRESET (1'b0),
.RXDLYSRESETDONE (),
.RXPHALIGN (1'b0),
.RXPHALIGNDONE (),
.RXPHALIGNEN (1'b0),
.RXPHDLYPD (1'b0),
.RXPHDLYRESET (1'b0),
.RXPHMONITOR (),
.RXPHOVRDEN (1'b0),
.RXPHSLIPMONITOR (),
.RXSTATUS (),
.RXBYTEISALIGNED (rxbyteisaligned),
.RXBYTEREALIGN (),
.RXCOMMADET (),
.RXCOMMADETEN (1'b1),
.RXMCOMMAALIGNEN (1'b1),
.RXPCOMMAALIGNEN (1'b1),
.RXCHANBONDSEQ (),
.RXCHBONDEN (1'b0),
.RXCHBONDLEVEL (3'd0),
.RXCHBONDMASTER (1'b0),
.RXCHBONDO (),
.RXCHBONDSLAVE (1'b0),
.RXCHANISALIGNED (),
.RXCHANREALIGN (),
.RXLPMHFHOLD (1'b0),
.RXLPMHFOVRDEN (1'b0),
.RXLPMLFHOLD (1'b0),
.RXDFEAGCHOLD (1'b0),
.RXDFEAGCOVRDEN (1'b0),
.RXDFECM1EN (1'b0),
.RXDFELFHOLD (1'b0),
.RXDFELFOVRDEN (1'b1),
.RXDFELPMRESET (rxreset),
.RXDFETAP2HOLD (1'b0),
.RXDFETAP2OVRDEN (1'b0),
.RXDFETAP3HOLD (1'b0),
.RXDFETAP3OVRDEN (1'b0),
.RXDFETAP4HOLD (1'b0),
.RXDFETAP4OVRDEN (1'b0),
.RXDFETAP5HOLD (1'b0),
.RXDFETAP5OVRDEN (1'b0),
.RXDFEUTHOLD (1'b0),
.RXDFEUTOVRDEN (1'b0),
.RXDFEVPHOLD (1'b0),
.RXDFEVPOVRDEN (1'b0),
// .RXDFEVSEN (1'b0),
.RXLPMLFKLOVRDEN (1'b0),
.RXMONITOROUT (),
.RXMONITORSEL (2'b01),
.RXOSHOLD (1'b0),
.RXOSOVRDEN (1'b0),
.RXRATEDONE (),
.RXOUTCLK (),
.RXOUTCLKFABRIC (),
.RXOUTCLKPCS (),
.RXOUTCLKSEL (3'b010),
.RXDATAVALID (),
.RXHEADER (),
.RXHEADERVALID (),
.RXSTARTOFSEQ (),
.RXGEARBOXSLIP (1'b0),
.GTRXRESET (rxreset),
.RXOOBRESET (1'b0),
.RXPCSRESET (1'b0),
.RXPMARESET (1'b0),//rxreset), // p78
.RXLPMEN (1'b0),
.RXCOMSASDET (),
.RXCOMWAKEDET (rxcomwakedet),
.RXCOMINITDET (rxcominitdet),
.RXELECIDLE (rxelecidle),
.RXELECIDLEMODE (2'b00),
.RXPOLARITY (1'b0),
.RXSLIDE (1'b0),
.RXCHARISCOMMA (),
.RXCHARISK (rxcharisk),
.RXCHBONDI (5'b00000),
.RXRESETDONE (rxresetdone),
.RXQPIEN (1'b0),
.RXQPISENN (),
.RXQPISENP (),
.TXPHDLYTSTCLK (1'b0),
.TXPOSTCURSOR (5'b00000),
.TXPOSTCURSORINV (1'b0),
.TXPRECURSOR (5'd0),
.TXPRECURSORINV (1'b0),
.TXQPIBIASEN (1'b0),
.TXQPISTRONGPDOWN (1'b0),
.TXQPIWEAKPUP (1'b0),
.CFGRESET (1'b0),
.GTTXRESET (txreset),
.PCSRSVDOUT (),
.TXUSERRDY (txuserrdy),
.GTRESETSEL (1'b0),
.RESETOVRD (1'b0),
.TXCHARDISPMODE (8'd0),
.TXCHARDISPVAL (8'd0),
.TXUSRCLK (txusrclk),
.TXUSRCLK2 (txusrclk2),
.TXELECIDLE (txelecidle),
.TXMARGIN (3'd0),
.TXRATE (3'd0),
.TXSWING (1'b0),
.TXPRBSFORCEERR (1'b0),
.TXDLYBYPASS (1'b1),
.TXDLYEN (1'b0),
.TXDLYHOLD (1'b0),
.TXDLYOVRDEN (1'b0),
.TXDLYSRESET (1'b0),
.TXDLYSRESETDONE (),
.TXDLYUPDOWN (1'b0),
.TXPHALIGN (1'b0),
.TXPHALIGNDONE (),
.TXPHALIGNEN (1'b0),
.TXPHDLYPD (1'b0),
.TXPHDLYRESET (1'b0),
.TXPHINIT (1'b0),
.TXPHINITDONE (),
.TXPHOVRDEN (1'b0),
.TXBUFSTATUS (),
.TXBUFDIFFCTRL (3'b100),
.TXDEEMPH (1'b0),
.TXDIFFCTRL (4'b1000),
.TXDIFFPD (1'b0),
.TXINHIBIT (1'b0),
.TXMAINCURSOR (7'b0000000),
.TXPISOPD (1'b0),
.TXDATA ({32'h0, txdata}),
.GTXTXN (txn),
.GTXTXP (txp),
.TXOUTCLK (txoutclk),
.TXOUTCLKFABRIC (),
.TXOUTCLKPCS (),
.TXOUTCLKSEL (3'b010),
.TXRATEDONE (),
.TXCHARISK ({7'b0, txcharisk}),
.TXGEARBOXREADY (),
.TXHEADER (3'd0),
.TXSEQUENCE (7'd0),
.TXSTARTSEQ (1'b0),
.TXPCSRESET (1'b0),
.TXPMARESET (1'b0),
.TXRESETDONE (txresetdone),
.TXCOMFINISH (),
.TXCOMINIT (txcominit),
.TXCOMSAS (1'b0),
.TXCOMWAKE (txcomwake),
.TXPDELECIDLEMODE (1'b0),
.TXPOLARITY (1'b0),
.TXDETECTRX (1'b0),
.TX8B10BBYPASS (8'd0),
.TXPRBSSEL (3'd0),
.TXQPISENN (),
.TXQPISENP ()/*,
.TXSYNCMODE (1'b0),
.TXSYNCALLIN (1'b0),
.TXSYNCIN (1'b0)*/
);
/*
* Interfaces
*/
assign DCMLOCKED_OUT = usrpll_locked;
assign PLLLKDET_OUT_N = cplllock;
assign rxn = RXN0_IN;
assign rxp = RXP0_IN;
assign TXN0_OUT = txn;
assign TXP0_OUT = txp;
assign cplllockdetclk = CLKIN_150;
assign drpclk = CLKIN_150;
assign LINKUP = linkup;
assign LINKUP_led = linkup_led;
assign rx_dataout = rxdata_out;
assign rx_charisk_out = rxcharisk_out;
assign rxelecidle_out = rxelecidle;
assign GEN2_led = 1'b0;
assign sata_user_clk = usrclk2;
endmodule
wire [31:0] phy2dev_data;
wire [3:0] phy2dev_charisk;
wire [3:0] phy2dev_err;
wire dev_clk;
wire dev_rst;
reg [31:0] dev2phy_data;
reg [3:0] dev2phy_charisk;
force dev.dev2phy_data =
force dev.dev2phy_charisk =
task
/*******************************************************************************
* Module: oob_ctrl
* Date: 2015-07-11
* Author: Alexey
* Description: module to start oob sequences and to handle errors
*
* Copyright (c) 2015 Elphel, Inc.
* oob_ctrl.v 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.
*
* oob_ctrl.v file 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/> .
*******************************************************************************/
`include "oob.v"
module oob_ctrl_dev #(
parameter DATA_BYTE_WIDTH = 4,
parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
)
(
// sata clk = usrclk2
input wire clk,
// reset oob
input wire rst,
// gtx is ready = all resets are done
input wire gtx_ready,
// oob responces
input wire rxcominitdet_in,
input wire rxcomwakedet_in,
input wire rxelecidle_in,
// oob issues
output wire txcominit,
output wire txcomwake,
output wire txelecidle,
// input data stream (if any data during OOB setting => ignored)
input wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_in,
input wire [DATA_BYTE_WIDTH - 1:0] txcharisk_in,
// output data stream to gtx
output wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_out,
output wire [DATA_BYTE_WIDTH - 1:0] txcharisk_out,
// input data from gtx
input wire [DATA_BYTE_WIDTH*8 - 1:0] rxdata_in,
input wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_in,
// bypassed data from gtx
output wire [DATA_BYTE_WIDTH*8 - 1:0] rxdata_out,
output wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_out,
// obvious
input wire rxbyteisaligned,
// shows if channel is ready
output wire phy_ready
);
// oob sequence needs to be issued
wire oob_start;
// connection established, all further data is valid
wire oob_done;
// doc p265, link is established after 3back-to-back non-ALIGNp
wire link_up;
wire link_down;
// the device itself sends cominit
wire cominit_req;
// allow to respond to cominit
wire cominit_allow;
// status information to handle by a control block if any exists
// incompatible host-device speed grades (host cannot lock to alignp)
wire oob_incompatible; // TODO
// timeout in an unexpected place
wire oob_error;
// noone responds to our cominits
wire oob_silence;
// obvious
wire oob_busy;
// for the resync sake
reg rxbyteisaligned_r;
reg rxbyteisaligned_rr;
always @ (posedge clk)
begin
rxbyteisaligned_rr <= rxbyteisaligned_r;
rxbyteisaligned_r <= rxbyteisaligned;
end
// 1 - link is up and running, 0 - probably not
reg link_state;
// 1 - connection is being established OR already established, 0 - is not
reg oob_state;
assign phy_ready = link_state & gtx_ready & rxbyteisaligned_rr;
always @ (posedge clk)
link_state <= (link_state | link_up) & ~link_down & ~rst;
always @ (posedge clk)
oob_state <= (oob_state | oob_start | cominit_req & cominit_allow) & ~oob_error & ~oob_silence & link_down & ~rst;
// decide when to issue oob: always when gtx is ready
assign oob_start = gtx_ready & ~oob_state & ~oob_busy;
// set line to idle state before if we're waiting for a device to answer AND while oob sequence
wire txelecidle_inner;
assign txelecidle = ~oob_state | txelecidle_inner;
// let devices always begin oob sequence, if only it's not a glitch
assign cominit_allow = cominit_req & link_state;
oob_dev #(
.DATA_BYTE_WIDTH (DATA_BYTE_WIDTH),
.CLK_SPEED_GRADE (CLK_SPEED_GRADE)
)
oob_dev
(
// sata clk = usrclk2
.clk (clk),
// reset oob
.rst (rst),
// oob responces
.rxcominitdet_in (rxcominitdet_in),
.rxcomwakedet_in (rxcomwakedet_in),
.rxelecidle_in (rxelecidle_in),
// oob issues
.txcominit (txcominit),
.txcomwake (txcomwake),
.txelecidle (txelecidle_inner),
// input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in),
.txcharisk_in (txcharisk_in),
// output data stream to gtx
.txdata_out (txdata_out),
.txcharisk_out (txcharisk_out),
// input data from gtx
.rxdata_in (rxdata_in),
.rxcharisk_in (rxcharisk_in),
// bypassed data from gtx
.rxdata_out (rxdata_out),
.rxcharisk_out (rxcharisk_out),
// oob sequence needs to be issued
.oob_start (oob_start),
// connection established, all further data is valid
.oob_done (oob_done),
// doc p265, link is established after 3back-to-back non-ALIGNp
.link_up (link_up),
.link_down (link_down),
// the device itself sends cominit
.cominit_req (cominit_req),
// allow to respond to cominit
.cominit_allow (cominit_allow),
// status information to handle by a control block if any exists
// incompatible host-device speed grades (host cannot lock to alignp)
.oob_incompatible (oob_incompatible),
// timeout in an unexpected place
.oob_error (oob_error),
// noone responds to our cominits
.oob_silence (oob_silence),
// oob can't handle new start request
.oob_busy (oob_busy)
);
endmodule
/*******************************************************************************
* Module: oob
* Date: 2015-07-11
* Author: Alexey
* Description: sata oob unit implementation
*
* Copyright (c) 2015 Elphel, Inc.
* oob.v 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.
*
* oob.v file 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/> .
*******************************************************************************/
/*
* For now both device and host shall be set up to SATA2 speeds.
* Need to think how to change speed grades on fly (either to broaden
* data iface width or to change RXRATE/TXRATE)
*/
// All references to doc = to SerialATA_Revision_2_6_Gold.pdf
module oob_dev #(
parameter DATA_BYTE_WIDTH = 4,
parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
)
(
// sata clk = usrclk2
input wire clk,
// reset oob
input wire rst,
input wire gtx_ready,
// oob responces
input wire rxcominitdet_in,
input wire rxcomwakedet_in,
input wire rxelecidle_in,
// oob issues
output reg txcominit,
output reg txcomwake,
output reg txelecidle,
// output data stream to gtx
output wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_out,
output wire [DATA_BYTE_WIDTH - 1:0] txcharisk_out,
// input data from gtx
input wire [DATA_BYTE_WIDTH*8 - 1:0] rxdata_in,
input wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_in,
output wire link_up
);
localparam STATE_RESET = 0;
localparam STATE_COMINIT = 1;
localparam STATE_AWAITCOMWAKE = 2;
localparam STATE_AWAITNOCOMWAKE = 3;
localparam STATE_CALIBRATE = 4;
localparam STATE_COMWAKE = 5;
localparam STATE_SENDALIGN = 6;
localparam STATE_READY = 7;
localparam STATE_PARTIAL = 8;
localparam STATE_SLUMBER = 9;
localparam STATE_REDUCESPEED = 10;
localparam STATE_ERROR = 11;
reg [9:0] state;
wire retry_interval_elapsed;
wire wait_interval_elapsed;
wire nocomwake;
wire [31:0] align;
wire [31:0] sync;
assign align = {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}; // {D27.3, D10.2, D10.2, K28.5}
assign sync = {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}; // {D21.5, D21.5, D21.4, K28.3}
reg [31:0] nocomwake_timer;
assign nocomwake = nocomwake_timer == 32'd38;
always @ (posedge clk)
nocomwake_timer <= rst | rxcomwakedet_in ? 32'h0 : nocomwake ? nocomwake_timer : nocomwake_timer + 1'b1;
reg [31:0] retry_timer;
assign retry_interval_elapsed = retry_timer == 32'd1000;
always @ (posedge clk)
retry_timer <= rst | ~(state == STATE_AWAITCOMWAKE) ? 32'h0 : retry_timer + 1'b1;
reg [31:0] wait_timer;
assign wait_interval_elapsed = wait_timer == 32'd1000;
always @ (posedge clk)
wait_timer <= rst | ~(state == STATE_SENDALIGN) ? 32'h0 : wait_timer + 1'b1;
reg [31:0] data;
reg [3:0] isk;
assign link_up = state == STATE_READY;
assign txdata_out = data;
assign txcharisk_out = isk;
// buf inputs from gtx
reg rxcominitdet;
reg rxcomwakedet;
reg rxelecidle;
reg [31:0] rxdata;
reg [3:0] rxcharisk;
always @ (posedge clk)
begin
rxcominitdet <= rxcominitdet_in;
rxcomwakedet <= rxcomwakedet_in;
rxelecidle <= rxelecidle_in;
rxdata <= rxdata_in;
rxcharisk <= rxcharisk_in;
end
assign aligndet = ~|(rxdata ^ {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 4'h1); // {D27.3, D10.2, D10.2, K28.5}
assign syncdet = ~|(rxdata ^ {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 4'h1); // {D21.5, D21.5, D21.4, K28.3}
always @ (posedge clk)
if (rst | ~gtx_ready)
begin
state <= STATE_RESET;
txelecidle <= 1'b1;
txcominit <= 1'b0;
txcomwake <= 1'b0;
end
else
case (state)
STATE_RESET:
begin
if (rxcominitdet_in)
state <= STATE_COMINIT;
txelecidle <= 1'b1;
txcominit <= 1'b0;
txcomwake <= 1'b0;
end
STATE_COMINIT:
begin
state <= STATE_AWAITCOMWAKE;
txcominit <= 1'b1;
end
STATE_AWAITCOMWAKE:
begin
txcominit <= 1'b0;
if (rxcomwakedet_in)
state <= STATE_AWAITNOCOMWAKE;
else
if (retry_interval_elapsed)
state <= STATE_RESET;
else
state <= STATE_AWAITCOMWAKE;
end
STATE_AWAITNOCOMWAKE:
begin
if (nocomwake)
begin
state <= STATE_CALIBRATE;
end
end
STATE_CALIBRATE:
begin
state <= STATE_COMWAKE;
end
STATE_COMWAKE:
begin
txcomwake <= 1'b1;
state <= STATE_SENDALIGN;
end
STATE_SENDALIGN:
begin
txcomwake <= 1'b0;
txelecidle <= 1'b0;
data <= align;
isk <= 4'h1;
if (aligndet)
state <= STATE_READY;
else
if (wait_interval_elapsed)
state <= STATE_ERROR;
else
state <= STATE_SENDALIGN;
end
STATE_READY:
begin
data <= sync;
isk <= 4'h1;
if (rxelecidle_in)
state <= STATE_ERROR;
end
STATE_ERROR:
begin
state <= STATE_RESET;
end
endcase
/*
// 873.8 us error timer
// = 2621400 SATA2 serial ticks (period = 0.000333 us)
// = 131070 ticks @ 150Mhz
// = 65535 ticks @ 75Mhz
localparam [19:0] CLK_TO_TIMER_CONTRIB = CLK_SPEED_GRADE == 1 ? 20'h4 :
CLK_SPEED_GRADE == 2 ? 20'h2 :
CLK_SPEED_GRADE == 4 ? 20'h1 : 20'h1;
`ifdef SIMULATION
localparam [19:0] TIMER_LIMIT = 19'd200;
`else
localparam [19:0] TIMER_LIMIT = 19'd262140;
`endif
reg [19:0] timer;
wire timer_clr;
wire timer_fin;
// latching inputs from gtx
reg rxcominitdet;
reg rxcomwakedet;
reg rxelecidle;
reg [DATA_BYTE_WIDTH*8 - 1:0] rxdata;
reg [DATA_BYTE_WIDTH - 1:0] rxcharisk;
// primitives detection
wire detected_alignp;
wire detected_syncp;
// fsm, doc p265,266
wire state_idle;
reg state_wait_cominit;
reg state_wait_comwake;
reg state_wait_align;
reg state_wait_synp;
reg state_wait_linkup;
reg state_error;
wire set_wait_cominit;
wire set_wait_comwake;
wire set_wait_align;
wire set_wait_synp;
wire set_wait_linkup;
wire set_error;
wire clr_wait_cominit;
wire clr_wait_comwake;
wire clr_wait_align;
wire clr_wait_synp;
wire clr_wait_linkup;
wire clr_error;
assign state_idle = ~state_wait_cominit & ~state_wait_comwake & ~state_wait_align & ~state_wait_synp & ~state_wait_linkup & ~state_error;
always @ (posedge clk)
begin
state_wait_cominit <= (state_wait_cominit | set_wait_cominit) & ~clr_wait_cominit & ~rst;
state_wait_comwake <= (state_wait_comwake | set_wait_comwake) & ~clr_wait_comwake & ~rst;
state_wait_align <= (state_wait_align | set_wait_align ) & ~clr_wait_align & ~rst;
state_wait_synp <= (state_wait_synp | set_wait_synp ) & ~clr_wait_synp & ~rst;
state_wait_linkup <= (state_wait_linkup | set_wait_linkup ) & ~clr_wait_linkup & ~rst;
state_error <= (state_error | set_error ) & ~clr_error & ~rst;
end
assign set_wait_cominit = state_idle & oob_start & ~cominit_req;
assign set_wait_comwake = state_idle & cominit_req & cominit_allow | state_wait_cominit & rxcominitdet;
assign set_wait_align = state_wait_comwake & rxcomwakedet;
assign set_wait_synp = state_wait_align & detected_alignp;
assign set_wait_linkup = state_wait_synp & detected_syncp;
assign set_error = timer_fin & (state_wait_cominit | state_wait_comwake | state_wait_align | state_wait_synp);
assign clr_wait_cominit = set_wait_comwake | set_error;
assign clr_wait_comwake = set_wait_align | set_error;
assign clr_wait_align = set_wait_synp | set_error;
assign clr_wait_synp = set_wait_linkup | set_error;
assign clr_wait_linkup = state_wait_linkup; //TODO not so important, but still have to trace 3 back-to-back non alignp primitives
assign clr_error = state_error;
// waiting timeout timer
assign timer_fin = timer == TIMER_LIMIT;
assign timer_clr = set_error | state_error | state_idle;
always @ (posedge clk)
timer <= rst | timer_clr ? 20'h0 : timer + CLK_TO_TIMER_CONTRIB;
// something is wrong with speed grades if the host cannot lock to device's alignp stream
assign oob_incompatible = state_wait_align & set_error;
// oob sequence is done, everything is okay
assign oob_done = set_wait_linkup;
// noone responds to cominits
assign oob_silence = set_error & state_wait_cominit;
// other timeouts
assign oob_error = set_error & ~oob_silence & ~oob_incompatible;
// obvioud
assign oob_busy = ~state_idle;
// set gtx controls
reg txelecidle_r;
always @ (posedge clk)
txelecidle_r <= rst ? 1'b1 : clr_wait_cominit ? 1'b0 : set_wait_cominit ? 1'b1 : txelecidle_r;
assign txcominit = set_wait_cominit;
assign txcomwake = set_wait_comwake;
assign txelecidle = set_wait_cominit | txelecidle_r;
// indicate if link up condition was made
assign link_up = clr_wait_linkup;
// link goes down when line is idle
reg rxelecidle_r;
reg rxelecidle_rr;
always @ (posedge clk)
begin
rxelecidle_rr <= rxelecidle_r;
rxelecidle_r <= rxelecidle;
end
assign link_down = rxelecidle_rr;
// indicate that device is requesting for oob
reg cominit_req_r;
wire cominit_req_set;
assign cominit_req_set = state_idle & rxcominitdet;
always @ (posedge clk)
cominit_req_r <= (cominit_req_r | cominit_req_set) & ~(cominit_allow & cominit_req) & ~rst;
assign cominit_req = cominit_req_set | cominit_req_r;
// detect which primitives sends the device after comwake was done
generate
if (DATA_BYTE_WIDTH == 2)
begin
reg detected_alignp_f;
always @ (posedge clk)
detected_alignp_f <= rst | ~state_wait_align ? 1'b0 :
~|(rxdata ^ {8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 2'b01); // {D10.2, K28.5}
assign detected_alignp = detected_alignp_f & ~|(rxdata ^ {8'b01111011, 8'b01001010}) & ~|(rxcharisk ^ 2'b00); // {D27.3, D10.2}
reg detected_syncp_f;
always @ (posedge clk)
detected_syncp_f <= rst | ~state_wait_synp ? 1'b0 :
~|(rxdata ^ {8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 2'b01); // {D21.4, K28.3}
assign detected_syncp = detected_syncp_f & ~|(rxdata ^ {8'b10110101, 8'b10110101}) & ~|(rxcharisk ^ 2'b00); // {D21.5, D21.5}
end
else
if (DATA_BYTE_WIDTH == 4)
begin
assign detected_alignp = ~|(rxdata ^ {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 4'h1); // {D27.3, D10.2, D10.2, K28.5}
assign detected_syncp = ~|(rxdata ^ {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 4'h1); // {D21.5, D21.5, D21.4, K28.3}
end
else
if (DATA_BYTE_WIDTH == 8)
begin
assign detected_alignp = ~|(rxdata ^ {2{8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}}) & ~|(rxcharisk ^ 8'h11); // {D27.3, D10.2, D10.2, K28.5}
assign detected_syncp = ~|(rxdata ^ {2{8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}}) & ~|(rxcharisk ^ 8'h11); // {D21.5, D21.5, D21.4, K28.3}
end
else
begin
always @ (posedge clk)
begin
$display("%m oob module works only with 16/32/64 gtx input data width");
$finish;
end
end
endgenerate
// buf inputs from gtx
always @ (posedge clk)
begin
rxcominitdet <= rxcominitdet_in;
rxcomwakedet <= rxcomwakedet_in;
rxelecidle <= rxelecidle_in;
rxdata <= rxdata_in;
rxcharisk <= rxcharisk_in;
end
// set data outputs to upper levels
assign rxdata_out = rxdata;
assign rxcharisk_out = rxcharisk;
// as depicted @ doc, p264, figure 163, have to insert D10.2 and align primitives after
// getting comwake from device
reg [DATA_BYTE_WIDTH*8 - 1:0] txdata;
reg [DATA_BYTE_WIDTH - 1:0] txcharisk;
wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_d102;
wire [DATA_BYTE_WIDTH - 1:0] txcharisk_d102;
wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_align;
wire [DATA_BYTE_WIDTH - 1:0] txcharisk_align;
always @ (posedge clk)
begin
txdata <= state_wait_align ? txdata_d102 :
state_wait_synp ? txdata_align : txdata_in;
txcharisk <= state_wait_align ? txcharisk_d102 :
state_wait_synp ? txcharisk_align : txcharisk_in;
end
// Continious D10.2 primitive
assign txcharisk_d102 = {DATA_BYTE_WIDTH{1'b0}};
assign txdata_d102 = {DATA_BYTE_WIDTH{8'b01001010}};
// Align primitive: K28.5 + D10.2 + D10.2 + D27.3
generate
if (DATA_BYTE_WIDTH == 2)
begin
reg align_odd;
always @ (posedge clk)
align_odd <= rst | ~state_wait_synp ? 1'b0 : ~align_odd;
assign txcharisk_align = align_odd ? 2'b01 : 2'b00;
assign txdata_align = align_odd ? {8'b01001010, 8'b10111100} : // {D10.2, K28.5}
{8'b01111011, 8'b01001010}; // {D27.3, D10.2}
end
else
if (DATA_BYTE_WIDTH == 4)
begin
assign txcharisk_align = 4'h1;
assign txdata_align = {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}; // {D27.3, D10.2, D10.2, K28.5}
end
else
if (DATA_BYTE_WIDTH == 8)
begin
assign txcharisk_align = 8'h11;
assign txdata_align = {2{8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}}; // 2x{D27.3, D10.2, D10.2, K28.5}
end
else
always @ (posedge clk)
begin
$display("%m oob module works only with 16/32/64 gtx input data width");
$finish;
end
endgenerate
// set data outputs to gtx
assign txdata_out = txdata;
assign txcharisk_out = txcharisk;
*/
endmodule
/*******************************************************************************
* Module: sata_device
* Date: 2015-07-11
* Author: Alexey
* Description: sata device emul top level
*
* Copyright (c) 2015 Elphel, Inc.
* sata_device.v 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.
*
* sata_device.v file 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/> .
*******************************************************************************/
`include "sata_phy_dev.v"
module sata_device(
input wire rst,
input wire RXN,
input wire RXP,
output wire TXN,
output wire TXP,
input wire EXTCLK_P,
input wire EXTCLK_N
);
wire phy_ready;
wire [31:0] phy2dev_data;
wire [3:0] phy2dev_charisk;
wire [3:0] phy2dev_err;
wire clk;
wire dev_rst;
reg [31:0] dev2phy_data = 32'hB5B5957C; // SYNCP
reg [3:0] dev2phy_isk = 4'h1;
sata_phy_dev phy(
// pll reset
.extrst (rst),
// top-level ifaces
// ref clk from an external source, shall be connected to pads
.extclk_p (EXTCLK_P),
.extclk_n (EXTCLK_N),
// sata link data pins
.txp_out (TXP),
.txn_out (TXN),
.rxp_in (RXP),
.rxn_in (RXN),
.clk (clk),
.rst (dev_rst),
.phy_ready (phy_ready),
.ll_data_out (phy2dev_data),
.ll_charisk_out (phy2dev_charisk),
.ll_err_out (phy2dev_err),
.ll_data_in (dev2phy_data),
.ll_charisk_in (dev2phy_isk)
);
localparam [31:0] PRIM_SYNCP = {3'd5, 5'd21, 3'd5, 5'd21, 3'd4, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_ALIGNP = {3'd3, 5'd27, 3'd2, 5'd10, 3'd2, 5'd10, 3'd5, 5'd28};
localparam [31:0] PRIM_XRDYP = {3'd2, 5'd23, 3'd2, 5'd23, 3'd5, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_SOFP = {3'd1, 5'd23, 3'd1, 5'd23, 3'd5, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_HOLDAP = {3'd4, 5'd21, 3'd4, 5'd21, 3'd5, 5'd10, 3'd3, 5'd28};
localparam [31:0] PRIM_HOLDP = {3'd6, 5'd21, 3'd6, 5'd21, 3'd5, 5'd10, 3'd3, 5'd28};
localparam [31:0] PRIM_EOFP = {3'd6, 5'd21, 3'd6, 5'd21, 3'd5, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_WTRMP = {3'd2, 5'd24, 3'd2, 5'd24, 3'd5, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_RRDYP = {3'd2, 5'd10, 3'd2, 5'd10, 3'd4, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_IPP = {3'd2, 5'd21, 3'd2, 5'd21, 3'd5, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_DMATP = {3'd1, 5'd22, 3'd1, 5'd22, 3'd5, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_OKP = {3'd1, 5'd21, 3'd1, 5'd21, 3'd5, 5'd21, 3'd3, 5'd28};
localparam [31:0] PRIM_ERRP = {3'd2, 5'd22, 3'd2, 5'd22, 3'd5, 5'd21, 3'd3, 5'd28};
initial begin
$display("LIST OF PRIMITIVES:");
$display("SYNC = %x", PRIM_SYNCP );
$display("ALIGN = %x", PRIM_ALIGNP);
$display("XRDY = %x", PRIM_XRDYP );
$display("SOF = %x", PRIM_SOFP );
$display("HOLDA = %x", PRIM_HOLDAP);
$display("HOLD = %x", PRIM_HOLDP );
$display("EOF = %x", PRIM_EOFP );
$display("WTRM = %x", PRIM_WTRMP );
$display("RRDY = %x", PRIM_RRDYP );
$display("IP = %x", PRIM_IPP );
$display("DMAT = %x", PRIM_DMATP );
$display("OK = %x", PRIM_OKP );
$display("ERR = %x", PRIM_ERRP );
end
integer transmit_lock = 0;
integer receive_lock = 0;
integer suppress_receive = 0;
reg [31:0] receive_data [2047:0];
reg [31:0] receive_data_pause [2047:0];
reg [31:0] receive_wait_fifo;
reg [31:0] receive_crc;
integer receive_id = 0;
integer receive_status = 0;
/*
* Monitor incoming primitives every clock cycle
* if there is a data transfer request, start a receive sequence
*/
initial forever @ (posedge clk) begin
if (~transmit_lock) begin
// transmitting sequence is not started
if (~receive_lock) begin
// if for the current xrdy stream we haven't aready started a receiving sequence
if (~suppress_receive) begin
// if we do not intentionally ignore host's transmissions
if (linkGetPrim(0) == "XRDY") begin
linkMonitorFIS(receive_id, 2049, receive_status);
receive_id = receive_id + 1;
end
end
end
end
end
function [31:0] scrambleFunc;
input [31:0] context;
reg [31:0] next;
reg [15:0] now;
begin
now = context[15:0];
next[31] = now[12] ^ now[10] ^ now[7] ^ now[3] ^ now[1] ^ now[0];
next[30] = now[15] ^ now[14] ^ now[12] ^ now[11] ^ now[9] ^ now[6] ^ now[3] ^ now[2] ^ now[0];
next[29] = now[15] ^ now[13] ^ now[12] ^ now[11] ^ now[10] ^ now[8] ^ now[5] ^ now[3] ^ now[2] ^ now[1];
next[28] = now[14] ^ now[12] ^ now[11] ^ now[10] ^ now[9] ^ now[7] ^ now[4] ^ now[2] ^ now[1] ^ now[0];
next[27] = now[15] ^ now[14] ^ now[13] ^ now[12] ^ now[11] ^ now[10] ^ now[9] ^ now[8] ^ now[6] ^ now[1] ^ now[0];
next[26] = now[15] ^ now[13] ^ now[11] ^ now[10] ^ now[9] ^ now[8] ^ now[7] ^ now[5] ^ now[3] ^ now[0];
next[25] = now[15] ^ now[10] ^ now[9] ^ now[8] ^ now[7] ^ now[6] ^ now[4] ^ now[3] ^ now[2];
next[24] = now[14] ^ now[9] ^ now[8] ^ now[7] ^ now[6] ^ now[5] ^ now[3] ^ now[2] ^ now[1];
next[23] = now[13] ^ now[8] ^ now[7] ^ now[6] ^ now[5] ^ now[4] ^ now[2] ^ now[1] ^ now[0];
next[22] = now[15] ^ now[14] ^ now[7] ^ now[6] ^ now[5] ^ now[4] ^ now[1] ^ now[0];
next[21] = now[15] ^ now[13] ^ now[12] ^ now[6] ^ now[5] ^ now[4] ^ now[0];
next[20] = now[15] ^ now[11] ^ now[5] ^ now[4];
next[19] = now[14] ^ now[10] ^ now[4] ^ now[3];
next[18] = now[13] ^ now[9] ^ now[3] ^ now[2];
next[17] = now[12] ^ now[8] ^ now[2] ^ now[1];
next[16] = now[11] ^ now[7] ^ now[1] ^ now[0];
next[15] = now[15] ^ now[14] ^ now[12] ^ now[10] ^ now[6] ^ now[3] ^ now[0];
next[14] = now[15] ^ now[13] ^ now[12] ^ now[11] ^ now[9] ^ now[5] ^ now[3] ^ now[2];
next[13] = now[14] ^ now[12] ^ now[11] ^ now[10] ^ now[8] ^ now[4] ^ now[2] ^ now[1];
next[12] = now[13] ^ now[11] ^ now[10] ^ now[9] ^ now[7] ^ now[3] ^ now[1] ^ now[0];
next[11] = now[15] ^ now[14] ^ now[10] ^ now[9] ^ now[8] ^ now[6] ^ now[3] ^ now[2] ^ now[0];
next[10] = now[15] ^ now[13] ^ now[12] ^ now[9] ^ now[8] ^ now[7] ^ now[5] ^ now[3] ^ now[2] ^ now[1];
next[9] = now[14] ^ now[12] ^ now[11] ^ now[8] ^ now[7] ^ now[6] ^ now[4] ^ now[2] ^ now[1] ^ now[0];
next[8] = now[15] ^ now[14] ^ now[13] ^ now[12] ^ now[11] ^ now[10] ^ now[7] ^ now[6] ^ now[5] ^ now[1] ^ now[0];
next[7] = now[15] ^ now[13] ^ now[11] ^ now[10] ^ now[9] ^ now[6] ^ now[5] ^ now[4] ^ now[3] ^ now[0];
next[6] = now[15] ^ now[10] ^ now[9] ^ now[8] ^ now[5] ^ now[4] ^ now[2];
next[5] = now[14] ^ now[9] ^ now[8] ^ now[7] ^ now[4] ^ now[3] ^ now[1];
next[4] = now[13] ^ now[8] ^ now[7] ^ now[6] ^ now[3] ^ now[2] ^ now[0];
next[3] = now[15] ^ now[14] ^ now[7] ^ now[6] ^ now[5] ^ now[3] ^ now[2] ^ now[1];
next[2] = now[14] ^ now[13] ^ now[6] ^ now[5] ^ now[4] ^ now[2] ^ now[1] ^ now[0];
next[1] = now[15] ^ now[14] ^ now[13] ^ now[5] ^ now[4] ^ now[1] ^ now[0];
next[0] = now[15] ^ now[13] ^ now[4] ^ now[0];
scrambleFunc = next;
end
endfunction
function [31:0] calculateCRC;
input [31:0] seed;
input [31:0] data;
reg [31:0] crc_bit;
reg [31:0] new_bit;
begin
crc_bit = seed ^ data;
new_bit[31] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[25] ^ crc_bit[24] ^
crc_bit[23] ^ crc_bit[15] ^ crc_bit[11] ^ crc_bit[9] ^ crc_bit[8] ^ crc_bit[5];
new_bit[30] = crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[24] ^ crc_bit[23] ^
crc_bit[22] ^ crc_bit[14] ^ crc_bit[10] ^ crc_bit[8] ^ crc_bit[7] ^ crc_bit[4];
new_bit[29] = crc_bit[31] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[23] ^
crc_bit[22] ^ crc_bit[21] ^ crc_bit[13] ^ crc_bit[9] ^ crc_bit[7] ^ crc_bit[6] ^ crc_bit[3];
new_bit[28] = crc_bit[30] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[24] ^ crc_bit[22] ^
crc_bit[21] ^ crc_bit[20] ^ crc_bit[12] ^ crc_bit[8] ^ crc_bit[6] ^ crc_bit[5] ^ crc_bit[2];
new_bit[27] = crc_bit[29] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[24] ^ crc_bit[23] ^ crc_bit[21] ^
crc_bit[20] ^ crc_bit[19] ^ crc_bit[11] ^ crc_bit[7] ^ crc_bit[5] ^ crc_bit[4] ^ crc_bit[1];
new_bit[26] = crc_bit[31] ^ crc_bit[28] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[24] ^ crc_bit[23] ^ crc_bit[22] ^
crc_bit[20] ^ crc_bit[19] ^ crc_bit[18] ^ crc_bit[10] ^ crc_bit[6] ^ crc_bit[4] ^ crc_bit[3] ^
crc_bit[0];
new_bit[25] = crc_bit[31] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[22] ^ crc_bit[21] ^ crc_bit[19] ^ crc_bit[18] ^
crc_bit[17] ^ crc_bit[15] ^ crc_bit[11] ^ crc_bit[8] ^ crc_bit[3] ^ crc_bit[2];
new_bit[24] = crc_bit[30] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[21] ^ crc_bit[20] ^ crc_bit[18] ^ crc_bit[17] ^
crc_bit[16] ^ crc_bit[14] ^ crc_bit[10] ^ crc_bit[7] ^ crc_bit[2] ^ crc_bit[1];
new_bit[23] = crc_bit[31] ^ crc_bit[29] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[20] ^ crc_bit[19] ^ crc_bit[17] ^
crc_bit[16] ^ crc_bit[15] ^ crc_bit[13] ^ crc_bit[9] ^ crc_bit[6] ^ crc_bit[1] ^ crc_bit[0];
new_bit[22] = crc_bit[31] ^ crc_bit[29] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[24] ^ crc_bit[23] ^ crc_bit[19] ^
crc_bit[18] ^ crc_bit[16] ^ crc_bit[14] ^ crc_bit[12] ^ crc_bit[11] ^ crc_bit[9] ^ crc_bit[0];
new_bit[21] = crc_bit[31] ^ crc_bit[29] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[24] ^ crc_bit[22] ^ crc_bit[18] ^
crc_bit[17] ^ crc_bit[13] ^ crc_bit[10] ^ crc_bit[9] ^ crc_bit[5];
new_bit[20] = crc_bit[30] ^ crc_bit[28] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[23] ^ crc_bit[21] ^ crc_bit[17] ^
crc_bit[16] ^ crc_bit[12] ^ crc_bit[9] ^ crc_bit[8] ^ crc_bit[4];
new_bit[19] = crc_bit[29] ^ crc_bit[27] ^ crc_bit[25] ^ crc_bit[24] ^ crc_bit[22] ^ crc_bit[20] ^ crc_bit[16] ^
crc_bit[15] ^ crc_bit[11] ^ crc_bit[8] ^ crc_bit[7] ^ crc_bit[3];
new_bit[18] = crc_bit[31] ^ crc_bit[28] ^ crc_bit[26] ^ crc_bit[24] ^ crc_bit[23] ^ crc_bit[21] ^ crc_bit[19] ^
crc_bit[15] ^ crc_bit[14] ^ crc_bit[10] ^ crc_bit[7] ^ crc_bit[6] ^ crc_bit[2];
new_bit[17] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[27] ^ crc_bit[25] ^ crc_bit[23] ^ crc_bit[22] ^ crc_bit[20] ^
crc_bit[18] ^ crc_bit[14] ^ crc_bit[13] ^ crc_bit[9] ^ crc_bit[6] ^ crc_bit[5] ^ crc_bit[1];
new_bit[16] = crc_bit[30] ^ crc_bit[29] ^ crc_bit[26] ^ crc_bit[24] ^ crc_bit[22] ^ crc_bit[21] ^ crc_bit[19] ^
crc_bit[17] ^ crc_bit[13] ^ crc_bit[12] ^ crc_bit[8] ^ crc_bit[5] ^ crc_bit[4] ^ crc_bit[0];
new_bit[15] = crc_bit[30] ^ crc_bit[27] ^ crc_bit[24] ^ crc_bit[21] ^ crc_bit[20] ^ crc_bit[18] ^ crc_bit[16] ^
crc_bit[15] ^ crc_bit[12] ^ crc_bit[9] ^ crc_bit[8] ^ crc_bit[7] ^ crc_bit[5] ^ crc_bit[4] ^
crc_bit[3];
new_bit[14] = crc_bit[29] ^ crc_bit[26] ^ crc_bit[23] ^ crc_bit[20] ^ crc_bit[19] ^ crc_bit[17] ^ crc_bit[15] ^
crc_bit[14] ^ crc_bit[11] ^ crc_bit[8] ^ crc_bit[7] ^ crc_bit[6] ^ crc_bit[4] ^ crc_bit[3] ^
crc_bit[2];
new_bit[13] = crc_bit[31] ^ crc_bit[28] ^ crc_bit[25] ^ crc_bit[22] ^ crc_bit[19] ^ crc_bit[18] ^ crc_bit[16] ^
crc_bit[14] ^ crc_bit[13] ^ crc_bit[10] ^ crc_bit[7] ^ crc_bit[6] ^ crc_bit[5] ^ crc_bit[3] ^
crc_bit[2] ^ crc_bit[1];
new_bit[12] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[27] ^ crc_bit[24] ^ crc_bit[21] ^ crc_bit[18] ^ crc_bit[17] ^
crc_bit[15] ^ crc_bit[13] ^ crc_bit[12] ^ crc_bit[9] ^ crc_bit[6] ^ crc_bit[5] ^ crc_bit[4] ^
crc_bit[2] ^ crc_bit[1] ^ crc_bit[0];
new_bit[11] = crc_bit[31] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[24] ^ crc_bit[20] ^
crc_bit[17] ^ crc_bit[16] ^ crc_bit[15] ^ crc_bit[14] ^ crc_bit[12] ^ crc_bit[9] ^ crc_bit[4] ^
crc_bit[3] ^ crc_bit[1] ^ crc_bit[0];
new_bit[10] = crc_bit[31] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[26] ^ crc_bit[19] ^ crc_bit[16] ^ crc_bit[14] ^
crc_bit[13] ^ crc_bit[9] ^ crc_bit[5] ^ crc_bit[3] ^ crc_bit[2] ^ crc_bit[0];
new_bit[9] = crc_bit[29] ^ crc_bit[24] ^ crc_bit[23] ^ crc_bit[18] ^ crc_bit[13] ^ crc_bit[12] ^ crc_bit[11] ^
crc_bit[9] ^ crc_bit[5] ^ crc_bit[4] ^ crc_bit[2] ^ crc_bit[1];
new_bit[8] = crc_bit[31] ^ crc_bit[28] ^ crc_bit[23] ^ crc_bit[22] ^ crc_bit[17] ^ crc_bit[12] ^ crc_bit[11] ^
crc_bit[10] ^ crc_bit[8] ^ crc_bit[4] ^ crc_bit[3] ^ crc_bit[1] ^ crc_bit[0];
new_bit[7] = crc_bit[29] ^ crc_bit[28] ^ crc_bit[25] ^ crc_bit[24] ^ crc_bit[23] ^ crc_bit[22] ^ crc_bit[21] ^
crc_bit[16] ^ crc_bit[15] ^ crc_bit[10] ^ crc_bit[8] ^ crc_bit[7] ^ crc_bit[5] ^ crc_bit[3] ^
crc_bit[2] ^ crc_bit[0];
new_bit[6] = crc_bit[30] ^ crc_bit[29] ^ crc_bit[25] ^ crc_bit[22] ^ crc_bit[21] ^ crc_bit[20] ^ crc_bit[14] ^
crc_bit[11] ^ crc_bit[8] ^ crc_bit[7] ^ crc_bit[6] ^ crc_bit[5] ^ crc_bit[4] ^ crc_bit[2] ^
crc_bit[1];
new_bit[5] = crc_bit[29] ^ crc_bit[28] ^ crc_bit[24] ^ crc_bit[21] ^ crc_bit[20] ^ crc_bit[19] ^ crc_bit[13] ^
crc_bit[10] ^ crc_bit[7] ^ crc_bit[6] ^ crc_bit[5] ^ crc_bit[4] ^ crc_bit[3] ^ crc_bit[1] ^
crc_bit[0];
new_bit[4] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[29] ^ crc_bit[25] ^ crc_bit[24] ^ crc_bit[20] ^ crc_bit[19] ^
crc_bit[18] ^ crc_bit[15] ^ crc_bit[12] ^ crc_bit[11] ^ crc_bit[8] ^ crc_bit[6] ^ crc_bit[4] ^
crc_bit[3] ^ crc_bit[2] ^ crc_bit[0];
new_bit[3] = crc_bit[31] ^ crc_bit[27] ^ crc_bit[25] ^ crc_bit[19] ^ crc_bit[18] ^ crc_bit[17] ^ crc_bit[15] ^
crc_bit[14] ^ crc_bit[10] ^ crc_bit[9] ^ crc_bit[8] ^ crc_bit[7] ^ crc_bit[3] ^ crc_bit[2] ^
crc_bit[1];
new_bit[2] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[26] ^ crc_bit[24] ^ crc_bit[18] ^ crc_bit[17] ^ crc_bit[16] ^
crc_bit[14] ^ crc_bit[13] ^ crc_bit[9] ^ crc_bit[8] ^ crc_bit[7] ^ crc_bit[6] ^ crc_bit[2] ^
crc_bit[1] ^ crc_bit[0];
new_bit[1] = crc_bit[28] ^ crc_bit[27] ^ crc_bit[24] ^ crc_bit[17] ^ crc_bit[16] ^ crc_bit[13] ^ crc_bit[12] ^
crc_bit[11] ^ crc_bit[9] ^ crc_bit[7] ^ crc_bit[6] ^ crc_bit[1] ^ crc_bit[0];
new_bit[0] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[24] ^
crc_bit[16] ^ crc_bit[12] ^ crc_bit[10] ^ crc_bit[9] ^ crc_bit[6] ^ crc_bit[0];
calculateCRC = new_bit;
end
endfunction
// stub TODO
function tranCheckFIS;
input count;
begin
$display("[Device] TRANSPORT: Says the FIS is valid");
tranCheckFIS = 0; // always tell LL the FIS os OK
end
endfunction
// TODO align every 256 dwords!
/*
* Receives data from a host. ~Link Receive FSM
* Correct execution, as it shall be w/o errors from a device side.
*
* Received data is stored in receive_data memory.
* Data is received by a dword // TODO make support for uneven words (16bit each) count
*
* Each data bundle has corresponding "pause" register, stored in a memory 'receive_data_pause'
* It represents a time (in clock cycles), for which the device shall send HOLD primitives after
* current data bundle reception. If after HOLD request data is still coming, consequetive 'pause's are summed up.
* Could be used to test timeout watchdogs of the host.
*
* receive_wait_fifo shows how many clock cycles receiver shall spent before it allows the host to transmit data
*
* Parameters:
* id - reception id, shown in logs
* dmat_index - after this count of received data dwords DMAT primitive would be sent to the line
* status - returns 0 when the host acknowledges the transaction with OK code,
* 1 when with ERR code
* if it's 1, there are 3 options:
* a) Generated CRC is invalid
* b) Scrambler messed up
* c) There is an error in the host
*/
task linkMonitorFIS;
input integer id;
input integer dmat_index;
output integer status;
reg [112:0] rprim;
integer pause;
integer rcv_stop;
integer rcv_ignore;
integer cnt;
reg [31:0] scrambler_value;
reg [31:0] crc;
begin
pause = receive_wait_fifo;
status = 0;
rcv_ignore = 0;
rcv_stop = 0;
crc = 32'h52325032;// crc seed
scrambler_value = {16'hf0f6, 16'h0000}; // scrambler seed
cnt = 0;
// current rprim = XRDY
rprim = "XRDY";
$display("[Device] LINK: Detected incoming transmission");
$display("[Device] LINK: Waiting %h cycles to empty input buffer", pause);
while (pause > 0) begin
// L_RcvWaitFifo
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim != "XRDY") begin
$display("[Device] LINK: Reception terminated by the host, reception id = %d", id);
$finish;
end
@ (posedge clk)
rprim = linkGetPrim(0);
end
// L_RcvChkRdy
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim != "XRDY") begin
$display("[Device] LINK: Reception terminated by the host, reception id = %d", id);
$finish;
end
linkSendPrim("RRDY");
$display("[Device] LINK: Starting the reception");
@ (posedge clk)
rprim = linkGetPrim(0);
while (rprim != "SOF") begin
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim != "XRDY") begin
$display("[Device] LINK: Reception terminated by the host, reception id = %d", id);
$finish;
end
@ (posedge clk)
rprim = linkGetPrim(0);
end
// L_RcvData
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
$display("[Device] LINK: Detected Start of FIS");
linkSendPrim("IP");
@ (posedge clk)
rprim = linkGetPrim(0);
pause = 0;
while (rcv_stop == 0) begin
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim == "SYNC") begin
$display("[Device] LINK: Reception terminated by the host, reception id = %d", id);
$finish;
end
if (rprim == "SCRAP") begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, reception id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
if (rprim == "EOF") begin
$display("[Device] LINK: Detected End of FIS");
rcv_stop = 1;
end
else
if (pause > 0) begin
pause = pause - 1;
linkSendPrim("HOLD");
if (rprim == "HOLDA") begin
$display("[Device] LINK: The pause is acknowledged by the host, chilling out");
rcv_ignore = 1;
end
else begin
$display("[Device] LINK: Asked for a pause");
rcv_ignore = 0;
end
end
else
if (rprim == "HOLD") begin
$display("[Device] LINK: the host asked for a pause, acknowledging");
linkSendPrim("HOLDA");
rcv_ignore = 1;
end
else begin
linkSendPrim("IP");
rcv_ignore = 0;
end
if (rprim == "WTRM") begin
$display("[Device] LINK: Host invalidated the reception, reception id = %d", id);
rcv_stop = 2;
end
if ((rcv_stop == 0) && (rcv_ignore == 0)) begin
if (cnt > 2048) begin
$display("[Device] LINK: Wrong data dwords count received, reception id = %d", id);
$finish;
end
if (cnt >= dmat_index) begin
linkSendPrim("DMAT");
end
scrambler_value = scrambleFunc(scrambler_value[31:16]);
receive_data[cnt] = linkGetData(0) ^ scrambler_value;
$display("[Device] LINK: Got data = %h", receive_data[cnt]);
pause = pause + receive_data_pause[cnt];
crc = calculateCRC(crc, receive_data[cnt]); // running crc. shall be 0
cnt = cnt + 1;
if (cnt <= 2048)
pause = pause + receive_data_pause[cnt];
end
@ (posedge clk)
rprim = linkGetPrim(0);
end
if (cnt < 2) begin
$display("[Device] LINK: Incorrect number of received words");
$finish;
end
$display("[Device] LINK: Running CRC after all data was received = %h", crc);
if (crc != 32'h88c21025) begin // running disparity when data crc matches actual received crc
$display("[Device] LINK: Running CRC check failed");
rcv_stop = 2;
end
else begin
$display("[Device] LINK: Running CRC OK");
end
if (rcv_stop == 1) begin // ordinary path
// L_RcvEOF
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim == "SYNC") begin
$display("[Device] LINK: Reception terminated by the host, reception id = %d", id);
$finish;
end
if ((rprim == "SCRAP") || (rprim == "DATA")) begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, reception id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
@ (posedge clk)
rprim = linkGetPrim(0);
// L_GoodCRC
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim == "SYNC") begin
$display("[Device] LINK: Reception terminated by the host, reception id = %d", id);
$finish;
end
if ((rprim == "SCRAP") || (rprim == "DATA")) begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, reception id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
if (tranCheckFIS(cnt - 1)) begin
rcv_stop = 2;
end
end
if (rcv_stop == 2) begin
// L_BadEnd
status = 1;
linkSendPrim("ERR");
$display("[Device] LINK: Found an error");
end
else begin
// L_GoodEnd
status = 0;
linkSendPrim("OK");
end
@ (posedge clk)
rprim = linkGetPrim(0);
while (rprim != "SYNC") begin
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if ((rprim == "SCRAP") || (rprim == "DATA")) begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, reception id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
@ (posedge clk)
rprim = linkGetPrim(0);
end
// L_IDLE
linkSendPrim("SYNC");
if (status == 1) begin
$display("[Device] LINK: Reception done, errors detected, reception id = %d", id);
end
else
if (status == 0) begin
$display("[Device] LINK: Reception done OK, reception id = %d", id);
end
end
endtask
reg [31:0] transmit_data [2047:0];
reg [31:0] transmit_data_pause [2047:0];
reg [31:0] transmit_crc;
/*
* Transmits data to a host. ~Link Transmit FSM
* Correct execution, as it shall be w/o errors from a device side. (except timeouts and data consistency, see below)
*
* Data to transmit is stored in transmit_data memory.
* Data is transmitted by dwords // TODO make support for uneven words (16bit each) count
*
* It is possible to send incorrect CRC by setting up an input transmit_custom_crc into 1 and desired crc value to transmit_crc
*
* Each data bundle has corresponding "pause" register, stored in a memory 'transmit_data_pause'
* It represents a time (in clock cycles), for which the device shall "wait" for a new portion of data
* Could be used to test timeout watchdogs of the host.
*
* Parameters:
* id - transmission id, shown in logs
* size - how much data to transmit in a FIS
* transmit_custom_crc - see upper
* status - returns 0 when the host acknowledges the transaction with OK code,
* 1 when with ERR code
* if it's 1, there are 3 options:
* a) Generated CRC is invalid
* b) Scrambler messed up
* c) There is an error in the host
*/
task linkTransmitFIS;
input integer id;
input integer size; // dwords count
input integer transmit_custom_crc;
output integer status;
integer pause;
integer cnt;
integer crc;
reg [112:0] rprim;
reg [31:0] scrambler_value;
begin
crc = 32'h52325032;// crc seed
scrambler_value = {16'hf0f6, 16'h0000}; // scrambler seed
// tell everyone we need a bus to transmit data
transmit_lock = 1;
// DL_SendChkRdy
linkSendPrim("XRDY");
$display("[Device] LINK: Started outcoming transmission");
rprim = linkGetPrim(0);
$display("[Device] LINK: Waiting for acknowledgement");
while (rprim != "RRDY") begin
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
@ (posedge clk)
rprim = linkGetPrim(0);
end
// L_SendSOF
linkSendPrim("SOF");
$display("[Device] LINK: Sending Start of FIS");
@ (posedge clk)
rprim = linkGetPrim(0);
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim == "SYNC") begin
$display("[Device] LINK: Transmission terminated by the host, transmission id = %d", id);
$finish;
end
if ((rprim == "SCRAP") || (rprim == "DATA")) begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, transmission id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
// L_SendData + L_RcvrHold + L_SendHold
cnt = 0;
pause = transmit_data_pause[0];
while (cnt < size) begin
scrambler_value = scrambleFunc(scrambler_value[31:16]);
// $display("[Device] LINK: Scrambler = %h", scrambler_value);
linkSendData(transmit_data[cnt] ^ scrambler_value);
crc = calculateCRC(crc, transmit_data[cnt]);
$display("[Device] LINK: Sent data = %h", transmit_data[cnt]);
@ (posedge clk)
rprim = linkGetPrim(0);
if (rprim == "SYNC") begin
$display("[Device] LINK: Transmission terminated by the host, transmission id = %d", id);
$finish;
end
if ((rprim == "SCRAP") || (rprim == "DATA")) begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, transmission id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
else
if (rprim == "DMAT") begin
$display("[Device] LINK: Transmission terminated by the host via DMAT, transmission id = %d", id);
$finish;
end
else
if (pause > 0) begin
$display("[Device] LINK: Transmission is paused");
linkSendPrim("HOLD");
pause = pause - 1;
end
else
if (rprim == "HOLD") begin
$display("[Device] LINK: The host asked for a pause, acknowledging");
linkSendPrim("HOLDA");
end
else begin
cnt = cnt + 1;
if (cnt < size)
pause = transmit_data_pause[cnt];
end
end
// L_SendCRC
scrambler_value = scrambleFunc(scrambler_value[31:16]);
if (transmit_custom_crc != 0) begin
crc = transmit_crc;
end
linkSendData(crc ^ scrambler_value);
$display("[Device] LINK: Sent crc = %h", crc);
@ (posedge clk)
rprim = linkGetPrim(0);
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim == "SYNC") begin
$display("[Device] LINK: Transmission terminated by the host, transmission id = %d", id);
$finish;
end
if ((rprim == "SCRAP") || (rprim == "DATA")) begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, transmission id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
// L_SendEOF
linkSendPrim("EOF");
$display("[Device] LINK: Sent End of FIS");
@ (posedge clk)
rprim = linkGetPrim(0);
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim == "SYNC") begin
$display("[Device] LINK: Transmission terminated by the host, transmission id = %d", id);
$finish;
end
if ((rprim == "SCRAP") || (rprim == "DATA")) begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, transmission id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
// L_Wait
linkSendPrim("WTRM");
$display("[Device] LINK: Waiting for a response from the host");
@ (posedge clk)
rprim = linkGetPrim(0);
status = 0;
while ((rprim != "OK") && (status == 0)) begin
if (~phy_ready) begin
$display("[Device] LINK: Unexpected line disconnect");
$finish;
end
if (rprim == "SYNC") begin
$display("[Device] LINK: Transmission terminated by the host, transmission id = %d", id);
$finish;
end
if ((rprim == "SCRAP") || (rprim == "DATA")) begin
$display("[Device] LINK: Bad primitives from the host, is data = %h, data = %h, transmission id = %d", linkIsData(0), linkGetData(0), id);
$finish;
end
if (rprim == "ERR") begin
$display("[Device] LINK: Host invalidated the transmission, transmission id = %d", id);
status = 1;
end
@ (posedge clk)
rprim = linkGetPrim(0);
end
if (status == 0)
$display("[Device] LINK: Transmission done OK, id = %d", id);
if (status == 1)
$display("[Device] LINK: Transmission done with ERRORs, id = %d", id);
// L_IDLE
linkSendPrim("SYNC");
end
endtask
// checks, if it is data coming from the host
function [0:0] linkIsData;
input dummy;
begin
if (|phy2dev_charisk)
linkIsData = 1;
else
linkIsData = 0;
end
endfunction
// obvious
function [31:0] linkGetData;
// TODO non-even word count
input dummy;
begin
linkGetData = phy2dev_data;
end
endfunction
/*
* Returns current primitive at the outputs of phy level
* Return value is a string containing its name!
*/
function [112:0] linkGetPrim;
input integer dummy;
reg [112:0] type;
begin
if (~|phy2dev_charisk) begin
type = "DATA";
end
else
if (phy2dev_charisk == 4'h1) begin
case (phy2dev_data)
PRIM_SYNCP:
type = "SYNC";
PRIM_ALIGNP:
type = "ALIGN";
PRIM_XRDYP:
type = "XRDY";
PRIM_SOFP:
type = "SOF";
PRIM_HOLDAP:
type = "HOLDA";
PRIM_HOLDP:
type = "HOLD";
PRIM_EOFP:
type = "EOF";
PRIM_WTRMP:
type = "WTRM";
PRIM_RRDYP:
type = "RRDY";
PRIM_IPP:
type = "IP";
PRIM_DMATP:
type = "DMAT";
PRIM_OKP:
type = "OK";
PRIM_ERRP:
type = "ERR";
default:
type = "SCRAP";
endcase
end
else begin
type = "SCRAP";
end
linkGetPrim = type;
end
endfunction
/*
* Sets some data to phy inputs
* input is a data dword
*/
task linkSendData;
input [31:0] data;
begin
dev2phy_data <= data;
dev2phy_isk <= 4'h0;
end
endtask
/*
* Set a desired primitive to phy inputs
* input is a string containing its name!
*/
task linkSendPrim;
input [112:0] type;
begin
case (type)
"SYNC":
begin
dev2phy_data <= PRIM_SYNCP;
dev2phy_isk <= 4'h1;
end
"ALIGN":
begin
dev2phy_data <= PRIM_ALIGNP;
dev2phy_isk <= 4'h1;
end
"XRDY":
begin
dev2phy_data <= PRIM_XRDYP;
dev2phy_isk <= 4'h1;
end
"SOF":
begin
dev2phy_data <= PRIM_SOFP;
dev2phy_isk <= 4'h1;
end
"HOLDA":
begin
dev2phy_data <= PRIM_HOLDAP;
dev2phy_isk <= 4'h1;
end
"HOLD":
begin
dev2phy_data <= PRIM_HOLDP;
dev2phy_isk <= 4'h1;
end
"EOF":
begin
dev2phy_data <= PRIM_EOFP;
dev2phy_isk <= 4'h1;
end
"WTRM":
begin
dev2phy_data <= PRIM_WTRMP;
dev2phy_isk <= 4'h1;
end
"RRDY":
begin
dev2phy_data <= PRIM_RRDYP;
dev2phy_isk <= 4'h1;
end
"IP":
begin
dev2phy_data <= PRIM_IPP;
dev2phy_isk <= 4'h1;
end
"DMAT":
begin
dev2phy_data <= PRIM_DMATP;
dev2phy_isk <= 4'h1;
end
"OK":
begin
dev2phy_data <= PRIM_OKP;
dev2phy_isk <= 4'h1;
end
"ERR":
begin
dev2phy_data <= PRIM_ERRP;
dev2phy_isk <= 4'h1;
end
default:
begin
dev2phy_data <= PRIM_SYNCP;
dev2phy_isk <= 4'h1;
end
endcase
end
endtask
endmodule
/*******************************************************************************
* Module: sata_phy
* Date: 2015-07-11
* Author: Alexey
* Description: phy-level, including oob, clock generation and GTXE2
*
* Copyright (c) 2015 Elphel, Inc.
* sata_phy.v 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.
*
* sata_phy.v file 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/> .
*******************************************************************************/
`include "oob_dev.v"
module sata_phy_dev(
// initial reset, resets PLL. After pll is locked, an internal sata reset is generated.
input wire extrst,
// sata clk, generated in pll as usrclk2
output wire clk,
output wire rst,
// state
output wire phy_ready,
// top-level ifaces
// ref clk from an external source, shall be connected to pads
input wire extclk_p,
input wire extclk_n,
// sata link data pins
output wire txp_out,
output wire txn_out,
input wire rxp_in,
input wire rxn_in,
// to link layer
output wire [31:0] ll_data_out,
output wire [3:0] ll_charisk_out,
output wire [3:0] ll_err_out, // TODO!!!
// from link layer
input wire [31:0] ll_data_in,
input wire [3:0] ll_charisk_in
);
parameter CHIPSCOPE = "FALSE";
wire [31:0] txdata;
wire [31:0] txdata_oob;
wire [3:0] txcharisk;
wire [3:0] txcharisk_oob;
wire [63:0] rxdata;
wire [3:0] rxcharisk;
wire [31:0] rxdata_out;
wire [31:0] txdata_in;
wire [3:0] txcharisk_in;
wire [3:0] rxcharisk_out;
wire rxcomwakedet;
wire rxcominitdet;
wire cplllock;
wire txcominit;
wire txcomwake;
wire rxreset;
wire rxelecidle;
wire txelecidle;
wire rxbyteisaligned;
wire gtx_ready;
assign txdata = phy_ready ? ll_data_in : txdata_oob;
assign txcharisk = phy_ready ? ll_charisk_in : txcharisk_oob;
assign ll_err_out = 4'h0;
assign ll_charisk_out = rxcharisk[3:0];
assign ll_data_out = rxdata;
oob_dev oob_dev(
// sata clk = usrclk2
.clk (clk),
// reset oob
.rst (rst),
// gtx is ready = all resets are done
.gtx_ready (gtx_ready),
// oob responces
.rxcominitdet_in (rxcominitdet),
.rxcomwakedet_in (rxcomwakedet),
.rxelecidle_in (rxelecidle),
// oob issues
.txcominit (txcominit),
.txcomwake (txcomwake),
.txelecidle (txelecidle),
// output data stream to gtx
.txdata_out (txdata_oob),
.txcharisk_out (txcharisk_oob),
// input data from gtx
.rxdata_in (rxdata[31:0]),
.rxcharisk_in (rxcharisk[3:0]),
// shows if channel is ready
.link_up (phy_ready)
);
wire cplllockdetclk; // TODO
wire drpclk; // TODO
wire cpllreset;
wire gtrefclk;
wire rxresetdone;
wire txresetdone;
wire txreset;
wire txuserrdy;
wire rxuserrdy;
wire txusrclk;
wire txusrclk2;
wire rxusrclk;
wire rxusrclk2;
wire txp;
wire txn;
wire rxp;
wire rxn;
wire txoutclk;
wire txpmareset_done;
wire rxeyereset_done;
// tx reset sequence; waves @ ug476 p67
localparam TXPMARESET_TIME = 5'h1;
reg [2:0] txpmareset_cnt;
assign txpmareset_done = txpmareset_cnt == TXPMARESET_TIME;
always @ (posedge gtrefclk)
txpmareset_cnt <= txreset ? 3'h0 : txpmareset_done ? txpmareset_cnt : txpmareset_cnt + 1'b1;
// rx reset sequence; waves @ ug476 p77
localparam RXPMARESET_TIME = 5'h11;
localparam RXCDRPHRESET_TIME = 5'h1;
localparam RXCDRFREQRESET_TIME = 5'h1;
localparam RXDFELPMRESET_TIME = 7'hf;
localparam RXISCANRESET_TIME = 5'h1;
localparam RXEYERESET_TIME = 7'h0 + RXPMARESET_TIME + RXCDRPHRESET_TIME + RXCDRFREQRESET_TIME + RXDFELPMRESET_TIME + RXISCANRESET_TIME;
reg [6:0] rxeyereset_cnt;
assign rxeyereset_done = rxeyereset_cnt == RXEYERESET_TIME;
always @ (posedge gtrefclk)
rxeyereset_cnt <= rxreset ? 3'h0 : rxeyereset_done ? rxeyereset_cnt : rxeyereset_cnt + 1'b1;
/*
* Resets
*/
wire usrpll_locked;
assign cpllreset = extrst;
assign rxreset = ~cplllock | cpllreset;
assign txreset = ~cplllock | cpllreset;
assign rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done;
assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done;
assign gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone;
// generate internal reset after a clock is established
// !!!ATTENTION!!!
// async rst block
reg [7:0] rst_timer;
reg rst_r;
localparam [7:0] RST_TIMER_LIMIT = 8'b1000;
always @ (posedge clk or posedge extrst)
rst_timer <= extrst | ~cplllock | ~usrpll_locked ? 8'h0 : rst_timer == RST_TIMER_LIMIT ? rst_timer : rst_timer + 1'b1;
assign rst = rst_r;
always @ (posedge clk or posedge extrst)
rst_r <= extrst | ~|rst_timer ? 1'b0 : rst_timer[3] ? 1'b0 : 1'b1;
/*
* USRCLKs generation. USRCLK @ 150MHz, same as TXOUTCLK; USRCLK2 @ 75Mhz -> sata_clk === sclk
* It's recommended to use MMCM instead of PLL, whatever
*/
wire usrpll_fb_clk;
wire usrclk;
wire usrclk2;
assign txusrclk = usrclk;
assign txusrclk2 = usrclk2;
assign rxusrclk = usrclk;
assign rxusrclk2 = usrclk2;
PLLE2_ADV #(
.BANDWIDTH ("OPTIMIZED"),
.CLKFBOUT_MULT (8),
.CLKFBOUT_PHASE (0.000),
.CLKIN1_PERIOD (6.666),
.CLKIN2_PERIOD (0.000),
.CLKOUT0_DIVIDE (8),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT0_PHASE (0.000),
.CLKOUT1_DIVIDE (16),
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT1_PHASE (0.000),
/* .CLKOUT2_DIVIDE = 1,
.CLKOUT2_DUTY_CYCLE = 0.500,
.CLKOUT2_PHASE = 0.000,
.CLKOUT3_DIVIDE = 1,
.CLKOUT3_DUTY_CYCLE = 0.500,
.CLKOUT3_PHASE = 0.000,
.CLKOUT4_DIVIDE = 1,
.CLKOUT4_DUTY_CYCLE = 0.500,
.CLKOUT4_PHASE = 0.000,
.CLKOUT5_DIVIDE = 1,
.CLKOUT5_DUTY_CYCLE = 0.500,
.CLKOUT5_PHASE = 0.000,*/
.COMPENSATION ("ZHOLD"),
.DIVCLK_DIVIDE (1),
.IS_CLKINSEL_INVERTED (1'b0),
.IS_PWRDWN_INVERTED (1'b0),
.IS_RST_INVERTED (1'b0),
.REF_JITTER1 (0.010),
.REF_JITTER2 (0.010),
.STARTUP_WAIT ("FALSE")
)
usrclk_pll(
.CLKFBOUT (usrpll_fb_clk),
.CLKOUT0 (usrclk),
.CLKOUT1 (usrclk2),
.CLKOUT2 (),
.CLKOUT3 (),
.CLKOUT4 (),
.CLKOUT5 (),
.DO (),
.DRDY (),
.LOCKED (usrpll_locked),
.CLKFBIN (usrpll_fb_clk),
.CLKIN1 (txoutclk),
.CLKIN2 (1'b0),
.CLKINSEL (1'b1),
.DADDR (7'h0),
.DCLK (drpclk),
.DEN (1'b0),
.DI (16'h0),
.DWE (1'b0),
.PWRDWN (1'b0),
.RST (~cplllock)
);
/*
* Padding for an external input clock @ 150 MHz
*/
localparam [1:0] CLKSWING_CFG = 2'b11;
IBUFDS_GTE2 #(
.CLKRCV_TRST ("TRUE"),
.CLKCM_CFG ("TRUE"),
.CLKSWING_CFG (CLKSWING_CFG)
)
ext_clock_buf(
.I (extclk_p),
.IB (extclk_n),
.CEB (1'b0),
.O (gtrefclk),
.ODIV2 ()
);
GTXE2_CHANNEL #(
.SIM_RECEIVER_DETECT_PASS ("TRUE"),
.SIM_TX_EIDLE_DRIVE_LEVEL ("X"),
.SIM_RESET_SPEEDUP ("FALSE"),
.SIM_CPLLREFCLK_SEL (3'b001),
.SIM_VERSION ("4.0"),
.ALIGN_COMMA_DOUBLE ("FALSE"),
.ALIGN_COMMA_ENABLE (10'b1111111111),
.ALIGN_COMMA_WORD (1),
.ALIGN_MCOMMA_DET ("TRUE"),
.ALIGN_MCOMMA_VALUE (10'b1010000011),
.ALIGN_PCOMMA_DET ("TRUE"),
.ALIGN_PCOMMA_VALUE (10'b0101111100),
.SHOW_REALIGN_COMMA ("TRUE"),
.RXSLIDE_AUTO_WAIT (7),
.RXSLIDE_MODE ("OFF"),
.RX_SIG_VALID_DLY (10),
.RX_DISPERR_SEQ_MATCH ("TRUE"),
.DEC_MCOMMA_DETECT ("TRUE"),
.DEC_PCOMMA_DETECT ("TRUE"),
.DEC_VALID_COMMA_ONLY ("FALSE"),
.CBCC_DATA_SOURCE_SEL ("DECODED"),
.CLK_COR_SEQ_2_USE ("FALSE"),
.CLK_COR_KEEP_IDLE ("FALSE"),
.CLK_COR_MAX_LAT (9),
.CLK_COR_MIN_LAT (7),
.CLK_COR_PRECEDENCE ("TRUE"),
.CLK_COR_REPEAT_WAIT (0),
.CLK_COR_SEQ_LEN (1),
.CLK_COR_SEQ_1_ENABLE (4'b1111),
.CLK_COR_SEQ_1_1 (10'b0100000000),
.CLK_COR_SEQ_1_2 (10'b0000000000),
.CLK_COR_SEQ_1_3 (10'b0000000000),
.CLK_COR_SEQ_1_4 (10'b0000000000),
.CLK_CORRECT_USE ("FALSE"),
.CLK_COR_SEQ_2_ENABLE (4'b1111),
.CLK_COR_SEQ_2_1 (10'b0100000000),
.CLK_COR_SEQ_2_2 (10'b0000000000),
.CLK_COR_SEQ_2_3 (10'b0000000000),
.CLK_COR_SEQ_2_4 (10'b0000000000),
.CHAN_BOND_KEEP_ALIGN ("FALSE"),
.CHAN_BOND_MAX_SKEW (1),
.CHAN_BOND_SEQ_LEN (1),
.CHAN_BOND_SEQ_1_1 (10'b0000000000),
.CHAN_BOND_SEQ_1_2 (10'b0000000000),
.CHAN_BOND_SEQ_1_3 (10'b0000000000),
.CHAN_BOND_SEQ_1_4 (10'b0000000000),
.CHAN_BOND_SEQ_1_ENABLE (4'b1111),
.CHAN_BOND_SEQ_2_1 (10'b0000000000),
.CHAN_BOND_SEQ_2_2 (10'b0000000000),
.CHAN_BOND_SEQ_2_3 (10'b0000000000),
.CHAN_BOND_SEQ_2_4 (10'b0000000000),
.CHAN_BOND_SEQ_2_ENABLE (4'b1111),
.CHAN_BOND_SEQ_2_USE ("FALSE"),
.FTS_DESKEW_SEQ_ENABLE (4'b1111),
.FTS_LANE_DESKEW_CFG (4'b1111),
.FTS_LANE_DESKEW_EN ("FALSE"),
.ES_CONTROL (6'b000000),
.ES_ERRDET_EN ("FALSE"),
.ES_EYE_SCAN_EN ("TRUE"),
.ES_HORZ_OFFSET (12'h000),
.ES_PMA_CFG (10'b0000000000),
.ES_PRESCALE (5'b00000),
.ES_QUALIFIER (80'h00000000000000000000),
.ES_QUAL_MASK (80'h00000000000000000000),
.ES_SDATA_MASK (80'h00000000000000000000),
.ES_VERT_OFFSET (9'b000000000),
.RX_DATA_WIDTH (20),
.OUTREFCLK_SEL_INV (2'b11),
.PMA_RSV (32'h00018480),
.PMA_RSV2 (16'h2050),
.PMA_RSV3 (2'b00),
.PMA_RSV4 (32'h00000000),
.RX_BIAS_CFG (12'b000000000100),
.DMONITOR_CFG (24'h000A00),
.RX_CM_SEL (2'b11),
.RX_CM_TRIM (3'b010),
.RX_DEBUG_CFG (12'b000000000000),
.RX_OS_CFG (13'b0000010000000),
.TERM_RCAL_CFG (5'b10000),
.TERM_RCAL_OVRD (1'b0),
.TST_RSV (32'h00000000),
.RX_CLK25_DIV (6),
.TX_CLK25_DIV (6),
.UCODEER_CLR (1'b0),
.PCS_PCIE_EN ("FALSE"),
.PCS_RSVD_ATTR (48'h0100),
.RXBUF_ADDR_MODE ("FAST"),
.RXBUF_EIDLE_HI_CNT (4'b1000),
.RXBUF_EIDLE_LO_CNT (4'b0000),
.RXBUF_EN ("TRUE"),
.RX_BUFFER_CFG (6'b000000),
.RXBUF_RESET_ON_CB_CHANGE ("TRUE"),
.RXBUF_RESET_ON_COMMAALIGN ("FALSE"),
.RXBUF_RESET_ON_EIDLE ("FALSE"),
.RXBUF_RESET_ON_RATE_CHANGE ("TRUE"),
.RXBUFRESET_TIME (5'b00001),
.RXBUF_THRESH_OVFLW (61),
.RXBUF_THRESH_OVRD ("FALSE"),
.RXBUF_THRESH_UNDFLW (4),
.RXDLY_CFG (16'h001F),
.RXDLY_LCFG (9'h030),
.RXDLY_TAP_CFG (16'h0000),
.RXPH_CFG (24'h000000),
.RXPHDLY_CFG (24'h084020),
.RXPH_MONITOR_SEL (5'b00000),
.RX_XCLK_SEL ("RXREC"),
.RX_DDI_SEL (6'b000000),
.RX_DEFER_RESET_BUF_EN ("TRUE"),
.RXCDR_CFG (72'h03000023ff10200020),
.RXCDR_FR_RESET_ON_EIDLE (1'b0),
.RXCDR_HOLD_DURING_EIDLE (1'b0),
.RXCDR_PH_RESET_ON_EIDLE (1'b0),
.RXCDR_LOCK_CFG (6'b010101),
.RXCDRFREQRESET_TIME (RXCDRFREQRESET_TIME),
.RXCDRPHRESET_TIME (RXCDRPHRESET_TIME),
.RXISCANRESET_TIME (RXISCANRESET_TIME),
.RXPCSRESET_TIME (5'b00001),
.RXPMARESET_TIME (RXPMARESET_TIME),
.RXOOB_CFG (7'b0000110),
.RXGEARBOX_EN ("FALSE"),
.GEARBOX_MODE (3'b000),
.RXPRBS_ERR_LOOPBACK (1'b0),
.PD_TRANS_TIME_FROM_P2 (12'h03c),
.PD_TRANS_TIME_NONE_P2 (8'h3c),
.PD_TRANS_TIME_TO_P2 (8'h64),
.SAS_MAX_COM (64),
.SAS_MIN_COM (36),
.SATA_BURST_SEQ_LEN (4'b0111),
.SATA_BURST_VAL (3'b110),
.SATA_EIDLE_VAL (3'b110),
.SATA_MAX_BURST (8),
.SATA_MAX_INIT (21),
.SATA_MAX_WAKE (7),
.SATA_MIN_BURST (4),
.SATA_MIN_INIT (12),
.SATA_MIN_WAKE (4),
.TRANS_TIME_RATE (8'h0E),
.TXBUF_EN ("TRUE"),
.TXBUF_RESET_ON_RATE_CHANGE ("TRUE"),
.TXDLY_CFG (16'h001F),
.TXDLY_LCFG (9'h030),
.TXDLY_TAP_CFG (16'h0000),
.TXPH_CFG (16'h0780),
.TXPHDLY_CFG (24'h084020),
.TXPH_MONITOR_SEL (5'b00000),
.TX_XCLK_SEL ("TXOUT"),
.TX_DATA_WIDTH (40),
.TX_DEEMPH0 (5'b00000),
.TX_DEEMPH1 (5'b00000),
.TX_EIDLE_ASSERT_DELAY (3'b110),
.TX_EIDLE_DEASSERT_DELAY (3'b100),
.TX_LOOPBACK_DRIVE_HIZ ("FALSE"),
.TX_MAINCURSOR_SEL (1'b0),
.TX_DRIVE_MODE ("DIRECT"),
.TX_MARGIN_FULL_0 (7'b1001110),
.TX_MARGIN_FULL_1 (7'b1001001),
.TX_MARGIN_FULL_2 (7'b1000101),
.TX_MARGIN_FULL_3 (7'b1000010),
.TX_MARGIN_FULL_4 (7'b1000000),
.TX_MARGIN_LOW_0 (7'b1000110),
.TX_MARGIN_LOW_1 (7'b1000100),
.TX_MARGIN_LOW_2 (7'b1000010),
.TX_MARGIN_LOW_3 (7'b1000000),
.TX_MARGIN_LOW_4 (7'b1000000),
.TXGEARBOX_EN ("FALSE"),
.TXPCSRESET_TIME (5'b00001),
.TXPMARESET_TIME (TXPMARESET_TIME),
.TX_RXDETECT_CFG (14'h1832),
.TX_RXDETECT_REF (3'b100),
.CPLL_CFG (24'hBC07DC),
.CPLL_FBDIV (4),
.CPLL_FBDIV_45 (5),
.CPLL_INIT_CFG (24'h00001E),
.CPLL_LOCK_CFG (16'h01E8),
.CPLL_REFCLK_DIV (1),
.RXOUT_DIV (2),
.TXOUT_DIV (2),
.SATA_CPLL_CFG ("VCO_3000MHZ"),
.RXDFELPMRESET_TIME (RXDFELPMRESET_TIME),
.RXLPM_HF_CFG (14'b00000011110000),
.RXLPM_LF_CFG (14'b00000011110000),
.RX_DFE_GAIN_CFG (23'h020FEA),
.RX_DFE_H2_CFG (12'b000000000000),
.RX_DFE_H3_CFG (12'b000001000000),
.RX_DFE_H4_CFG (11'b00011110000),
.RX_DFE_H5_CFG (11'b00011100000),
.RX_DFE_KL_CFG (13'b0000011111110),
.RX_DFE_LPM_CFG (16'h0954),
.RX_DFE_LPM_HOLD_DURING_EIDLE (1'b0),
.RX_DFE_UT_CFG (17'b10001111000000000),
.RX_DFE_VP_CFG (17'b00011111100000011),
.RX_CLKMUX_PD (1'b1),
.TX_CLKMUX_PD (1'b1),
.RX_INT_DATAWIDTH (0),
.TX_INT_DATAWIDTH (0),
.TX_QPI_STATUS_EN (1'b0),
.RX_DFE_KL_CFG2 (32'h301148AC),
.RX_DFE_XYD_CFG (13'b0000000000000),
.TX_PREDRIVER_MODE (1'b0)
)
gtx(
.CPLLFBCLKLOST (),
.CPLLLOCK (cplllock),
.CPLLLOCKDETCLK (cplllockdetclk),
.CPLLLOCKEN (1'b1),
.CPLLPD (1'b0),
.CPLLREFCLKLOST (),
.CPLLREFCLKSEL (3'b001),
.CPLLRESET (cpllreset),
.GTRSVD (1'b0),
.PCSRSVDIN (1'b0),
.PCSRSVDIN2 (1'b0),
.PMARSVDIN (1'b0),
.PMARSVDIN2 (1'b0),
.TSTIN (1'b1),
.TSTOUT (),
.CLKRSVD (4'b0000),
.GTGREFCLK (1'b0),
.GTNORTHREFCLK0 (1'b0),
.GTNORTHREFCLK1 (1'b0),
.GTREFCLK0 (gtrefclk),
.GTREFCLK1 (1'b0),
.GTSOUTHREFCLK0 (1'b0),
.GTSOUTHREFCLK1 (1'b0),
.DRPADDR (9'b0),
.DRPCLK (drpclk),
.DRPDI (16'b0),
.DRPDO (),
.DRPEN (1'b0),
.DRPRDY (),
.DRPWE (1'b0),
.GTREFCLKMONITOR (),
.QPLLCLK (gtrefclk),
.QPLLREFCLK (gtrefclk),
.RXSYSCLKSEL (2'b00),
.TXSYSCLKSEL (2'b00),
.DMONITOROUT (),
.TX8B10BEN (1'b1),
.LOOPBACK (3'd0),
.PHYSTATUS (),
.RXRATE (3'd0),
.RXVALID (),
.RXPD (2'b00),
.TXPD (2'b00),
.SETERRSTATUS (1'b0),
.EYESCANRESET (1'b0),//rxreset), // p78
.RXUSERRDY (rxuserrdy),
.EYESCANDATAERROR (),
.EYESCANMODE (1'b0),
.EYESCANTRIGGER (1'b0),
.RXCDRFREQRESET (1'b0),
.RXCDRHOLD (1'b0),
.RXCDRLOCK (),
.RXCDROVRDEN (1'b0),
.RXCDRRESET (1'b0),
.RXCDRRESETRSV (1'b0),
.RXCLKCORCNT (),
.RX8B10BEN (1'b1),
.RXUSRCLK (rxusrclk),
.RXUSRCLK2 (rxusrclk2),
.RXDATA (rxdata),
.RXPRBSERR (),
.RXPRBSSEL (3'd0),
.RXPRBSCNTRESET (1'b0),
.RXDFEXYDEN (1'b1),
.RXDFEXYDHOLD (1'b0),
.RXDFEXYDOVRDEN (1'b0),
.RXDISPERR (),
.RXNOTINTABLE (),
.GTXRXP (rxp),
.GTXRXN (rxn),
.RXBUFRESET (1'b0),
.RXBUFSTATUS (),
.RXDDIEN (1'b0),
.RXDLYBYPASS (1'b1),
.RXDLYEN (1'b0),
.RXDLYOVRDEN (1'b0),
.RXDLYSRESET (1'b0),
.RXDLYSRESETDONE (),
.RXPHALIGN (1'b0),
.RXPHALIGNDONE (),
.RXPHALIGNEN (1'b0),
.RXPHDLYPD (1'b0),
.RXPHDLYRESET (1'b0),
.RXPHMONITOR (),
.RXPHOVRDEN (1'b0),
.RXPHSLIPMONITOR (),
.RXSTATUS (),
.RXBYTEISALIGNED (rxbyteisaligned),
.RXBYTEREALIGN (),
.RXCOMMADET (),
.RXCOMMADETEN (1'b1),
.RXMCOMMAALIGNEN (1'b1),
.RXPCOMMAALIGNEN (1'b1),
.RXCHANBONDSEQ (),
.RXCHBONDEN (1'b0),
.RXCHBONDLEVEL (3'd0),
.RXCHBONDMASTER (1'b0),
.RXCHBONDO (),
.RXCHBONDSLAVE (1'b0),
.RXCHANISALIGNED (),
.RXCHANREALIGN (),
.RXLPMHFHOLD (1'b0),
.RXLPMHFOVRDEN (1'b0),
.RXLPMLFHOLD (1'b0),
.RXDFEAGCHOLD (1'b0),
.RXDFEAGCOVRDEN (1'b0),
.RXDFECM1EN (1'b0),
.RXDFELFHOLD (1'b0),
.RXDFELFOVRDEN (1'b1),
.RXDFELPMRESET (rxreset),
.RXDFETAP2HOLD (1'b0),
.RXDFETAP2OVRDEN (1'b0),
.RXDFETAP3HOLD (1'b0),
.RXDFETAP3OVRDEN (1'b0),
.RXDFETAP4HOLD (1'b0),
.RXDFETAP4OVRDEN (1'b0),
.RXDFETAP5HOLD (1'b0),
.RXDFETAP5OVRDEN (1'b0),
.RXDFEUTHOLD (1'b0),
.RXDFEUTOVRDEN (1'b0),
.RXDFEVPHOLD (1'b0),
.RXDFEVPOVRDEN (1'b0),
// .RXDFEVSEN (1'b0),
.RXLPMLFKLOVRDEN (1'b0),
.RXMONITOROUT (),
.RXMONITORSEL (2'b01),
.RXOSHOLD (1'b0),
.RXOSOVRDEN (1'b0),
.RXRATEDONE (),
.RXOUTCLK (),
.RXOUTCLKFABRIC (),
.RXOUTCLKPCS (),
.RXOUTCLKSEL (3'b010),
.RXDATAVALID (),
.RXHEADER (),
.RXHEADERVALID (),
.RXSTARTOFSEQ (),
.RXGEARBOXSLIP (1'b0),
.GTRXRESET (rxreset),
.RXOOBRESET (1'b0),
.RXPCSRESET (1'b0),
.RXPMARESET (1'b0),//rxreset), // p78
.RXLPMEN (1'b0),
.RXCOMSASDET (),
.RXCOMWAKEDET (rxcomwakedet),
.RXCOMINITDET (rxcominitdet),
.RXELECIDLE (rxelecidle),
.RXELECIDLEMODE (2'b00),
.RXPOLARITY (1'b0),
.RXSLIDE (1'b0),
.RXCHARISCOMMA (),
.RXCHARISK (rxcharisk),
.RXCHBONDI (5'b00000),
.RXRESETDONE (rxresetdone),
.RXQPIEN (1'b0),
.RXQPISENN (),
.RXQPISENP (),
.TXPHDLYTSTCLK (1'b0),
.TXPOSTCURSOR (5'b00000),
.TXPOSTCURSORINV (1'b0),
.TXPRECURSOR (5'd0),
.TXPRECURSORINV (1'b0),
.TXQPIBIASEN (1'b0),
.TXQPISTRONGPDOWN (1'b0),
.TXQPIWEAKPUP (1'b0),
.CFGRESET (1'b0),
.GTTXRESET (txreset),
.PCSRSVDOUT (),
.TXUSERRDY (txuserrdy),
.GTRESETSEL (1'b0),
.RESETOVRD (1'b0),
.TXCHARDISPMODE (8'd0),
.TXCHARDISPVAL (8'd0),
.TXUSRCLK (txusrclk),
.TXUSRCLK2 (txusrclk2),
.TXELECIDLE (txelecidle),
.TXMARGIN (3'd0),
.TXRATE (3'd0),
.TXSWING (1'b0),
.TXPRBSFORCEERR (1'b0),
.TXDLYBYPASS (1'b1),
.TXDLYEN (1'b0),
.TXDLYHOLD (1'b0),
.TXDLYOVRDEN (1'b0),
.TXDLYSRESET (1'b0),
.TXDLYSRESETDONE (),
.TXDLYUPDOWN (1'b0),
.TXPHALIGN (1'b0),
.TXPHALIGNDONE (),
.TXPHALIGNEN (1'b0),
.TXPHDLYPD (1'b0),
.TXPHDLYRESET (1'b0),
.TXPHINIT (1'b0),
.TXPHINITDONE (),
.TXPHOVRDEN (1'b0),
.TXBUFSTATUS (),
.TXBUFDIFFCTRL (3'b100),
.TXDEEMPH (1'b0),
.TXDIFFCTRL (4'b1000),
.TXDIFFPD (1'b0),
.TXINHIBIT (1'b0),
.TXMAINCURSOR (7'b0000000),
.TXPISOPD (1'b0),
.TXDATA ({32'h0, txdata}),
.GTXTXN (txn),
.GTXTXP (txp),
.TXOUTCLK (txoutclk),
.TXOUTCLKFABRIC (),
.TXOUTCLKPCS (),
.TXOUTCLKSEL (3'b010),
.TXRATEDONE (),
.TXCHARISK ({4'b0, txcharisk}),
.TXGEARBOXREADY (),
.TXHEADER (3'd0),
.TXSEQUENCE (7'd0),
.TXSTARTSEQ (1'b0),
.TXPCSRESET (1'b0),
.TXPMARESET (1'b0),
.TXRESETDONE (txresetdone),
.TXCOMFINISH (),
.TXCOMINIT (txcominit),
.TXCOMSAS (1'b0),
.TXCOMWAKE (txcomwake),
.TXPDELECIDLEMODE (1'b0),
.TXPOLARITY (1'b0),
.TXDETECTRX (1'b0),
.TX8B10BBYPASS (8'd0),
.TXPRBSSEL (3'd0),
.TXQPISENN (),
.TXQPISENP ()/*,
.TXSYNCMODE (1'b0),
.TXSYNCALLIN (1'b0),
.TXSYNCIN (1'b0)*/
);
/*
* Interfaces
*/
assign cplllockdetclk = gtrefclk; //TODO
assign drpclk = gtrefclk;
assign clk = usrclk2;
assign rxn = rxn_in;
assign rxp = rxp_in;
assign txn_out = txn;
assign txp_out = txp;
assign ll_data_out = rxdata_out;
assign ll_charisk_out = rxcharisk_out;
assign txdata_in = ll_data_in;
assign txcharisk_in = ll_charisk_in;
endmodule
......@@ -204,7 +204,7 @@ assign wr_cnt_to_push = 7'hf;
assign wr_stop = wr_val_in & wr_data_count == wr_cnt_to_push;
assign wr_ack_out = wr_val_in & rdwr_state == WRITE_DATA;
assign wr_data_in = wr_data;
//assign wr_data_in = wr_data;
// assuming for now we write only pre-defined 16 64-bit words
......
......@@ -63,7 +63,7 @@ module dma_regs #(
output wire sh_dev_val,
output wire [7:0] sh_control,
output wire sh_control_val,
output wire [31:0] sh_dma_id_lo
output wire [31:0] sh_dma_id_lo,
output wire sh_dma_id_lo_val,
output wire [31:0] sh_dma_id_hi,
output wire sh_dma_id_hi_val,
......@@ -71,7 +71,7 @@ module dma_regs #(
output wire sh_buf_off_val,
output wire [31:0] sh_dma_cnt,
output wire sh_dma_cnt_val,
output wire [31:0] sh_tran_cnt,
output wire [15:0] sh_tran_cnt,
output wire sh_tran_cnt_val,
output wire sh_autoact,
output wire sh_autoact_val,
......@@ -104,7 +104,7 @@ module dma_regs #(
input wire [31:0] sh_dma_cnt_in,
input wire [15:0] sh_tran_cnt_in, // Transfer Count
input wire sh_notif_in,
input wire sh_autoact_in
input wire sh_autoact_in,
// inputs from cmd control
input wire [31:0] cmd_in
);
......
......@@ -18,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ns
`timescale 1ns/1ps
`include "axi_regs.v"
`include "dma_regs.v"
`include "sata_host.v"
......@@ -141,9 +141,77 @@
output wire RXN,
output wire RXP,
input wire REFCLK_PAD_P_IN,
input wire REFCLK_PAD_N_IN
input wire EXTCLK_P,
input wire EXTCLK_N
);
wire sata_rst;
// dma_regs <-> sata host
// tmp to cmd control
wire cmd_val_out;
wire [31:0] cmd_out;
// tmp to shadow registers
wire [31:0] sh_data; // write data
wire sh_data_val; // write strobe
wire sh_data_strobe; // read strobe
wire [15:0] sh_feature;
wire sh_feature_val;
wire [23:0] sh_lba_lo;
wire sh_lba_lo_val;
wire [23:0] sh_lba_hi;
wire sh_lba_hi_val;
wire [15:0] sh_count;
wire sh_count_val;
wire [7:0] sh_command;
wire sh_command_val;
wire [7:0] sh_dev;
wire sh_dev_val;
wire [7:0] sh_control;
wire sh_control_val;
wire [31:0] sh_dma_id_lo;
wire sh_dma_id_lo_val;
wire [31:0] sh_dma_id_hi;
wire sh_dma_id_hi_val;
wire [31:0] sh_buf_off;
wire sh_buf_off_val;
wire [31:0] sh_dma_cnt;
wire sh_dma_cnt_val;
wire [15:0] sh_tran_cnt;
wire sh_tran_cnt_val;
wire sh_autoact;
wire sh_autoact_val;
wire sh_inter;
wire sh_inter_val;
wire [3:0] sh_port;
wire sh_port_val;
wire sh_notif;
wire sh_notif_val;
wire sh_dir;
wire sh_dir_val;
// inputs from sh registers
wire sh_data_val_in;
wire [31:0] sh_data_in;
wire [7:0] sh_control_in;
wire [15:0] sh_feature_in;
wire [47:0] sh_lba_in;
wire [15:0] sh_count_in;
wire [7:0] sh_command_in;
wire [7:0] sh_err_in;
wire [7:0] sh_status_in;
wire [7:0] sh_estatus_in; // E_Status
wire [7:0] sh_dev_in;
wire [3:0] sh_port_in;
wire sh_inter_in;
wire sh_dir_in;
wire [63:0] sh_dma_id_in;
wire [31:0] sh_dma_off_in;
wire [31:0] sh_dma_cnt_in;
wire [15:0] sh_tran_cnt_in; // Transfer Count
wire sh_notif_in;
wire sh_autoact_in;
// inputs from cmd control
wire [31:0] cmd_in;
// axi_regs <-> data regs
wire [31:0] bram_rdata;
wire [31:0] bram_waddr;
......@@ -214,14 +282,6 @@ wire buf_rd;
wire [63:0] buf_rdata;
// additional adapter <-> membridge wire
wire rdata_done; // = membridge.is_last_in_page & membridge.afi_rready;
// sata_host timer
wire host_sata_timer;
// sata_host diag
wire host_linkup;
wire host_plllkdet;
wire host_dcmlocked;
// temporary 150Mhz clk
wire gtrefclk;
assign rst = ARESETN;
......@@ -301,7 +361,74 @@ dma_regs dma_regs(
.bram_wstb (bram_wstb),
.bram_wen (bram_wen),
.bram_ren (bram_ren),
.bram_regen (bram_regen)
.bram_regen (bram_regen),
// direct connections to the host
// tmp to cmd control
.cmd_val_out (cmd_val_out),
.cmd_out (cmd_out),
// tmp to shadow registers
.sh_data (sh_data), // write data
.sh_data_val (sh_data_val), // write strobe
.sh_data_strobe (sh_data_strobe), // read strobe
.sh_feature (sh_feature),
.sh_feature_val (sh_feature_val),
.sh_lba_lo (sh_lba_lo),
.sh_lba_lo_val (sh_lba_lo_val),
.sh_lba_hi (sh_lba_hi),
.sh_lba_hi_val (sh_lba_hi_val),
.sh_count (sh_count),
.sh_count_val (sh_count_val),
.sh_command (sh_command),
.sh_command_val (sh_command_val),
.sh_dev (sh_dev),
.sh_dev_val (sh_dev_val),
.sh_control (sh_control),
.sh_control_val (sh_control_val),
.sh_dma_id_lo (sh_dma_id_lo),
.sh_dma_id_lo_val (sh_dma_id_lo_val),
.sh_dma_id_hi (sh_dma_id_hi),
.sh_dma_id_hi_val (sh_dma_id_hi_val),
.sh_buf_off (sh_buf_off),
.sh_buf_off_val (sh_buf_off_val),
.sh_dma_cnt (sh_dma_cnt),
.sh_dma_cnt_val (sh_dma_cnt_val),
.sh_tran_cnt (sh_tran_cnt),
.sh_tran_cnt_val (sh_tran_cnt_val),
.sh_autoact (sh_autoact),
.sh_autoact_val (sh_autoact_val),
.sh_inter (sh_inter),
.sh_inter_val (sh_inter_val),
.sh_port (sh_port),
.sh_port_val (sh_port_val),
.sh_notif (sh_notif),
.sh_notif_val (sh_notif_val),
.sh_dir (sh_dir),
.sh_dir_val (sh_dir_val),
// inputs from sh registers
.sh_data_val_in (sh_data_val_in),
.sh_data_in (sh_data_in),
.sh_control_in (sh_control_in),
.sh_feature_in (sh_feature_in),
.sh_lba_in (sh_lba_in),
.sh_count_in (sh_count_in),
.sh_command_in (sh_command_in),
.sh_err_in (sh_err_in),
.sh_status_in (sh_status_in),
.sh_estatus_in (sh_estatus_in), // E_Status
.sh_dev_in (sh_dev_in),
.sh_port_in (sh_port_in),
.sh_inter_in (sh_inter_in),
.sh_dir_in (sh_dir_in),
.sh_dma_id_in (sh_dma_id_in),
.sh_dma_off_in (sh_dma_off_in),
.sh_dma_cnt_in (sh_dma_cnt_in),
.sh_tran_cnt_in (sh_tran_cnt_in), // Transfer Count
.sh_notif_in (sh_notif_in),
.sh_autoact_in (sh_autoact_in),
// inputs from cmd control
.cmd_in (cmd_in)
);
......@@ -481,52 +608,88 @@ V .MEMBRIDGE_ADDR (),
);
sata_host sata_host(
.ready_for_cmd (host_ready_for_cmd),
.new_cmd (host_new_cmd),
.cmd_type (host_cmd_type),
.sector_count (host_sector_count),
.sector_addr (host_sector_addr),
.sata_din (out_data),
.sata_din_we (out_val),
.sata_core_full (out_busy),
.sata_dout (in_data),
.sata_dout_re (in_val),
.sata_core_empty (in_busy),
.data_clk_in (sclk),
.data_clk_out (sclk),
.extrst (rst),
// sata rst
.rst (sata_rst),
// sata clk
.clk (clk),
// temporary
.al_cmd_in (cmd_out), // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good; cmd_busy}
.al_cmd_val_in (cmd_val_out),
.al_cmd_out (cmd_in), // same
.sata_timer (host_sata_timer),
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
.al_sh_data_in (sh_data), // write data
.al_sh_data_val_in (sh_data_val), // write strobe
.al_sh_data_strobe_in (sh_data_strobe), // read strobe
.al_sh_feature_in (sh_feature),
.al_sh_feature_val_in (sh_feature_val),
.al_sh_lba_lo_in (sh_lba_lo),
.al_sh_lba_lo_val_in (sh_lba_lo_val),
.al_sh_lba_hi_in (sh_lba_hi),
.al_sh_lba_hi_val_in (sh_lba_hi_val),
.al_sh_count_in (sh_count),
.al_sh_count_val_in (sh_count_val),
.al_sh_command_in (sh_command),
.al_sh_command_val_in (sh_command_val),
.al_sh_dev_in (sh_dev),
.al_sh_dev_val_in (sh_dev_val),
.al_sh_control_in (sh_control),
.al_sh_control_val_in (sh_control_val),
.al_sh_dma_id_lo_in (sh_dma_id_lo),
.al_sh_dma_id_lo_val_in (sh_dma_id_lo_val),
.al_sh_dma_id_hi_in (sh_dma_id_hi),
.al_sh_dma_id_hi_val_in (sh_dma_id_hi_val),
.al_sh_buf_off_in (sh_buf_off),
.al_sh_buf_off_val_in (sh_buf_off_val),
.al_sh_tran_cnt_in (sh_tran_cnt),
.al_sh_tran_cnt_val_in (sh_tran_cnt_val),
.al_sh_autoact_in (sh_autoact),
.al_sh_autoact_val_in (sh_autoact_val),
.al_sh_inter_in (sh_inter),
.al_sh_inter_val_in (sh_inter_val),
.al_sh_dir_in (sh_dir),
.al_sh_dir_val_in (sh_dir_val),
.al_sh_dma_cnt_in (sh_dma_cnt),
.al_sh_dma_cnt_val_in (sh_dma_cnt_val),
.al_sh_notif_in (sh_notif),
.al_sh_notif_val_in (sh_notif_val),
.al_sh_port_in (sh_port),
.al_sh_port_val_in (sh_port_val),
.clkin_150 (gtrefclk),
.reset (rst),
// outputs from shadow registers
.linkup (host_linkup),
.txp_out (TXP),
.txn_out (TXN),
.rxp_in (RXP),
.rxn_in (RXN),
.sh_data_val_out (sh_data_val_in),
.sh_data_out (sh_data_in),
.sh_control_out (sh_control_in),
.sh_feature_out (sh_feature_in),
.sh_lba_out (sh_lba_in),
.sh_count_out (sh_count_in),
.sh_command_out (sh_command_in),
.sh_err_out (sh_err_in),
.sh_status_out (sh_status_in),
.sh_estatus_out (sh_estatus_in), // E_Status
.sh_dev_out (sh_dev_in),
.sh_port_out (sh_port_in),
.sh_inter_out (sh_inter_in),
.sh_dir_out (sh_dir_in),
.sh_dma_id_out (sh_dma_id_in),
.sh_dma_off_out (sh_dma_off_in),
.sh_dma_cnt_out (sh_dma_cnt_in),
.sh_tran_cnt_out (sh_tran_cnt_in), // Transfer Count
.sh_notif_out (sh_notif_in),
.sh_autoact_out (sh_autoact_in),
.plllkdet (host_plllkdet),
.dcmlocked (host_dcmlocked)
);
/*
* Padding for an external input clock @ 150 MHz
* TODO!!! Shall be done on phy-level
*/
localparam [1:0] CLKSWING_CFG = 2'b11;
IBUFDS_GTE2 #(
.CLKRCV_TRST ("TRUE"),
.CLKCM_CFG ("TRUE"),
.CLKSWING_CFG (CLKSWING_CFG)
)
ext_clock_buf(
.I (REFCLK_PAD_P_IN),
.IB (REFCLK_PAD_N_IN),
.CEB (1'b0),
.O (gtrefclk),
.ODIV2 ()
// top-level ifaces
// ref clk from an external source, shall be connected to pads
.extclk_p (EXTCLK_P),
.extclk_n (EXTCLK_N),
// sata physical link data pins
.txp_out (TXP),
.txn_out (TXN),
.rxp_in (RXP),
.rxn_in (RXN)
);
endmodule
/*******************************************************************************
* Module: send_dma
* Date: 2015-07-11
* Author: Alexey
* Description: temporary interconnect to membridge testing purposes only
*
* Copyright (c) 2015 Elphel, Inc.
* send_dma.v 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.
*
* send_dma.v file 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/> .
*******************************************************************************/
/*
* The module is temporary
* It could make transactions from DMA data buffer to membridge and vice versa.
* Processes 1 transaction of 16 x 64bit-words at a time.
* Waits until 1 read or 1 write is completely done.
* After that it deasserts busy and is ready to process a new transaction.
*
* The whole purpose of a module as a system block is to be a buffer between
* a big dma data storage and axi interface. So it shall recieve data and control
* for 1 burst and pass it to axi.
*/
/*
* For debug only:
* DMA write:
* 0x0c: |mem[:] => use dbg registers as a source of dma data
* 0x10: addr of the buffer
* 0x14: size
* 0x18: burst len
* 0x1c: start dma
* 0x20-0x3c - data
*/
module send_dma #(
parameter REGISTERS_CNT = 20
)
(
input wire clk,
input wire rst,
// dbg iface
input wire [32*REGISTERS_CNT - 1:0] mem,
input wire dbg_mode,
output wire clrstart,
// cmd iface
input wire cmd_type, // 1 = wr, 0 = rd
input wire cmd_val, // issue a cmd
input wire [31:7] cmd_addr, // [2:0] - 64-bit (8-bytes) word offset, [6:3] - 16-words transfer offset
output wire cmd_busy, // no-pipelined cmd execution, 1 cmd at a time
// data iface
input wire [63:0] wr_data_in,
output wire wr_val_out,
output wire [63:0] rd_data_out,
input wire rd_val_in,
// membridge iface
output wire [7:0] cmd_ad,
output wire cmd_stb,
input wire [7:0] status_ad,
input wire status_rq,
output wire status_start,
input wire frame_start_chn,
input wire next_page_chn,
output wire cmd_wrmem,
output wire page_ready_chn,
output wire frame_done_chn,
output wire [15:0] line_unfinished_chn1,
input wire suspend_chn1,
output wire xfer_reset_page_rd,
output wire buf_wpage_nxt,
output wire buf_wr,
output wire [63:0] buf_wdata,
output wire xfer_reset_page_wr,
output wire buf_rpage_nxt,
output wire buf_rd,
input wire [63:0] buf_rdata,
// additinal wire to indicate if membridge recieved a packet
input wire rdata_done // = membridge.is_last_in_page & membridge.afi_rready;
);
// cmd handling
// if not busy and got cmd with val => cmd recieved, assert busy, start a respective algorithm
wire wr_start;
wire rd_start;
reg wr_done;
reg rd_done;
reg cmd_type_r;
reg cmd_addr_r;
reg cmd_val_r;
reg cmd_busy_r;
wire set_busy;
wire clr_busy;
assign set_busy = ~cmd_busy_r & cmd_val;
assign clr_busy = cmd_busy_r & (wr_done | rd_done)
always @ (posedge clk)
begin
cmd_type_r <= rst ? 1'b0 :
cmd_addr_r <= rst ? 1'b0 :
cmd_val_r <= rst ? 1'b0 :
cmd_busy_r <= rst ? 1'b0 : ~cmd_busy_r & cmd_val_r
end
/*
* Read/write state machine
* For better readability the state machine is splitted to two pieces:
* the first one is responsible only for the CMD WRITE case handling,
* the second one, respectively, for CMD READ
*
* Each fsm starts a membridge fsm, which, if being 1st time launched, sets up
* membridge's registers, or, if have been launched before, just programs read/write
* address.
*
* Current implementation is extremely slow, but simple and reliable
* After all other parts are implemented and this place occurs to be a bottleneck
* then replace it (and may be membridge too) with something more ... pipelined
*/
reg [1:0] rdwr_state;
// Get data from buffer
localparam READ_IDLE = 0;
localparam READ_ON = 2;
localparam READ_DATA = 3;
reg rd_reset_page;
reg rd_next_page;
reg rd_data
always @ (posedge clk)
if (rst)
begin
rd_state <= READ_IDLE;
rd_done <=
end
else
case (rst)
READ_IDLE:
begin
end
READ_ON:
begin
end
// Put data into buffer
localparam WRITE_IDLE = 0;
localparam WRITE_ON = 1;
reg wr_en;
reg wr_reset_page;
reg wr_next_page;
reg [63:0] wr_data;
reg [6:0] wr_page_offset;
reg wr_page_ready;
reg wr_val;
wire [31:0] dw0 = mem[32*9-1:32*8];
wire [31:0] dw1 = mem[32*10-1:32*9];
wire [31:0] dw2 = mem[32*11-1:32*10];
wire [31:0] dw3 = mem[32*12-1:32*11];
wire [6:0] wr_cnt_to_push;
wire wr_stop;
assign wr_cnt_to_push = 7'hf;
assign wr_stop = wr_page_offset == wr_cnt_to_push;
assign wr_val_in = wr_val;
assign wr_data_in = wr_data;
// assuming for now we write only pre-defined 16 64-bit words
always @ (posedge clk)
if (rst)
begin
wr_done <= 1'b0;
wr_page_offset <= 7'd0;
wr_val <= 1'b0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
rdwr_state <= WRITE_IDLE;
end
else
case (wr_state)
WRITE_IDLE:
begin
wr_page_offset <= 7'd0;
wr_done <= 1'b0;
wr_val <= 1'b0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= wr_start ? 1'b1 : 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
rdwr_state <= wr_start ? WRITE_ON : WRITE_IDLE;
end
WRITE_ON:
begin
wr_done <= wr_stop ? 1'b1 : 1'b0;
wr_page_offset <= wr_page_offset + 1'b1;
wr_val <= 1'b1;
wr_data <= ~dbg_mode ? in_data :
wr_page_offset[1:0] == 2'b00 ? {dw0, 25'h0, wr_page_offset} :
wr_page_offset[1:0] == 2'b01 ? {dw1, 25'h0, wr_page_offset} :
wr_page_offset[1:0] == 2'b10 ? {dw2, 25'h0, wr_page_offset} :
{dw3, 25'h0, wr_page_offset};
wr_next_page <= wr_stop ? 1'b1 : 1'b0;
wr_reset_page <= 1'b0;
wr_en <= 1'b1;
wr_page_ready <= wr_stop ? 1'b1 : 1'b0;
rdwr_state <= wr_stop ? WRITE_IDLE : WRITE_ON;
end
default: // read is executed
begin
wr_done <= 1'b0;
wr_page_offset <= 7'd0;
wr_val <= 1'b0;
wr_data <= 64'h0;
wr_next_page <= 1'b0;
wr_reset_page <= 1'b0;
wr_en <= 1'b0;
wr_page_ready <= 1'b0;
rdwr_state <= rdwr_state;
end
endcase
// temporary assigments
assign status_start = 1'b0; // no need until status is used
assign cmd_wrmem = 1'b0; // for now only writing
assign xfer_reset_page_wr = 1'b0; // for now only writing
assign buf_rpage_nxt = 1'b0; // for now only writing
assign buf_rd = 1'b0; // for now only writing
assign xfer_reset_page_wr = 1'b0;
assign buf_wdata = wr_data;
assign buf_wr = wr_en;
assign buf_wpage_nxt = wr_next_page;
assign xfer_reset_page_rd = wr_reset_page;
assign page_ready_chn = cmd_wrmem ? 1'b0 : wr_page_ready;
assign frame_done_chn = 1'b1;
// compute membridge parameters to corresponding mem register
// dma fsm
// mode = 0
// width = 4
// size = 0x14
// start = 0
// lo_address = 0x10
// ctrl = 0x1c
// len = 0x18
localparam MEMBR_IDLE = 0;
localparam MEMBR_MODE = 1;
localparam MEMBR_WIDTH = 2;
localparam MEMBR_LEN = 3;
localparam MEMBR_START = 4;
localparam MEMBR_SIZE = 5;
localparam MEMBR_LOADDR = 6;
localparam MEMBR_CTRL = 7;
reg [32:0] membr_data;
reg [15:0] membr_addr;
reg membr_start;
reg membr_done;
reg [2:0] membr_state;
reg membr_setup; // indicates the first tick of the state
wire membr_inprocess;
wire dma_start;
assign dma_start = |mem[32*8-1:32*7];
assign clrstart = dma_start & membr_state == MEMBR_IDLE;
//assign wr_start = membr_state == MEMBR_CTRL;
always @ (posedge clk)
if (rst)
begin
membr_data <= 32'h0;
membr_addr <= 16'h0;
membr_start <= 1'b0;
membr_setup <= 1'b0;
membr_state <= MEMBR_IDLE;
end
else
case (membr_state)
MEMBR_IDLE:
begin
membr_data <= 32'h0;
membr_addr <= 16'h200;
membr_start <= dma_start ? 1'b1 : 1'b0;
membr_setup <= dma_start ? 1'b1 : 1'b0;
membr_state <= dma_start ? MEMBR_MODE : MEMBR_IDLE;
end
MEMBR_MODE:
begin
membr_data <= 32'h3;
membr_addr <= 16'h207;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_state <= membr_inprocess | membr_setup ? MEMBR_MODE : MEMBR_WIDTH;
end
MEMBR_WIDTH:
begin
membr_data <= 32'h10;
membr_addr <= 16'h206;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_state <= membr_inprocess | membr_setup ? MEMBR_WIDTH : MEMBR_LEN;
end
MEMBR_LEN:
begin
membr_data <= 32'h10;
membr_addr <= 16'h205;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_state <= membr_inprocess | membr_setup ? MEMBR_LEN : MEMBR_START;
end
MEMBR_START:
begin
membr_data <= 32'h0;
membr_addr <= 16'h204;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_state <= membr_inprocess | membr_setup ? MEMBR_START : MEMBR_SIZE;
end
MEMBR_SIZE:
begin
membr_data <= 32'h10;
membr_addr <= 16'h203;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_state <= membr_inprocess | membr_setup ? MEMBR_SIZE : MEMBR_LOADDR;
end
MEMBR_LOADDR:
begin
membr_data <= mem[32*5-1:32*4];
membr_addr <= 16'h202;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1;
membr_state <= membr_inprocess | membr_setup ? MEMBR_LOADDR : MEMBR_CTRL;
end
MEMBR_CTRL:
begin
membr_data <= {28'h0000000, 4'b0011};
membr_addr <= 16'h200;
membr_start <= membr_inprocess ? 1'b0 : 1'b1;
membr_setup <= 1'b0;
membr_state <= membr_inprocess | membr_setup ? MEMBR_CTRL : MEMBR_IDLE;
end
default:
begin
membr_data <= 32'h0;
membr_addr <= 16'h0;
membr_start <= 1'b0;
membr_setup <= 1'b0;
membr_state <= MEMBR_IDLE;
end
endcase
// write to memridge registers fsm
localparam STATE_IDLE = 3'h0;
localparam STATE_CMD_0 = 3'h1;
localparam STATE_CMD_1 = 3'h2;
localparam STATE_DATA_0 = 3'h3;
localparam STATE_DATA_1 = 3'h4;
localparam STATE_DATA_2 = 3'h5;
localparam STATE_DATA_3 = 3'h6;
reg [2:0] state;
reg [7:0] out_ad;
reg out_stb;
assign membr_inprocess = state != STATE_IDLE;
assign cmd_ad = out_ad;
assign cmd_stb = out_stb;
always @ (posedge clk)
if (rst)
begin
membr_done <= 1'b0;
state <= STATE_IDLE;
out_ad <= 8'h0;
out_stb <= 1'b0;
end
else
case (state)
STATE_IDLE:
begin
membr_done <= 1'b0;
out_ad <= 8'h0;
out_stb <= 1'b0;
state <= membr_setup ? STATE_CMD_0 : STATE_IDLE;
end
STATE_CMD_0:
begin
membr_done <= 1'b0;
out_ad <= membr_addr[7:0];
out_stb <= 1'b1;
state <= STATE_CMD_1;
end
STATE_CMD_1:
begin
membr_done <= 1'b0;
out_ad <= membr_addr[15:8];
out_stb <= 1'b0;
state <= STATE_DATA_0;
end
STATE_DATA_0:
begin
membr_done <= 1'b0;
out_ad <= membr_data[7:0];
out_stb <= 1'b0;
state <= STATE_DATA_1;
end
STATE_DATA_1:
begin
membr_done <= 1'b0;
out_ad <= membr_data[15:8];
out_stb <= 1'b0;
state <= STATE_DATA_2;
end
STATE_DATA_2:
begin
membr_done <= 1'b0;
out_ad <= membr_data[23:16];
out_stb <= 1'b0;
state <= STATE_DATA_3;
end
STATE_DATA_3:
begin
membr_done <= 1'b0;
out_ad <= membr_data[31:24];
out_stb <= 1'b0;
state <= STATE_IDLE;
end
default:
begin
membr_done <= 1'b1;
out_ad <= 8'hff;
out_stb <= 1'b0;
state <= STATE_IDLE;
end
endcase
endmodule
......@@ -35,8 +35,8 @@ module top #(
output wire TXN,
output wire TXP,
// sata clocking iface
input wire REFCLK_PAD_P_IN,
input wire REFCLK_PAD_N_IN
input wire EXTCLK_P,
input wire EXTCLK_N
);
parameter REGISTERS_CNT = 20;
wire [32*REGISTERS_CNT - 1:0] outmem;
......@@ -285,8 +285,8 @@ sata_top sata_top(
.RXN (RXN),
.RXP (RXP),
.REFCLK_PAD_P_IN (REFCLK_PAD_P_IN),
.REFCLK_PAD_N_IN (REFCLK_PAD_N_IN)
.EXTCLK_P (EXTCLK_P),
.EXTCLK_N (EXTCLK_N)
);
PS7 ps7_i (
......
......@@ -74,7 +74,7 @@ module command(
input wire al_sh_dma_id_hi_val_in,
input wire [31:0] al_sh_buf_off_in,
input wire al_sh_buf_off_val_in,
input wire [31:0] al_sh_tran_cnt_in,
input wire [15:0] al_sh_tran_cnt_in,
input wire al_sh_tran_cnt_val_in,
input wire al_sh_autoact_in,
input wire al_sh_autoact_val_in,
......@@ -188,7 +188,7 @@ begin
sh_dma_id[63:32] <= rst ? 32'h0 : al_sh_dma_id_lo_val_in ? al_sh_dma_id_hi_in : tl_sh_dma_id_val_in ? tl_sh_dma_id_in[63:32] : sh_dma_id[63:32];
sh_dma_off <= rst ? 32'h0 : al_sh_buf_off_val_in ? al_sh_buf_off_in : tl_sh_dma_off_val_in ? tl_sh_dma_off_in : sh_dma_off;
sh_dma_cnt <= rst ? 32'h0 : al_sh_dma_cnt_val_in ? al_sh_dma_cnt_in : tl_sh_dma_cnt_val_in ? tl_sh_dma_cnt_in : sh_dma_cnt;
sh_tran_cnt <= rst ? 32'h0 : al_sh_tran_cnt_val_in ? al_sh_tran_cnt_in : tl_sh_tran_cnt_val_in ? tl_sh_tran_cnt_in : sh_tran_cnt;
sh_tran_cnt <= rst ? 16'h0 : al_sh_tran_cnt_val_in ? al_sh_tran_cnt_in : tl_sh_tran_cnt_val_in ? tl_sh_tran_cnt_in : sh_tran_cnt;
sh_notif <= rst ? 1'h0 : al_sh_notif_val_in ? al_sh_notif_in : tl_sh_notif_val_in ? tl_sh_notif_in : sh_notif;
sh_autoact <= rst ? 1'h0 : al_sh_autoact_val_in ? al_sh_autoact_in : tl_sh_autoact_val_in ? tl_sh_autoact_in : sh_autoact;
end
......@@ -220,10 +220,10 @@ reg [31:0] cmd;
assign al_cmd_out = cmd;
always @ (posedge clk)
begin
cmd[31:4] <= rst ? 28'h0 : al_cmd_val_in ? al_cmd_in : cmd;
cmd[31:4] <= rst ? 28'h0 : al_cmd_val_in ? al_cmd_in[31:4] : cmd[31:4];
cmd[3] <= rst ? 1'b0 : al_cmd_val_in ? al_cmd_in[3] : cmd_val ? 1'b0 : cmd[3];
cmd[2] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_bad ? 1'b1 : cmd[2];
cmd[1] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_good ? 1'b1 : cmd[2];
cmd[1] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_good ? 1'b1 : cmd[1];
cmd[0] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_busy;
end
......
......@@ -18,6 +18,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`include "scrambler.v"
`include "crc.v"
module link #(
// 4 = dword. 4-bytes aligned data transfers TODO 2 = word - easy, 8 = qword - difficult
parameter DATA_BYTE_WIDTH = 4
......@@ -92,11 +94,11 @@ module link #(
// data-primitives stream from phy
input wire [DATA_BYTE_WIDTH*8 - 1:0] phy_data_in,
input wire [DATA_BYTE_WIDTH/2 - 1:0] phy_isk_in, // charisk
input wire [DATA_BYTE_WIDTH/2 - 1:0] phy_err_in, // disperr | notintable
input wire [DATA_BYTE_WIDTH - 1:0] phy_isk_in, // charisk
input wire [DATA_BYTE_WIDTH - 1:0] phy_err_in, // disperr | notintable
// to phy
output wire [DATA_BYTE_WIDTH*8 - 1:0] phy_data_out,
output wire [DATA_BYTE_WIDTH/2 - 1:0] phy_isk_out // charisk
output wire [DATA_BYTE_WIDTH - 1:0] phy_isk_out // charisk
);
// scrambled data
wire [DATA_BYTE_WIDTH*8 - 1:0] scrambler_out;
......@@ -114,7 +116,7 @@ always @ (posedge clk)
// send primitives variety count, including CRC and DATA as primitives
localparam PRIM_NUM = 15;
// list of bits of rcvd_dword
wire [PRIM_NUM:0] rcvd_dword; // shows current processing primitive (or just data dword)
wire [PRIM_NUM - 1:0] rcvd_dword; // shows current processing primitive (or just data dword)
wire dword_val;
localparam CODE_DATA = 0;
localparam CODE_CRC = 1;
......@@ -213,27 +215,27 @@ wire clr_rcvr_goodend;
wire clr_rcvr_badend;
assign state_idle = ~state_sync_esc
| ~state_nocommerr
| ~state_nocomm
| ~state_align
| ~state_reset
| ~state_send_rdy
| ~state_send_sof
| ~state_send_data
| ~state_send_rhold
| ~state_send_shold
| ~state_send_crc
| ~state_send_eof
| ~state_wait
| ~state_rcvr_wait
| ~state_rcvr_rdy
| ~state_rcvr_data
| ~state_rcvr_rhold
| ~state_rcvr_shold
| ~state_rcvr_eof
| ~state_rcvr_goodcrc
| ~state_rcvr_goodend
| ~state_rcvr_badend;
& ~state_nocommerr
& ~state_nocomm
& ~state_align
& ~state_reset
& ~state_send_rdy
& ~state_send_sof
& ~state_send_data
& ~state_send_rhold
& ~state_send_shold
& ~state_send_crc
& ~state_send_eof
& ~state_wait
& ~state_rcvr_wait
& ~state_rcvr_rdy
& ~state_rcvr_data
& ~state_rcvr_rhold
& ~state_rcvr_shold
& ~state_rcvr_eof
& ~state_rcvr_goodcrc
& ~state_rcvr_goodend
& ~state_rcvr_badend;
// got an escaping primitive = request to cancel the transmission
......@@ -306,13 +308,13 @@ assign clr_send_shold = set_nocommerr | set_reset | set_sync_esc | set_sen
assign clr_send_crc = set_nocommerr | set_reset | set_sync_esc | set_send_eof | got_escape;
assign clr_send_eof = set_nocommerr | set_reset | set_sync_esc | set_wait | got_escape;
assign clr_wait = set_nocommerr | set_reset | set_sync_esc | frame_done | got_escape;
assign clr_rcvr_wait = set_nocommerr | set_reset | set_sync_esc | set_rcvr_rdy | dword_val & ~rcvd_dword[CODE_RRDYP];
assign clr_rcvr_rdy = set_nocommerr | set_reset | set_sync_esc | set_rcvr_data | dword_val & ~rcvd_dword[CODE_RRDYP] & ~rcvd_dword[CODE_SOFP];
assign clr_rcvr_wait = set_nocommerr | set_reset | set_sync_esc | set_rcvr_rdy | dword_val & ~rcvd_dword[CODE_XRDYP];
assign clr_rcvr_rdy = set_nocommerr | set_reset | set_sync_esc | set_rcvr_data | dword_val & ~rcvd_dword[CODE_XRDYP] & ~rcvd_dword[CODE_SOFP];
assign clr_rcvr_data = set_nocommerr | set_reset | set_sync_esc | set_rcvr_rhold | set_rcvr_shold | set_rcvr_eof | set_rcvr_badend | got_escape;
assign clr_rcvr_rhold = set_nocommerr | set_reset | set_sync_esc | set_rcvr_data | set_rcvr_eof | set_rcvr_shold | got_escape;
assign clr_rcvr_shold = set_nocommerr | set_reset | set_sync_esc | set_rcvr_data | set_rcvr_eof | got_escape;
assign clr_rcvr_eof = set_nocommerr | set_reset | set_sync_esc | set_rcvr_eof | set_rcvr_goodcrc | set_rcvr_badend;
assign clr_rcvr_goodcrc = set_nocommerr | set_reset | set_sync_esc | set_rcvr_goodend | set_rcvr_badend | set_rcvr_goodcrc | got_escape;
assign clr_rcvr_eof = set_nocommerr | set_reset | set_sync_esc | set_rcvr_goodcrc | set_rcvr_badend;
assign clr_rcvr_goodcrc = set_nocommerr | set_reset | set_sync_esc | set_rcvr_goodend | set_rcvr_badend | got_escape;
assign clr_rcvr_goodend = set_nocommerr | set_reset | set_sync_esc | got_escape;
assign clr_rcvr_badend = set_nocommerr | set_reset | set_sync_esc | got_escape;
......@@ -352,7 +354,7 @@ always @ (posedge clk)
// form data to phy
reg [DATA_BYTE_WIDTH*8 - 1:0] to_phy_data;
reg [DATA_BYTE_WIDTH/2 - 1:0] to_phy_isk;
reg [DATA_BYTE_WIDTH - 1:0] to_phy_isk;
// TODO implement CONTP
localparam [15:0] PRIM_SYNCP_HI = {3'd5, 5'd21, 3'd5, 5'd21};
localparam [15:0] PRIM_SYNCP_LO = {3'd4, 5'd21, 3'd3, 5'd28};
......@@ -477,7 +479,7 @@ always @ (posedge clk)
{DATA_BYTE_WIDTH*8{select_prim[CODE_DATA]}} & prim_data[CODE_DATA];
always @ (posedge clk)
to_phy_isk <= rst | ~select_prim[CODE_DATA] & ~select_prim[CODE_CRC] ? {{(DATA_BYTE_WIDTH/2 - 1){1'b0}}, 1'b1} : {DATA_BYTE_WIDTH/2{1'b0}} ;
to_phy_isk <= rst | ~select_prim[CODE_DATA] & ~select_prim[CODE_CRC] ? {{(DATA_BYTE_WIDTH - 1){1'b0}}, 1'b1} : {DATA_BYTE_WIDTH{1'b0}} ;
// incoming data is data
wire inc_is_data;
......@@ -503,7 +505,7 @@ crc crc(
.clk (clk),
.rst (select_prim[CODE_SOFP] | dword_val & rcvd_dword[CODE_SOFP]),
.val_in (select_prim[CODE_DATA] | inc_is_data),
.data_in (data_in & {DATA_BYTE_WIDTH*8{select_prim[CODE_DATA]}} | phy_data_in & {DATA_BYTE_WIDTH*8{inc_is_data}}),
.data_in (data_in & {DATA_BYTE_WIDTH*8{select_prim[CODE_DATA]}} | scrambler_out & {DATA_BYTE_WIDTH*8{inc_is_data}}),
.crc_out (crc_dword)
);
......@@ -549,26 +551,27 @@ assign incom_start = set_rcvr_wait & ~alignes_pair;
// ... and processed
assign incom_done = set_rcvr_goodcrc & ~alignes_pair;
// or the FIS had errors
assign incom_invalidate = state_rcvr_eof & crc_bad & ~alignes_pair | state_rcvr_data & dword_val & rcvd_dword[CODE_WTRMP];
assign incom_invalidate = state_rcvr_eof & crc_bad & ~alignes_pair | state_rcvr_data & dword_val & rcvd_dword[CODE_WTRMP]
| (state_rcvr_wait | state_rcvr_rdy | state_rcvr_data | state_rcvr_rhold | state_rcvr_shold | state_rcvr_eof | state_rcvr_goodcrc) & got_escape;
// shows that incoming primitive or data is ready to be processed // TODO somehow move alignes_pair into dword_val
assign dword_val = |rcvd_dword & phy_ready;
assign dword_val = |rcvd_dword & phy_ready & ~rcvd_dword[CODE_ALIGNP];
// determine imcoming primitive type
assign rcvd_dword[CODE_DATA] = ~|phy_isk_in;
assign rcvd_dword[CODE_CRC] = 1'b0;
assign rcvd_dword[CODE_SYNCP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_SYNCP ] == phy_data_in;
assign rcvd_dword[CODE_ALIGNP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_ALIGNP] == phy_data_in;
assign rcvd_dword[CODE_XRDYP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_XRDYP ] == phy_data_in;
assign rcvd_dword[CODE_SOFP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_SOFP ] == phy_data_in;
assign rcvd_dword[CODE_HOLDAP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_HOLDAP] == phy_data_in;
assign rcvd_dword[CODE_HOLDP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_HOLDP ] == phy_data_in;
assign rcvd_dword[CODE_EOFP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_EOFP ] == phy_data_in;
assign rcvd_dword[CODE_WTRMP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_WTRMP ] == phy_data_in;
assign rcvd_dword[CODE_RRDYP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_RRDYP ] == phy_data_in;
assign rcvd_dword[CODE_IPP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_IPP ] == phy_data_in;
assign rcvd_dword[CODE_DMATP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_DMATP ] == phy_data_in;
assign rcvd_dword[CODE_OKP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_OKP ] == phy_data_in;
assign rcvd_dword[CODE_ERRP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH/2-1:1] & prim_data[CODE_ERRP ] == phy_data_in;
assign rcvd_dword[CODE_SYNCP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_SYNCP ] == phy_data_in;
assign rcvd_dword[CODE_ALIGNP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_ALIGNP] == phy_data_in;
assign rcvd_dword[CODE_XRDYP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_XRDYP ] == phy_data_in;
assign rcvd_dword[CODE_SOFP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_SOFP ] == phy_data_in;
assign rcvd_dword[CODE_HOLDAP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_HOLDAP] == phy_data_in;
assign rcvd_dword[CODE_HOLDP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_HOLDP ] == phy_data_in;
assign rcvd_dword[CODE_EOFP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_EOFP ] == phy_data_in;
assign rcvd_dword[CODE_WTRMP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_WTRMP ] == phy_data_in;
assign rcvd_dword[CODE_RRDYP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_RRDYP ] == phy_data_in;
assign rcvd_dword[CODE_IPP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_IPP ] == phy_data_in;
assign rcvd_dword[CODE_DMATP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_DMATP ] == phy_data_in;
assign rcvd_dword[CODE_OKP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_OKP ] == phy_data_in;
assign rcvd_dword[CODE_ERRP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_WIDTH-1:1] & prim_data[CODE_ERRP ] == phy_data_in;
// phy level errors handling TODO
assign dec_err = |phy_err_in;
......@@ -591,7 +594,8 @@ always @ (posedge clk)
reg [STATES_COUNT - 1:0] sim_states_concat;
always @ (posedge clk)
if (~rst)
if ((state_idle
if (( 32'h0
+ state_idle
+ state_sync_esc
+ state_nocommerr
+ state_nocomm
......@@ -616,7 +620,7 @@ always @ (posedge clk)
+ state_rcvr_badend
) != 1)
begin
sim_state_concat = {
sim_states_concat = {
state_idle
, state_sync_esc
, state_nocommerr
......@@ -641,9 +645,23 @@ always @ (posedge clk)
, state_rcvr_goodend
, state_rcvr_badend
};
$display("%m: invalid states: %b", sim_state_concat);
$display("%m: invalid states: %b", sim_states_concat);
$finish;
end
`endif
`ifdef SIMULATION
always @ (posedge clk)
begin
if (data_val_out) begin
$display("[Host] LINK: From device - received data = %h", data_out);
end
if (inc_is_data) begin
$display("[Host] LINK: From device - received raw data = %h", phy_data_in);
end
end
`endif
endmodule
......@@ -26,7 +26,7 @@
// All references to doc = to SerialATA_Revision_2_6_Gold.pdf
module oob #(
parameter DATA_BYTE_WIDTH = 4,
parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
parameter CLK_SPEED_GRADE = 1 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
)
(
// sata clk = usrclk2
......@@ -59,6 +59,8 @@ module oob #(
input wire oob_start,
// connection established, all further data is valid
output wire oob_done,
// oob can't handle new start request
output wire oob_busy,
// doc p265, link is established after 3back-to-back non-ALIGNp
output wire link_up,
......@@ -104,7 +106,11 @@ module oob #(
localparam [19:0] CLK_TO_TIMER_CONTRIB = CLK_SPEED_GRADE == 1 ? 20'h4 :
CLK_SPEED_GRADE == 2 ? 20'h2 :
CLK_SPEED_GRADE == 4 ? 20'h1 : 20'h1;
`ifdef SIMULATION
localparam [19:0] TIMER_LIMIT = 19'd20000;
`else
localparam [19:0] TIMER_LIMIT = 19'd262140;
`endif
reg [19:0] timer;
wire timer_clr;
wire timer_fin;
......@@ -120,6 +126,25 @@ reg [DATA_BYTE_WIDTH - 1:0] rxcharisk;
wire detected_alignp;
wire detected_syncp;
// wait until device's cominit is done
reg cominit_req_l;
reg rxcominitdet_l;
reg rxcomwakedet_l;
wire rxcominit_done;
wire rxcomwake_done;
reg [9:0] rxcom_timer;
// for 75MHz : period of cominit = 426.7 ns = 32 ticks => need to wait x6 pulses + 1 as an insurance => 224 clock cycles. Same thoughts for comwake
localparam COMINIT_DONE_TIME = 896; // 300Mhz cycles
localparam COMWAKE_DONE_TIME = 448; // 300Mhz cycles
assign rxcominit_done = rxcom_timer == COMINIT_DONE_TIME & state_wait_cominit;
assign rxcomwake_done = rxcom_timer == COMWAKE_DONE_TIME & state_wait_comwake;
always @ (posedge clk) begin
cominit_req_l <= rst | rxcominit_done | ~state_idle ? 1'b0 : cominit_req ? 1'b1 : cominit_req_l;
rxcominitdet_l <= rst | rxcominit_done | ~state_wait_cominit ? 1'b0 : rxcominitdet ? 1'b1 : rxcominitdet_l;
rxcomwakedet_l <= rst | rxcomwake_done | ~state_wait_comwake ? 1'b0 : rxcomwakedet ? 1'b1 : rxcomwakedet_l;
end
// fsm, doc p265,266
wire state_idle;
reg state_wait_cominit;
......@@ -154,8 +179,8 @@ begin
end
assign set_wait_cominit = state_idle & oob_start & ~cominit_req;
assign set_wait_comwake = state_idle & cominit_req & cominit_allow | state_wait_cominit & rxcominitdet;
assign set_wait_align = state_wait_comwake & rxcomwakedet;
assign set_wait_comwake = state_idle & cominit_req_l & cominit_allow & rxcominit_done | state_wait_cominit & rxcominitdet_l & rxcominit_done;
assign set_wait_align = state_wait_comwake & rxcomwakedet_l & rxcomwake_done;
assign set_wait_synp = state_wait_align & detected_alignp;
assign set_wait_linkup = state_wait_synp & detected_syncp;
assign set_error = timer_fin & (state_wait_cominit | state_wait_comwake | state_wait_align | state_wait_synp/* | state_wait_linkup*/);
......@@ -168,9 +193,9 @@ assign clr_error = state_error;
// waiting timeout timer
assign timer_fin = timer == TIMER_LIMIT;
assign timer_clr = set_error | state_idle;
assign timer_clr = set_error | state_error | state_idle;
always @ (posedge clk)
timer <= rst ? 20'h0 : timer + CLK_TO_TIMER_CONTRIB;
timer <= rst | timer_clr ? 20'h0 : timer + CLK_TO_TIMER_CONTRIB;
// something is wrong with speed grades if the host cannot lock to device's alignp stream
assign oob_incompatible = state_wait_align & set_error;
......@@ -184,10 +209,13 @@ assign oob_silence = set_error & state_wait_cominit;
// other timeouts
assign oob_error = set_error & ~oob_silence & ~oob_incompatible;
// obvioud
assign oob_busy = ~state_idle;
// set gtx controls
reg txelecidle_r;
always @ (posedge clk)
txelecidle_r <= rst ? 1'b0 : clr_wait_cominit ? 1'b0 : set_wait_cominit ? 1'b1 : txelecidle_r;
txelecidle_r <= rst ? 1'b1 : /*clr_wait_cominit */ clr_wait_comwake ? 1'b0 : set_wait_cominit ? 1'b1 : txelecidle_r;
assign txcominit = set_wait_cominit;
assign txcomwake = set_wait_comwake;
......@@ -321,6 +349,9 @@ generate
end
endgenerate
always @ (posedge clk)
rxcom_timer <= rst | rxcominit_done & state_wait_cominit | rxcomwake_done & state_wait_comwake | rxcominitdet & state_wait_cominit | rxcomwakedet & state_wait_comwake ? 10'h0 : cominit_req_l & state_idle | rxcominitdet_l & state_wait_cominit | rxcomwakedet_l & state_wait_comwake ? rxcom_timer + CLK_TO_TIMER_CONTRIB : 10'h0;
// set data outputs to gtx
assign txdata_out = txdata;
assign txcharisk_out = txcharisk;
......
......@@ -21,7 +21,7 @@
`include "oob.v"
module oob_ctrl #(
parameter DATA_BYTE_WIDTH = 4,
parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
parameter CLK_SPEED_GRADE = 1 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
)
(
// sata clk = usrclk2
......@@ -80,6 +80,8 @@ wire oob_incompatible; // TODO
wire oob_error;
// noone responds to our cominits
wire oob_silence;
// obvious
wire oob_busy;
// for the resync sake
reg rxbyteisaligned_r;
......@@ -87,12 +89,12 @@ reg rxbyteisaligned_rr;
always @ (posedge clk)
begin
rxbyteisaligned_rr <= rxbyteisaligned_r;
rxbyteisaligned <= rxbyteisaligned;
rxbyteisaligned_r <= rxbyteisaligned;
end
// 1 - link is up and running, 0 - probably not
reg link_state;
// 1 - connection is being established, 0 - is not
// 1 - connection is being established OR already established, 0 - is not
reg oob_state;
assign phy_ready = link_state & gtx_ready & rxbyteisaligned_rr;
......@@ -101,11 +103,14 @@ always @ (posedge clk)
link_state <= (link_state | link_up) & ~link_down & ~rst;
always @ (posedge clk)
oob_state <= (oob_state | oob_start | cominit_req & cominit_allow) & ~oob_error & ~oob_silence & ~link_up & ~rst;
oob_state <= (oob_state | oob_start | cominit_req & cominit_allow) & ~oob_error & ~oob_silence & ~(link_down & ~oob_busy & ~oob_start) & ~rst;
// decide when to issue oob: always when gtx is ready
assign oob_start = gtx_ready & ~oob_state;
assign oob_start = gtx_ready & ~oob_state & ~oob_busy;
// set line to idle state before if we're waiting for a device to answer AND while oob sequence
wire txelecidle_inner;
assign txelecidle = /*~oob_state |*/ txelecidle_inner;
// let devices always begin oob sequence, if only it's not a glitch
assign cominit_allow = cominit_req & link_state;
......@@ -127,7 +132,7 @@ oob
// oob issues
.txcominit (txcominit),
.txcomwake (txcomwake),
.txelecidle (txelecidle),
.txelecidle (txelecidle_inner),
// input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in),
......@@ -162,7 +167,9 @@ oob
// timeout in an unexpected place
.oob_error (oob_error),
// noone responds to our cominits
.oob_silence (oob_silence)
.oob_silence (oob_silence),
// oob can't handle new start request
.oob_busy (oob_busy)
);
......
......@@ -24,13 +24,15 @@
`include "command.v"
module sata_host(
input wire rst,
input wire extrst,
// sata rst
output wire rst,
// sata clk
output wire clk,
// temporary
input wire [31:0] al_cmd_in; // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good; cmd_busy}
input wire al_cmd_val_in;
input wire [31:0] al_cmd_out; // same
input wire [31:0] al_cmd_in, // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good; cmd_busy}
input wire al_cmd_val_in,
output wire [31:0] al_cmd_out, // same
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
......@@ -51,13 +53,13 @@ module sata_host(
input wire al_sh_dev_val_in,
input wire [7:0] al_sh_control_in,
input wire al_sh_control_val_in,
input wire [31:0] al_sh_dma_id_lo_in
input wire [31:0] al_sh_dma_id_lo_in,
input wire al_sh_dma_id_lo_val_in,
input wire [31:0] al_sh_dma_id_hi_in,
input wire al_sh_dma_id_hi_val_in,
input wire [31:0] al_sh_buf_off_in,
input wire al_sh_buf_off_val_in,
input wire [31:0] al_sh_tran_cnt_in,
input wire [15:0] al_sh_tran_cnt_in,
input wire al_sh_tran_cnt_val_in,
input wire al_sh_autoact_in,
input wire al_sh_autoact_val_in,
......@@ -72,21 +74,48 @@ module sata_host(
input wire [3:0] al_sh_port_in,
input wire al_sh_port_val_in,
// outputs from shadow registers
output wire sh_data_val_out,
output wire [31:0] sh_data_out,
output wire [7:0] sh_control_out,
output wire [15:0] sh_feature_out,
output wire [47:0] sh_lba_out,
output wire [15:0] sh_count_out,
output wire [7:0] sh_command_out,
output wire [7:0] sh_err_out,
output wire [7:0] sh_status_out,
output wire [7:0] sh_estatus_out, // E_Status
output wire [7:0] sh_dev_out,
output wire [3:0] sh_port_out,
output wire sh_inter_out,
output wire sh_dir_out,
output wire [63:0] sh_dma_id_out,
output wire [31:0] sh_dma_off_out,
output wire [31:0] sh_dma_cnt_out,
output wire [15:0] sh_tran_cnt_out, // Transfer Count
output wire sh_notif_out,
output wire sh_autoact_out,
// top-level ifaces
// ref clk from an external source, shall be connected to pads
input wire extclk_p;
input wire extclk_n;
input wire extclk_p,
input wire extclk_n,
// sata physical link data pins
input wire txp_out;
input wire txn_out;
input wire rxp_in;
input wire rxn_in;
output wire txp_out,
output wire txn_out,
input wire rxp_in,
input wire rxn_in
);
wire rst;
// sata clk
wire clk;
/*
initial
begin
$dumpfile("dump.vcd");
$dumpvars(0, sata_host);
end
*/
parameter DATA_BYTE_WIDTH = 4;
// tl cmd iface
wire [2:0] cl2tl_cmd_type;
......@@ -110,38 +139,40 @@ wire cl2tl_data_strobe;
// from tl
wire [47:0] tl2cl_sh_lba_in;
wire [15:0] tl2cl_sh_count_in;
wire [7:0] tl2cl_sh_command_in;
wire [7:0] tl2cl_sh_err_in;
wire [7:0] tl2cl_sh_status_in;
wire [7:0] tl2cl_sh_estatus_in; // E_Status
wire [7:0] tl2cl_sh_dev_in;
wire [3:0] tl2cl_sh_port_in;
wire tl2cl_sh_inter_in;
wire tl2cl_sh_dir_in;
wire [63:0] tl2cl_sh_dma_id_in;
wire [31:0] tl2cl_sh_dma_off_in;
wire [31:0] tl2cl_sh_dma_cnt_in;
wire [15:0] tl2cl_sh_tran_cnt_in; // Transfer Count
wire tl2cl_sh_notif_in;
wire tl2cl_sh_autoact_in;
wire tl2cl_sh_lba_val_in;
wire tl2cl_sh_count_val_in;
wire tl2cl_sh_command_val_in;
wire tl2cl_sh_err_val_in;
wire tl2cl_sh_status_val_in;
wire tl2cl_sh_estatus_val_in; // E_Status
wire tl2cl_sh_dev_val_in;
wire tl2cl_sh_port_val_in;
wire tl2cl_sh_inter_val_in;
wire tl2cl_sh_dir_val_in;
wire tl2cl_sh_dma_id_val_in;
wire tl2cl_sh_dma_off_val_in;
wire tl2cl_sh_dma_cnt_val_in;
wire tl2cl_sh_tran_cnt_val_in; // Transfer Count
wire tl2cl_sh_notif_val_in;
wire tl2cl_sh_autoact_val_in;
wire [47:0] tl2cl_sh_lba;
wire [15:0] tl2cl_sh_count;
wire [7:0] tl2cl_sh_command;
wire [7:0] tl2cl_sh_err;
wire [7:0] tl2cl_sh_status;
wire [7:0] tl2cl_sh_estatus; // E_Status
wire [7:0] tl2cl_sh_dev;
wire [3:0] tl2cl_sh_port;
wire tl2cl_shter_in;
wire tl2cl_sh_dir;
wire tl2cl_sh_inter;
wire [63:0] tl2cl_sh_dma_id;
wire [31:0] tl2cl_sh_dma_off;
wire [31:0] tl2cl_sh_dma_cnt;
wire [15:0] tl2cl_sh_tran_cnt; // Transfer Count
wire tl2cl_sh_notif;
wire tl2cl_sh_autoact;
wire tl2cl_sh_lba_val;
wire tl2cl_sh_count_val;
wire tl2cl_sh_command_val;
wire tl2cl_sh_err_val;
wire tl2cl_sh_status_val;
wire tl2cl_sh_estatus_val; // E_Status
wire tl2cl_sh_dev_val;
wire tl2cl_sh_port_val;
wire tl2cl_shter_val_in;
wire tl2cl_sh_dir_val;
wire tl2cl_sh_inter_val;
wire tl2cl_sh_dma_id_val;
wire tl2cl_sh_dma_off_val;
wire tl2cl_sh_dma_cnt_val;
wire tl2cl_sh_tran_cnt_val; // Transfer Count
wire tl2cl_sh_notif_val;
wire tl2cl_sh_autoact_val;
// all regs to output
wire sh_data_val;
......@@ -165,6 +196,27 @@ wire [15:0] sh_tran_cnt; // Transfer Count
wire sh_notif;
wire sh_autoact;
assign sh_data_val_out = sh_data_val;
assign sh_data_out = sh_data;
assign sh_control_out = sh_control;
assign sh_feature_out = sh_feature;
assign sh_lba_out = sh_lba;
assign sh_count_out = sh_count;
assign sh_command_out = sh_command;
assign sh_err_out = sh_err;
assign sh_status_out = sh_status;
assign sh_estatus_out = sh_estatus;
assign sh_dev_out = sh_dev;
assign sh_port_out = sh_port;
assign sh_inter_out = sh_inter;
assign sh_dir_out = sh_dir;
assign sh_dma_id_out = sh_dma_id;
assign sh_dma_off_out = sh_dma_off;
assign sh_dma_cnt_out = sh_dma_cnt;
assign sh_tran_cnt_out = sh_tran_cnt;
assign sh_notif_out = sh_notif;
assign sh_autoact_out = sh_autoact;
command command(
.rst (rst),
.clk (clk),
......@@ -184,9 +236,9 @@ command command(
// data from tl
.tl_data_in (tl2cl_data),
.tl_data_val_in (tl2tl_data_val),
.tl_data_last_in (tl2tl_data_last),
.tl_data_busy_out (tl2tl_data_busy),
.tl_data_val_in (tl2cl_data_val),
.tl_data_last_in (tl2cl_data_last),
.tl_data_busy_out (tl2cl_data_busy),
// to tl
.tl_data_out (cl2tl_data),
.tl_data_last_out (cl2tl_data_last),
......@@ -234,60 +286,60 @@ command command(
.al_sh_port_val_in (al_sh_port_val_in),
// from tl
.tl_sh_lba_in (tl_sh_lba_in),
.tl_sh_count_in (tl_sh_count_in),
.tl_sh_command_in (tl_sh_command_in),
.tl_sh_err_in (tl_sh_err_in),
.tl_sh_status_in (tl_sh_status_in),
.tl_sh_estatus_in (tl_sh_estatus_in), // E_Status
.tl_sh_dev_in (tl_sh_dev_in),
.tl_sh_port_in (tl_sh_port_in),
.tl_sh_inter_in (tl_sh_inter_in),
.tl_sh_dir_in (tl_sh_dir_in),
.tl_sh_dma_id_in (tl_sh_dma_id_in),
.tl_sh_dma_off_in (tl_sh_dma_off_in),
.tl_sh_dma_cnt_in (tl_sh_dma_cnt_in),
.tl_sh_tran_cnt_in (tl_sh_tran_cnt_in), // Transfer Count
.tl_sh_notif_in (tl_sh_notif_in),
.tl_sh_autoact_in (tl_sh_autoact_in),
.tl_sh_lba_val_in (tl_sh_lba_val_in),
.tl_sh_count_val_in (tl_sh_count_val_in),
.tl_sh_command_val_in (tl_sh_command_val_in),
.tl_sh_err_val_in (tl_sh_err_val_in),
.tl_sh_status_val_in (tl_sh_status_val_in),
.tl_sh_estatus_val_in (tl_sh_estatus_val_in), // E_Status
.tl_sh_dev_val_in (tl_sh_dev_val_in),
.tl_sh_port_val_in (tl_sh_port_val_in),
.tl_sh_inter_val_in (tl_sh_inter_val_in),
.tl_sh_dir_val_in (tl_sh_dir_val_in),
.tl_sh_dma_id_val_in (tl_sh_dma_id_val_in),
.tl_sh_dma_off_val_in (tl_sh_dma_off_val_in),
.tl_sh_dma_cnt_val_in (tl_sh_dma_cnt_val_in),
.tl_sh_tran_cnt_val_in (tl_sh_tran_cnt_val_in), // Transfer Count
.tl_sh_notif_val_in (tl_sh_notif_val_in),
.tl_sh_autoact_val_in (tl_sh_autoact_val_in),
.tl_sh_lba_in (tl2cl_sh_lba),
.tl_sh_count_in (tl2cl_sh_count),
.tl_sh_command_in (tl2cl_sh_command),
.tl_sh_err_in (tl2cl_sh_err),
.tl_sh_status_in (tl2cl_sh_status),
.tl_sh_estatus_in (tl2cl_sh_estatus), // E_Status
.tl_sh_dev_in (tl2cl_sh_dev),
.tl_sh_port_in (tl2cl_sh_port),
.tl_sh_inter_in (tl2cl_sh_inter),
.tl_sh_dir_in (tl2cl_sh_dir),
.tl_sh_dma_id_in (tl2cl_sh_dma_id),
.tl_sh_dma_off_in (tl2cl_sh_dma_off),
.tl_sh_dma_cnt_in (tl2cl_sh_dma_cnt),
.tl_sh_tran_cnt_in (tl2cl_sh_tran_cnt), // Transfer Count
.tl_sh_notif_in (tl2cl_sh_notif),
.tl_sh_autoact_in (tl2cl_sh_autoact),
.tl_sh_lba_val_in (tl2cl_sh_lba_val),
.tl_sh_count_val_in (tl2cl_sh_count_val),
.tl_sh_command_val_in (tl2cl_sh_command_val),
.tl_sh_err_val_in (tl2cl_sh_err_val),
.tl_sh_status_val_in (tl2cl_sh_status_val),
.tl_sh_estatus_val_in (tl2cl_sh_estatus_val), // E_Status
.tl_sh_dev_val_in (tl2cl_sh_dev_val),
.tl_sh_port_val_in (tl2cl_sh_port_val),
.tl_sh_inter_val_in (tl2cl_sh_inter_val),
.tl_sh_dir_val_in (tl2cl_sh_dir_val),
.tl_sh_dma_id_val_in (tl2cl_sh_dma_id_val),
.tl_sh_dma_off_val_in (tl2cl_sh_dma_off_val),
.tl_sh_dma_cnt_val_in (tl2cl_sh_dma_cnt_val),
.tl_sh_tran_cnt_val_in (tl2cl_sh_tran_cnt_val), // Transfer Count
.tl_sh_notif_val_in (tl2cl_sh_notif_val),
.tl_sh_autoact_val_in (tl2cl_sh_autoact_val),
// all regs to output
.sh_data_val_out (sh_data_val_out),
.sh_data_out (sh_data_out),
.sh_control_out (sh_control_out),
.sh_feature_out (sh_feature_out),
.sh_lba_out (sh_lba_out),
.sh_count_out (sh_count_out),
.sh_command_out (sh_command_out),
.sh_err_out (sh_err_out),
.sh_status_out (sh_status_out),
.sh_estatus_out (sh_estatus_out), // E_Status
.sh_dev_out (sh_dev_out),
.sh_port_out (sh_port_out),
.sh_inter_out (sh_inter_out),
.sh_dir_out (sh_dir_out),
.sh_dma_id_out (sh_dma_id_out),
.sh_dma_off_out (sh_dma_off_out),
.sh_dma_cnt_out (sh_dma_cnt_out),
.sh_tran_cnt_out (sh_tran_cnt_out), // Transfer Count
.sh_notif_out (sh_notif_out),
.sh_autoact_out (sh_autoact_out)
.sh_data_val_out (sh_data_val),
.sh_data_out (sh_data),
.sh_control_out (sh_control),
.sh_feature_out (sh_feature),
.sh_lba_out (sh_lba),
.sh_count_out (sh_count),
.sh_command_out (sh_command),
.sh_err_out (sh_err),
.sh_status_out (sh_status),
.sh_estatus_out (sh_estatus), // E_Status
.sh_dev_out (sh_dev),
.sh_port_out (sh_port),
.sh_inter_out (sh_inter),
.sh_dir_out (sh_dir),
.sh_dma_id_out (sh_dma_id),
.sh_dma_off_out (sh_dma_off),
.sh_dma_cnt_out (sh_dma_cnt),
.sh_tran_cnt_out (sh_tran_cnt), // Transfer Count
.sh_notif_out (sh_notif),
.sh_autoact_out (sh_autoact)
);
// issue a frame
......@@ -340,7 +392,7 @@ wire ll2tl_data_busy;
// data outputs to LL
wire [DATA_BYTE_WIDTH*8 - 1:0] tl2ll_data;
// not implemented yet TODO
wire [DATA_BYTE_WIDTH*8 - 1:0] tl2ll_data_mask;
wire [DATA_BYTE_WIDTH/2 - 1:0] tl2ll_data_mask;
wire tl2ll_data_last;
wire tl2ll_data_val;
wire tl2ll_data_strobe;
......@@ -358,36 +410,36 @@ transport transport(
// link layer (LL) control
// issue a frame
.frame_req (frame_req),
.frame_req (tl2ll_frame_req),
// frame started to be transmitted
.frame_ack (frame_ack),
.frame_ack (tl2ll_frame_ack),
// frame issue was rejected because of incoming frame with higher priority
.frame_rej (frame_rej),
.frame_rej (tl2ll_frame_rej),
// LL is not ready to receive a frame request. frame_req shall be low if busy is asserted
.frame_busy (frame_busy),
.frame_busy (tl2ll_frame_busy),
// frame was transmitted w/o probles and successfully received @ a device side
.frame_done_good (frame_done_good),
.frame_done_good (tl2ll_frame_done_good),
// frame was transmitted, but device messages of problems with receiving
.frame_done_bad (frame_done_bad),
.frame_done_bad (tl2ll_frame_done_bad),
// LL reports of an incoming frame transmission. They're always allowed and have the highest priority
.incom_start (incom_start),
.incom_start (ll2tl_incom_start),
// LL reports of a completion of an incoming frame transmission.
.incom_done (incom_done),
.incom_done (ll2tl_incom_done),
// LL reports of errors in current FIS
.incom_invalidate (incom_invalidate), // TODO
.incom_invalidate (ll2tl_incom_invalidate), // TODO
// TL analyzes FIS and returnes if FIS makes sense.
.incom_ack_good (incom_ack_good),
.incom_ack_good (ll2tl_incom_ack_good),
// ... and if it doesn't
.incom_ack_bad (incom_ack_bad),
.incom_ack_bad (ll2tl_incom_ack_bad),
// transmission interrupts
// TL demands to brutally cancel current transaction TODO
.sync_escape_req (sync_escape_req),
.sync_escape_req (tl2ll_sync_escape_req),
// acknowlegement of a successful reception TODO
.sync_escape_ack (sync_escape_ack),
.sync_escape_ack (tl2ll_sync_escape_ack),
// TL demands to stop current recieving session TODO
.incom_stop_req (incom_stop_req),
.incom_stop_req (tl2ll_incom_stop_req),
// controls from a command layer (CL)
// FIS type, ordered by CL
......@@ -416,44 +468,44 @@ transport transport(
.sh_inter_in (sh_inter),
.sh_dir_in (sh_dir),
.sh_dma_id_in (sh_dma_id),
.sh_buf_off_in (sh_buf_off),
.sh_buf_off_in (sh_dma_off),
.sh_dma_cnt_in (sh_dma_cnt),
.sh_notif_in (sh_notif),
.sh_tran_cnt_in (sh_tran_cnt),
.sh_port_in (sh_port),
// TL decodes register writes and sends corresponding issues to CL
.sh_lba_out (tl2cl_sh_lba_out),
.sh_count_out (tl2cl_sh_count_out),
.sh_command_out (tl2cl_sh_command_out),
.sh_err_out (tl2cl_sh_err_out),
.sh_status_out (tl2cl_sh_status_out),
.sh_estatus_out (tl2cl_sh_estatus_out), // E_Status
.sh_dev_out (tl2cl_sh_dev_out),
.sh_port_out (tl2cl_sh_port_out),
.sh_inter_out (tl2cl_sh_inter_out),
.sh_dir_out (tl2cl_sh_dir_out),
.sh_dma_id_out (tl2cl_sh_dma_id_out),
.sh_dma_off_out (tl2cl_sh_dma_off_out),
.sh_dma_cnt_out (tl2cl_sh_dma_cnt_out),
.sh_tran_cnt_out (tl2cl_sh_tran_cnt_out), // Transfer Count
.sh_notif_out (tl2cl_sh_notif_out),
.sh_autoact_out (tl2cl_sh_autoact_out),
.sh_lba_val_out (tl2cl_sh_lba_val_out),
.sh_count_val_out (tl2cl_sh_count_val_out),
.sh_command_val_out (tl2cl_sh_command_val_out),
.sh_err_val_out (tl2cl_sh_err_val_out),
.sh_status_val_out (tl2cl_sh_status_val_out),
.sh_estatus_val_out (tl2cl_sh_estatus_val_out), // E_Status
.sh_dev_val_out (tl2cl_sh_dev_val_out),
.sh_port_val_out (tl2cl_sh_port_val_out),
.sh_inter_val_out (tl2cl_sh_inter_val_out),
.sh_dir_val_out (tl2cl_sh_dir_val_out),
.sh_dma_id_val_out (tl2cl_sh_dma_id_val_out),
.sh_dma_off_val_out (tl2cl_sh_dma_off_val_out),
.sh_dma_cnt_val_out (tl2cl_sh_dma_cnt_val_out),
.sh_tran_cnt_val_out (tl2cl_sh_tran_cnt_val_out), // Transfer Count
.sh_notif_val_out (tl2cl_sh_notif_val_out),
.sh_autoact_val_out (tl2cl_sh_autoact_val_out),
.sh_lba_out (tl2cl_sh_lba),
.sh_count_out (tl2cl_sh_count),
.sh_command_out (tl2cl_sh_command),
.sh_err_out (tl2cl_sh_err),
.sh_status_out (tl2cl_sh_status),
.sh_estatus_out (tl2cl_sh_estatus), // E_Status
.sh_dev_out (tl2cl_sh_dev),
.sh_port_out (tl2cl_sh_port),
.sh_inter_out (tl2cl_sh_inter),
.sh_dir_out (tl2cl_sh_dir),
.sh_dma_id_out (tl2cl_sh_dma_id),
.sh_dma_off_out (tl2cl_sh_dma_off),
.sh_dma_cnt_out (tl2cl_sh_dma_cnt),
.sh_tran_cnt_out (tl2cl_sh_tran_cnt), // Transfer Count
.sh_notif_out (tl2cl_sh_notif),
.sh_autoact_out (tl2cl_sh_autoact),
.sh_lba_val_out (tl2cl_sh_lba_val),
.sh_count_val_out (tl2cl_sh_count_val),
.sh_command_val_out (tl2cl_sh_command_val),
.sh_err_val_out (tl2cl_sh_err_val),
.sh_status_val_out (tl2cl_sh_status_val),
.sh_estatus_val_out (tl2cl_sh_estatus_val), // E_Status
.sh_dev_val_out (tl2cl_sh_dev_val),
.sh_port_val_out (tl2cl_sh_port_val),
.sh_inter_val_out (tl2cl_sh_inter_val),
.sh_dir_val_out (tl2cl_sh_dir_val),
.sh_dma_id_val_out (tl2cl_sh_dma_id_val),
.sh_dma_off_val_out (tl2cl_sh_dma_off_val),
.sh_dma_cnt_val_out (tl2cl_sh_dma_cnt_val),
.sh_tran_cnt_val_out (tl2cl_sh_tran_cnt_val), // Transfer Count
.sh_notif_val_out (tl2cl_sh_notif_val),
.sh_autoact_val_out (tl2cl_sh_autoact_val),
// shows if dma activate was received (a pulse)
......@@ -464,20 +516,20 @@ transport transport(
// LL data
// data inputs from LL
.ll_data_in (ll_data_in),
.ll_data_mask_in (ll_data_mask_in),
.ll_data_val_in (ll_data_val_in),
.ll_data_last_in (ll_data_last_in),
.ll_data_in (ll2tl_data),
.ll_data_mask_in (ll2tl_data_mask),
.ll_data_val_in (ll2tl_data_val),
.ll_data_last_in (ll2tl_data_last),
// transport layer tells if its inner buffer is almost full
.ll_data_busy_out (ll_data_busy_out),
.ll_data_busy_out (ll2tl_data_busy),
// data outputs to LL
.ll_data_out (ll_data_out),
.ll_data_out (tl2ll_data),
// not implemented yet TODO
.ll_data_mask_out (ll_data_mask_out),
.ll_data_last_out (ll_data_last_out),
.ll_data_val_out (ll_data_val_out),
.ll_data_strobe_in (ll_data_strobe_in),
.ll_data_mask_out (tl2ll_data_mask),
.ll_data_last_out (tl2ll_data_last),
.ll_data_val_out (tl2ll_data_val),
.ll_data_strobe_in (tl2ll_data_strobe),
// CL data
// required content is bypassed from ll, other is trimmed
......@@ -493,7 +545,7 @@ transport transport(
// data inputs from CL
.cl_data_in (cl2tl_data),
// not implemented yet TODO
.cl_data_mask_in (cl2tl_data_mask),
.cl_data_mask_in (2'b11),//cl2tl_data_mask),
.cl_data_last_in (cl2tl_data_last),
.cl_data_val_in (cl2tl_data_val),
.cl_data_strobe_out (cl2tl_data_strobe),
......@@ -508,18 +560,18 @@ transport transport(
// oob sequence is reinitiated and link now is not established or rxelecidle
wire link_reset,
wire link_reset;
// phy is ready - link is established
wire phy_ready,
wire phy_ready;
// data-primitives stream from phy
wire [DATA_BYTE_WIDTH*8 - 1:0] phy2ll_data;
wire [DATA_BYTE_WIDTH/2 - 1:0] phy2ll_isk; // charisk
wire [DATA_BYTE_WIDTH/2 - 1:0] phy2ll_err; // disperr | notintable
wire [DATA_BYTE_WIDTH - 1:0] phy2ll_isk; // charisk
wire [DATA_BYTE_WIDTH - 1:0] phy2ll_err; // disperr | notintable
// to phy
wire [DATA_BYTE_WIDTH*8 - 1:0] ll2phy_data;
wire [DATA_BYTE_WIDTH/2 - 1:0] ll2phy_isk; // charisk
wire [DATA_BYTE_WIDTH - 1:0] ll2phy_isk; // charisk
link link(
......@@ -540,7 +592,7 @@ link link(
// transaction's last data budle pulse
.data_last_in (tl2ll_data_last),
// read data is valid (if 0 while last pulse wasn't received => need to hold the line)
.data_val_in (tl2ll_val),
.data_val_in (tl2ll_data_val),
// data outputs to transport layer
// read data, same as related inputs
......@@ -551,7 +603,7 @@ link link(
// let the transport layer handle oveflows by himself
.data_val_out (ll2tl_data_val),
// transport layer tells if its inner buffer is almost full
.data_busy_in (ll2tl_busy),
.data_busy_in (ll2tl_data_busy),
.data_last_out (ll2tl_data_last),
// request for a new frame transition
......@@ -578,7 +630,7 @@ link link(
.incom_ack_bad (ll2tl_incom_ack_bad),
// oob sequence is reinitiated and link now is not established or rxelecidle
.link_reset (link_reset),
.link_reset (~phy_ready), //TODO mb it shall be independent
// TL demands to brutally cancel current transaction
.sync_escape_req (tl2ll_sync_escape_req),
// acknowlegement of a successful reception
......@@ -600,31 +652,34 @@ link link(
);
sata_phy phy(
.rst (rst),
// pll reset
.extrst (extrst),
// sata clk
.rst (rst),
// sata clk, generated in pll as usrclk2
.clk (clk),
.clk (clk),
// state
.phy_ready (phy_ready),
.phy_ready (phy_ready),
// top-level ifaces
// ref clk from an external source, shall be connected to pads
.extclk_p (extclk_p),
.extclk_n (extclk_n),
.extclk_p (extclk_p),
.extclk_n (extclk_n),
// sata link data pins
.txp_out (txp_out),
.txn_out (txn_out),
.rxp_in (rxp_in),
.rxn_in (rxn_in),
.txp_out (txp_out),
.txn_out (txn_out),
.rxp_in (rxp_in),
.rxn_in (rxn_in),
// to link layer
.ll_data_out (phy2ll_data),
.ll_charisk_out (phy2ll_isk),
.ll_data_out (phy2ll_data),
.ll_charisk_out (phy2ll_isk),
.ll_err_out (phy2ll_err),
// from link layer
.ll_data_in (ll2phy_data),
.ll_charisk_in (ll2phy_charisk)
.ll_data_in (ll2phy_data),
.ll_charisk_in (ll2phy_isk)
);
endmodule
......@@ -20,9 +20,11 @@
*******************************************************************************/
`include "oob_ctrl.v"
module sata_phy(
input wire rst,
// initial reset, resets PLL. After pll is locked, an internal sata reset is generated.
input wire extrst,
// sata clk, generated in pll as usrclk2
output wire clk,
output wire rst,
// state
output wire phy_ready,
......@@ -52,7 +54,7 @@ parameter CHIPSCOPE = "FALSE";
wire [31:0] txdata;
wire [3:0] txcharisk;
wire [63:0] rxdata;
wire [3:0] rxcharisk;
wire [7:0] rxcharisk;
wire [31:0] rxdata_out;
wire [31:0] txdata_in;
wire [3:0] txcharisk_in;
......@@ -68,6 +70,8 @@ wire rxelecidle;
wire txelecidle;
wire rxbyteisaligned;
wire gtx_ready;
oob_ctrl oob_ctrl(
// sata clk = usrclk2
......@@ -89,11 +93,11 @@ oob_ctrl oob_ctrl(
.txdata_in (txdata_in),
.txcharisk_in (txcharisk_in),
// output data stream to gtx
.txdata_out (txdata_out),
.txcharisk_out (txcharisk_out),
.txdata_out (txdata),
.txcharisk_out (txcharisk),
// input data from gtx
.rxdata_in (rxdata_in),
.rxcharisk_in (rxcharisk_in),
.rxdata_in (rxdata[31:0]),
.rxcharisk_in (rxcharisk[3:0]),
// bypassed data from gtx
.rxdata_out (rxdata_out),
.rxcharisk_out (rxcharisk_out),
......@@ -150,12 +154,27 @@ always @ (posedge gtrefclk)
*/
wire usrpll_locked;
assign cpllreset = rst;
assign cpllreset = extrst;
assign rxreset = ~cplllock | cpllreset;
assign txreset = ~cplllock | cpllreset;
assign rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done;
assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done;
assign gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone;
// generate internal reset after a clock is established
// !!!ATTENTION!!!
// async rst block
reg [7:0] rst_timer;
reg rst_r;
localparam [7:0] RST_TIMER_LIMIT = 8'b1000;
always @ (posedge clk or posedge extrst)
rst_timer <= extrst | ~cplllock | ~usrpll_locked ? 8'h0 : rst_timer == RST_TIMER_LIMIT ? rst_timer : rst_timer + 1'b1;
assign rst = rst_r;
always @ (posedge clk or posedge extrst)
rst_r <= extrst | ~|rst_timer ? 1'b0 : rst_timer[3] ? 1'b0 : 1'b1;
/*
* USRCLKs generation. USRCLK @ 150MHz, same as TXOUTCLK; USRCLK2 @ 75Mhz -> sata_clk === sclk
* It's recommended to use MMCM instead of PLL, whatever
......@@ -252,7 +271,7 @@ GTXE2_CHANNEL #(
.SIM_VERSION ("4.0"),
.ALIGN_COMMA_DOUBLE ("FALSE"),
.ALIGN_COMMA_ENABLE (10'b1111111111),
.ALIGN_COMMA_WORD (1),
.ALIGN_COMMA_WORD (2),
.ALIGN_MCOMMA_DET ("TRUE"),
.ALIGN_MCOMMA_VALUE (10'b1010000011),
.ALIGN_PCOMMA_DET ("TRUE"),
......@@ -372,7 +391,7 @@ GTXE2_CHANNEL #(
.PD_TRANS_TIME_TO_P2 (8'h64),
.SAS_MAX_COM (64),
.SAS_MIN_COM (36),
.SATA_BURST_SEQ_LEN (4'b0111),
.SATA_BURST_SEQ_LEN (4'b0110),
.SATA_BURST_VAL (3'b110),
.SATA_EIDLE_VAL (3'b110),
.SATA_MAX_BURST (8),
......@@ -445,7 +464,7 @@ GTXE2_CHANNEL #(
.RX_DFE_XYD_CFG (13'b0000000000000),
.TX_PREDRIVER_MODE (1'b0)
)
dut(
gtx(
.CPLLFBCLKLOST (),
.CPLLLOCK (cplllock),
.CPLLLOCKDETCLK (cplllockdetclk),
......@@ -675,22 +694,22 @@ dut(
.TX8B10BBYPASS (8'd0),
.TXPRBSSEL (3'd0),
.TXQPISENN (),
.TXQPISENP ()/*,
.TXQPISENP (),
.TXSYNCMODE (1'b0),
.TXSYNCALLIN (1'b0),
.TXSYNCIN (1'b0)*/
.TXSYNCIN (1'b0)
);
/*
* Interfaces
*/
assign cplllockdetclk = CLKIN_150;
assign drpclk = CLKIN_150;
assign cplllockdetclk = gtrefclk; //TODO
assign drpclk = gtrefclk;
assign clk = usrclk2;
assign rxn = rxn_in;
assign rxp = rxp_in;
assign txp_out = txn;
assign txn_out = txn;
assign txp_out = txp;
assign ll_data_out = rxdata_out;
assign ll_charisk_out = rxcharisk_out;
......
......@@ -38,7 +38,7 @@ reg [15:0] now;
reg [31:0] next;
always @ (posedge clk)
now <= rst ? 16'hf0f6 : val_in ? next : now;
now <= rst ? 16'hf0f6 : val_in ? next[31:16] : now;
assign data_out = val_in ? data_in ^ next : data_in;
......
......@@ -53,11 +53,11 @@ module transport #(
// transmission interrupts
// TL demands to brutally cancel current transaction TODO
input wire sync_escape_req,
output wire sync_escape_req,
// acknowlegement of a successful reception TODO
output wire sync_escape_ack,
input wire sync_escape_ack,
// TL demands to stop current recieving session TODO
input wire incom_stop_req,
output wire incom_stop_req,
// controls from a command layer (CL)
// FIS type, ordered by CL
......@@ -87,9 +87,9 @@ module transport #(
input wire sh_dir_in,
input wire [63:0] sh_dma_id_in,
input wire [31:0] sh_buf_off_in,
input wire [32:0] sh_dma_cnt_in,
input wire [31:0] sh_dma_cnt_in,
input wire sh_notif_in,
input wire [31:0] sh_tran_cnt_in,
input wire [15:0] sh_tran_cnt_in,
input wire [3:0] sh_port_in,
// TL decodes register writes and sends corresponding issues to CL
output wire [47:0] sh_lba_out,
......@@ -144,7 +144,7 @@ module transport #(
// data outputs to LL
output wire [DATA_BYTE_WIDTH*8 - 1:0] ll_data_out,
// not implemented yet TODO
output wire [DATA_BYTE_WIDTH*8 - 1:0] ll_data_mask_out,
output wire [DATA_BYTE_WIDTH/2 - 1:0] ll_data_mask_out,
output wire ll_data_last_out,
output wire ll_data_val_out,
input wire ll_data_strobe_in,
......@@ -176,6 +176,11 @@ module transport #(
output wire watchdog_dwords
);
//TODO
assign sync_escape_req = 1'b0;
assign incom_stop_req = 1'b0;
assign cl_data_strobe_out = 1'b0;
// How much time does device have to response on EOF
parameter [13:0] WATCHDOG_EOF_LIMIT = 14'd1000;
......@@ -1100,9 +1105,13 @@ assign cmd_busy = |state | frame_busy;
// respond if received FIS had any meaning in terms of TL
// actual response shall come next tick after done signal to fit LL fsm
reg incom_done_r;
reg incom_done_bad_r;
always @ (posedge clk)
incom_done_bad_r <= incom_done & state == STATE_IN_UNRECOG;
always @ (posedge clk)
incom_done_r <= incom_done;
assign incom_ack_bad = state == STATE_IN_UNRECOG & incom_done_r | bad_fis_received;
incom_done_r <= incom_done;
assign incom_ack_bad = incom_done_bad_r | bad_fis_received;
assign incom_ack_good = incom_done_r & ~incom_ack_bad;
// after a device says it received the FIS, reveal the error code
......@@ -1122,7 +1131,7 @@ assign header_dmas = dword_cnt[3:0] == 3'h0 ? {8'h0, 8'h0, sh_autoact_in,
dword_cnt[3:0] == 3'h1 ? {sh_dma_id_in[31:0]} : // DMA Buffer Identifier Low
dword_cnt[3:0] == 3'h2 ? {sh_dma_id_in[63:32]} : // DMA Buffer Identifier High
dword_cnt[3:0] == 3'h4 ? {sh_buf_off_in[31:0]} : // DMA Buffer Offset
dword_cnt[3:0] == 3'h5 ? {sh_tran_cnt_in[31:0]} : // DMA Transfer Count
dword_cnt[3:0] == 3'h5 ? {sh_dma_cnt_in[31:0]} : // DMA Transfer Count
/* 3'h3 | 3'h6 */ {32'h0000}; // Reserved
// BIST Activate FIS header
wire [31:0] header_bist; // TODO
......@@ -1149,6 +1158,7 @@ assign cl_data_val_out = ll_data_val_in & state == STATE_IN_DATA;
assign cl_data_last_out = ll_data_val_in & ll_data_last_in & state == STATE_IN_DATA;
assign cl_data_mask_out = ll_data_mask_in;
assign cl_data_out = ll_data_in & {32{cl_data_val_out}};
assign ll_data_busy_out = cl_data_busy_in;
// set data to ll: bypass payload from cl or headers constructed in here
assign ll_data_val_out = ll_header_val | cl_data_val_in;
......@@ -1163,6 +1173,8 @@ assign data_limit_exceeded = dword_cnt == 14'd2048 & ~cl_data_last_in;
wire chk_strobe_while_waitresp;
assign chk_strobe_while_waitresp = state == STATE_OUT_WAIT_RESP & ll_data_strobe_in;
// issue a FIS
assign frame_req = cmd_val & state == STATE_IDLE & ~frame_busy;
// update shadow registers as soon as transaction finishes TODO invalidate in case of errors
// TODO update only corresponding fields, which was updated during the transmission
......@@ -1216,7 +1228,7 @@ assign watchdog_eof = dword_cnt == WATCHDOG_EOF_LIMIT & state == STATE_OUT_WAIT
`ifdef CHECKERS_ENABLED
always @ (posedge clk)
if (~rst)
if (watchgod_eof)
if (watchdog_eof)
begin
$display("WARNING in %m: watchdog_eof asserted");
$stop;
......
//--------------------------------------------------------------------------------
// 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;
TOPLEVEL := sata_host
TOPLEVEL_LANG ?= verilog
PWD=$(shell pwd)
COCOTB=~/sata/git/x393_sata/coco
ifeq ($(OS),Msys)
WPWD=$(shell sh -c 'pwd -W')
PYTHONPATH := $(WPWD);$(PYTHONPATH)
else
WPWD=$(shell pwd)
PYTHONPATH := $(WPWD):$(PYTHONPATH)
endif
export PYTHONPATH
VERILOG_SOURCES = $(WPWD)/../sata_host.v $(WPWD)/../x393/glbl.v $(WPWD)/../GTXE2_CHANNEL.v
COMPILE_ARGS = -I$(WPWD)/../ -I$(WPWD)/../x393/ -I$(WPWD)/../x393/axi/ -I$(WPWD)/../host/ -y$(WPWD)/../x393/unisims -y$(WPWD)/../x393/util_modules/ -y$(WPWD)/../x393/wrap -y$(WPWD)/../x393/memctrl -D CHECKERS_ENABLED -D SIMULATION
GPI_IMPL := vpi
export TOPLEVEL_LANG
MODULE ?= test_host
include $(COCOTB)/makefiles/Makefile.inc
include $(COCOTB)/makefiles/Makefile.sim
import cocotb
from cocotb.triggers import Timer, RisingEdge
from cocotb.drivers import BusDriver
from cocotb.result import ReturnValue
import timescale
class SataHostDriver(BusDriver):
'''
shall drive sata_host interface
'''
_signals = ['al_cmd_in', 'al_cmd_val_in', 'al_cmd_out',
# shadow regs inputs
'al_sh_data_in', 'al_sh_data_val_in', 'al_sh_data_strobe_in',
'al_sh_feature_in', 'al_sh_feature_val_in', 'al_sh_lba_lo_in',
'al_sh_lba_lo_val_in', 'al_sh_lba_hi_in', 'al_sh_lba_hi_val_in',
'al_sh_count_in', 'al_sh_count_val_in', 'al_sh_command_in',
'al_sh_command_val_in', 'al_sh_dev_in', 'al_sh_dev_val_in',
'al_sh_control_in', 'al_sh_control_val_in', 'al_sh_dma_id_lo_in',
'al_sh_dma_id_lo_val_in', 'al_sh_dma_id_hi_in', 'al_sh_dma_id_hi_val_in',
'al_sh_buf_off_in', 'al_sh_buf_off_val_in', 'al_sh_tran_cnt_in',
'al_sh_tran_cnt_val_in', 'al_sh_autoact_in', 'al_sh_autoact_val_in',
'al_sh_inter_in', 'al_sh_inter_val_in', 'al_sh_dir_in',
'al_sh_dir_val_in', 'al_sh_dma_cnt_in', 'al_sh_dma_cnt_val_in',
'al_sh_notif_in', 'al_sh_notif_val_in', 'al_sh_port_in',
'al_sh_port_val_in',
# shadow regs outputs
'sh_data_val_out', 'sh_data_out', 'sh_control_out',
'sh_feature_out', 'sh_lba_out', 'sh_count_out',
'sh_command_out', 'sh_err_out', 'sh_status_out',
'sh_estatus_out', 'sh_dev_out', 'sh_port_out',
'sh_inter_out', 'sh_dir_out', 'sh_dma_id_out',
'sh_dma_off_out', 'sh_dma_cnt_out', 'sh_tran_cnt_out',
'sh_notif_out', 'sh_autoact_out']
def __init__(self, entity, name, clk):
BusDriver.__init__(self, entity, name, clk)
# initial interface states
self.bus.al_cmd_in.setimmediatevalue(0)
self.bus.al_cmd_val_in.setimmediatevalue(0)
self.bus.al_cmd_out.setimmediatevalue(0)
self.bus.al_sh_data_in.setimmediatevalue(0)
self.bus.al_sh_data_val_in.setimmediatevalue(0)
self.bus.al_sh_data_strobe_in.setimmediatevalue(0)
self.bus.al_sh_feature_in.setimmediatevalue(0)
self.bus.al_sh_feature_val_in.setimmediatevalue(0)
self.bus.al_sh_lba_lo_in.setimmediatevalue(0)
self.bus.al_sh_lba_lo_val_in.setimmediatevalue(0)
self.bus.al_sh_lba_hi_in.setimmediatevalue(0)
self.bus.al_sh_lba_hi_val_in.setimmediatevalue(0)
self.bus.al_sh_count_in.setimmediatevalue(0)
self.bus.al_sh_count_val_in.setimmediatevalue(0)
self.bus.al_sh_command_in.setimmediatevalue(0)
self.bus.al_sh_command_val_in.setimmediatevalue(0)
self.bus.al_sh_dev_in.setimmediatevalue(0)
self.bus.al_sh_dev_val_in.setimmediatevalue(0)
self.bus.al_sh_control_in.setimmediatevalue(0)
self.bus.al_sh_control_val_in.setimmediatevalue(0)
self.bus.al_sh_dma_id_lo_in.setimmediatevalue(0)
self.bus.al_sh_dma_id_lo_val_in.setimmediatevalue(0)
self.bus.al_sh_dma_id_hi_in.setimmediatevalue(0)
self.bus.al_sh_dma_id_hi_val_in.setimmediatevalue(0)
self.bus.al_sh_buf_off_in.setimmediatevalue(0)
self.bus.al_sh_buf_off_val_in.setimmediatevalue(0)
self.bus.al_sh_tran_cnt_in.setimmediatevalue(0)
self.bus.al_sh_tran_cnt_val_in.setimmediatevalue(0)
self.bus.al_sh_autoact_in.setimmediatevalue(0)
self.bus.al_sh_autoact_val_in.setimmediatevalue(0)
self.bus.al_sh_inter_in.setimmediatevalue(0)
self.bus.al_sh_inter_val_in.setimmediatevalue(0)
self.bus.al_sh_dir_in.setimmediatevalue(0)
self.bus.al_sh_dir_val_in.setimmediatevalue(0)
self.bus.al_sh_dma_cnt_in.setimmediatevalue(0)
self.bus.al_sh_dma_cnt_val_in.setimmediatevalue(0)
self.bus.al_sh_notif_in.setimmediatevalue(0)
self.bus.al_sh_notif_val_in.setimmediatevalue(0)
self.bus.al_sh_port_in.setimmediatevalue(0)
self.bus.al_sh_port_val_in.setimmediatevalue(0)
@cocotb.coroutine
def getCmd(self):
''' get the value of al_cmd register '''
raise ReturnValue(self.bus.al_cmd_out & 7 ) # get the last 3 bits
@cocotb.coroutine
def setCmd(self, cmd_type, cmd_port, cmd_val):
self.bus.al_cmd_in <= ((cmd_type << 5) + (cmd_port << 1) + (cmd_val)) << 3
self.bus.al_cmd_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_cmd_val_in <= 0
@cocotb.coroutine
def getReg(self, addr):
if addr == 0:
raise ReturnValue(self.bus.sh_data_out)
elif addr == 1:
raise ReturnValue(self.bus.sh_feature_out)
elif addr == 2:
raise ReturnValue(self.bus.sh_lba_out)
elif addr == 3:
raise ReturnValue(self.bus.sh_lba_out << 24)
elif addr == 4:
raise ReturnValue(self.bus.sh_count_out)
elif addr == 5:
raise ReturnValue(self.bus.sh_command_out)
elif addr == 6:
raise ReturnValue(self.bus.sh_dev_out)
elif addr == 7:
raise ReturnValue(self.bus.sh_control_out)
elif addr == 8:
raise ReturnValue(self.bus.sh_dma_id_out)
elif addr == 9:
raise ReturnValue(self.bus.sh_dma_id_out << 32)
elif addr == 10:
raise ReturnValue(self.bus.sh_dma_off_out)
elif addr == 11:
raise ReturnValue(self.bus.sh_tran_cnt_out)
elif addr == 12:
raise ReturnValue(self.bus.sh_autoact_out)
elif addr == 13:
raise ReturnValue(self.bus.sh_inter_out)
elif addr == 14:
raise ReturnValue(self.bus.sh_dir_out)
elif addr == 15:
raise ReturnValue(self.bus.al_cmd_out)
elif addr == 16:
raise ReturnValue(self.bus.sh_err_out)
elif addr == 17:
raise ReturnValue(self.bus.sh_status_out)
elif addr == 18:
raise ReturnValue(self.bus.sh_estatus_out)
elif addr == 19:
raise ReturnValue(self.bus.sh_port_out)
elif addr == 20:
raise ReturnValue(self.bus.sh_dma_cnt_out)
elif addr == 21:
raise ReturnValue(self.bus.sh_notif_out)
else:
raise ReturnValue(0)
@cocotb.coroutine
def setReg(self, addr, data):
if addr == 0:
self.bus.al_sh_data_in <= data
self.bus.al_sh_data_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_data_in <= 0
self.bus.al_sh_data_val_in <= 0
elif addr == 1:
self.bus.al_sh_feature_in <= data
self.bus.al_sh_feature_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_feature_in <= 0
self.bus.al_sh_feature_val_in <= 0
elif addr == 2:
self.bus.al_sh_lba_lo_in <= data
self.bus.al_sh_lba_lo_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_lba_lo_in <= 0
self.bus.al_sh_lba_lo_val_in <= 0
elif addr == 3:
self.bus.al_sh_lba_hi_in <= data
self.bus.al_sh_lba_hi_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_lba_hi_in <= 0
self.bus.al_sh_lba_hi_val_in <= 0
elif addr == 4:
self.bus.al_sh_count_in <= data
self.bus.al_sh_count_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_count_in <= 0
self.bus.al_sh_count_val_in <= 0
elif addr == 5:
self.bus.al_sh_command_in <= data
self.bus.al_sh_command_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_command_in <= 0
self.bus.al_sh_command_val_in <= 0
elif addr == 6:
self.bus.al_sh_dev_in <= data
self.bus.al_sh_dev_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_dev_in <= 0
self.bus.al_sh_dev_val_in <= 0
elif addr == 7:
self.bus.al_sh_control_in <= data
self.bus.al_sh_control_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_control_in <= 0
self.bus.al_sh_control_val_in <= 0
elif addr == 8:
self.bus.al_sh_dma_id_lo_in <= data
self.bus.al_sh_dma_id_lo_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_dma_id_lo_in <= 0
self.bus.al_sh_dma_id_lo_val_in <= 0
elif addr == 9:
self.bus.al_sh_dma_id_hi_in <= data
self.bus.al_sh_dma_id_hi_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_dma_id_hi_in <= 0
self.bus.al_sh_dma_id_hi_val_in <= 0
elif addr == 10:
self.bus.al_sh_dma_off_in <= data
self.bus.al_sh_dma_off_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_dma_off_in <= 0
self.bus.al_sh_dma_off_val_in <= 0
elif addr == 11:
self.bus.al_sh_tran_cnt_in <= data
self.bus.al_sh_tran_cnt_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_tran_cnt_in <= 0
self.bus.al_sh_tran_cnt_val_in <= 0
elif addr == 12:
self.bus.al_sh_autoact_in <= data
self.bus.al_sh_autoact_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_autoact_in <= 0
self.bus.al_sh_autoact_val_in <= 0
elif addr == 13:
self.bus.al_sh_inter_in <= data
self.bus.al_sh_inter_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_inter_in <= 0
self.bus.al_sh_inter_val_in <= 0
elif addr == 14:
self.bus.al_sh_dir_in <= data
self.bus.al_sh_dir_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_dir_in <= 0
self.bus.al_sh_dir_val_in <= 0
elif addr == 19:
self.bus.al_sh_port_in <= data
self.bus.al_sh_port_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_port_in <= 0
self.bus.al_sh_port_val_in <= 0
elif addr == 20:
self.bus.al_sh_dma_cnt_in <= data
self.bus.al_sh_dma_cnt_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_dma_cnt_in <= 0
self.bus.al_sh_dma_cnt_val_in <= 0
elif addr == 21:
self.bus.al_sh_notif_in <= data
self.bus.al_sh_notif_val_in <= 1
yield RisingEdge(self.clock)
self.bus.al_sh_notif_in <= 0
self.bus.al_sh_notif_val_in <= 0
import cocotb
from cocotb.triggers import Timer, RisingEdge
from cocotb.drivers import BusDriver
from cocotb.result import ReturnValue
class SataHalfWord(BusDriver):
''' Every 8 bits -> 10 on phy line '''
def __init__(self, data, control):
self.data = [].append(data)
self.control = [].append(control)
class SataPhyDriver(BusDriver):
_signals = ['txp_out', 'txn_out', 'rxp_in', 'rxp_out']
def __init__(self, entity, name, clock, gen):
''' The clock shall be serial '''
BusDriver.__init__(self, entity, name, clock)
# outcoming elecidle flag
self.txelecidle = 1
# queue of *parallel* values to send
self.sq = []
# stream trace of received parallel values
self.rq = []
# sata generation (~ clock frequency)
self.gen = gen
self.driveBit(0)
# Queues management section
def addHalfWord(self, hword):
self.sq = self.sq.append(hword)
# elecidle management section
def setElecIdle(self):
self.txelecidle = 1
def unsetElecIdle(self):
self.txelecidle = 0
# Data send section
def driveBit(self, value):
if txelecidle:
self.bus.txp_out.setimmediatevalue('z')
self.bus.txn_out.setimmediatevalue('z')
elif value == 1:
self.bus.txp_out.setimmediatevalue(1)
self.bus.txn_out.setimmediatevalue(0)
elif value == 0:
self.bus.txp_out.setimmediatevalue(0)
self.bus.txn_out.setimmediatevalue(1)
else:
self.bus.txp_out.setimmediatevalue(value)
self.bus.txn_out.setimmediatevalue(value)
yield RisingEdge(self.clock)
def serial(self, parallel):
for i in range(9, -1, -1):
value = '{0:b}'.format(parallel)[i]
driveBit(value)
def sendQueue(self):
for hword in self.sq:
serial(self, hword)
class SataPhyMonitor(BusMonitor):
_signals = ['txp_out', 'txn_out', 'rxp_in', 'rxp_out']
def __init__(self, *args, **kwargs):
BusMOnitor.__init__(self, *arggs, **kwargs)
# Data receive section
def getBit(self)
yield RisingEdge(self.clock)
return self.bus.txp_out.getValue()
def getHalfWord(self):
hword = ''
for i in range(9, -1, -1):
hword.append(getBit)
return hword
def alignReciever(self):
''' look for a comma character in a bitstream
returns running disparity value, when comma occurs '''
# get an initial hword
hword = ''
for i in range(9, -1, -1):
hword.append(getBit)
# shift until we meet a comma
while True:
if hword == '0011111010':
disparity = 1
break
elif hword == '1100000101':
disparity = 0
break
else
hword.pop(1)
hword.append(getBit)
return disparity
def decodeHalfWord(self):
pass
# oob
def monitorElecidle(self):
import timescale
import cocotb
from cocotb.triggers import Timer, RisingEdge, FallingEdge
from driver_host import SataHostDriver
TIMESCALE = 1000 # in ps
@cocotb.coroutine
def issueReset(rst, length):
rst <= 1
yield Timer(length * TIMESCALE)
rst <= 0
@cocotb.coroutine
def setClk(clk, halfperiod):
while True:
clk <= 0
yield Timer(halfperiod * TIMESCALE)
clk <= 1
yield Timer(halfperiod * TIMESCALE)
@cocotb.coroutine
def setDiffClk(clkp, clkn, halfperiod):
while True:
clkp <= 0
clkn <= 1
yield Timer(halfperiod * TIMESCALE)
clkp <= 1
clkn <= 0
yield Timer(halfperiod * TIMESCALE)
@cocotb.test()
def basic_test(dut):
cocotb.fork(setDiffClk(dut.extclk_p, dut.extclk_n, 3.333))
dut.rst = 0
yield Timer(30 * TIMESCALE)
yield issueReset(dut.extrst, 1050)
shadow = SataHostDriver(dut, "", dut.clk)
yield FallingEdge(dut.rst)
# set random data to shadow registers
yield RisingEdge(dut.clk)
cocotb.fork(shadow.setReg(1,0xe))
cocotb.fork(shadow.setReg(4,0xdead))
cocotb.fork(shadow.setReg(5,0xbee1))
yield Timer(100 * TIMESCALE)
# write registers to a device
yield RisingEdge(dut.clk)
# cocotb.fork(shadow.setCmd(cmd_type = 1, cmd_port = 0, cmd_val = 1))
yield Timer(40000 * TIMESCALE)
TIMESCALE = 1000; # in ps
......@@ -17,7 +17,7 @@ if [ "$GTX_PATH" == '' ]
then
export GTX_PATH=$SATA_PATH
fi
iverilog -Wall $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v -I$SATA_PATH/tb -I$SATA_PATH -I$SATA_PATH/x393/axi -I$SATA_PATH/x393 -y$SATA_PATH/x393/util_modules -y$SATA_PATH/x393/wrap -y$UNISIMS_PATH -y$SATA_PATH/x393/memctrl -y$SATA_PATH/x393/axi -y$SATA_PATH/x393/simulation_modules $SATA_PATH/x393/simulation_modules/simul_axi_fifo_out.v -y$SATA_PATH/x393/
iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v $SATA_PATH/gtxe2_gpl/GTXE2_CHANNEL.v -I$SATA_PATH/device -I$SATA_PATH/host -I$SATA_PATH/dma -I$SATA_PATH/tb -I$SATA_PATH -I$SATA_PATH/x393/axi -I$SATA_PATH/x393 -y$SATA_PATH/x393/util_modules -y$SATA_PATH/x393/wrap -y$UNISIMS_PATH -y$SATA_PATH/x393/memctrl -y$SATA_PATH/x393/axi -y$SATA_PATH/x393/simulation_modules $SATA_PATH/x393/simulation_modules/simul_axi_fifo_out.v -y$SATA_PATH/x393/ -D SIMULATION -D CHECKERS_ENABLED
#iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v -f opts -stb -sglbl $1 2>&1| tee $LOGFILE_PATH
......
......@@ -11,7 +11,8 @@ if [ $? != 0 ]
then
echo "BUILD FAILED"
exit
else
gtkwave test.vcd $SAV_FILE &> waves.log &
fi
gtkwave test.vcd $SAV_FILE &> waves.log &
echo all done
......@@ -23,6 +23,7 @@
*/
`timescale 1ns/1ps
`include "top.v"
`include "sata_device.v"
module tb #(
`include "includes/x393_parameters.vh" // SuppressThisWarning VEditor - not used
......@@ -330,17 +331,34 @@ simul_axi_read #(
.burst(), // burst in progress - just debug
.err_out()); // data last does not match predicted or FIFO over/under run - just debug
reg EXT_REF_CLK_P = 1'b1;
reg EXT_REF_CLK_N = 1'b0;
reg EXTCLK_P = 1'b1;
reg EXTCLK_N = 1'b0;
reg serial_clk = 1'b1;
// device-under-test instance
wire rxn;
wire rxp;
wire txn;
wire txp;
wire device_rst;
top dut(
.RXN (1'b0),
.RXP (1'b0),
.TXN (),
.TXP (),
.REFCLK_PAD_P_IN (EXT_REF_CLK_P),
.REFCLK_PAD_N_IN (EXT_REF_CLK_N)
.RXN (rxn),
.RXP (rxp),
.TXN (txn),
.TXP (txp),
.EXTCLK_P (EXTCLK_P),
.EXTCLK_N (EXTCLK_N)
);
assign device_rst = dut.axi_rst;
sata_device dev(
.rst (device_rst),
.RXN (txn),
.RXP (txp),
.TXN (rxn),
.TXP (rxp),
.EXTCLK_P (EXTCLK_P),
.EXTCLK_N (EXTCLK_N)
);
// SAXI HP interface
......
......@@ -26,10 +26,12 @@
always #3.333
begin
EXT_REF_CLK_P = ~EXT_REF_CLK_P;
EXT_REF_CLK_N = ~EXT_REF_CLK_N;
EXTCLK_P = ~EXTCLK_P;
EXTCLK_N = ~EXTCLK_N;
end
integer i;
integer status;
// write registers
initial
begin
......@@ -48,6 +50,7 @@ begin
repeat (20) @(posedge CLK) ;
RST =1'b0;
@ (negedge dut.sata_top.sata_rst);
repeat (20)
@ (posedge CLK);
// test MAXI1 inface
......@@ -59,17 +62,118 @@ begin
axi_write_single(32'h8, 32'hd34db33f);
axi_read_addr(12'h555, 32'h0, 4'h3, 2'b01);
for (i = 0; i < 2048; i = i + 1) begin
dev.receive_data_pause[i] = 32'h0;
end
dev.receive_wait_fifo = 0;
// issue Identify Device command
// ATAPI command id = EC
axi_write_single({30'h5, 2'b00}, 32'hEC);
// start!
axi_write_single({30'hf, 2'b00}, 32'h0108);
$display("[Test] H2D Reg with pio cmd issued");
// wait until reception
while (dev.receive_id != 1) begin
repeat (100)
@ (posedge dev.clk);
end
if (dev.receive_status != 0) begin
$display("[Test] Failed step");
$finish;
end
$display("[Test] H2D Reg with pio cmd received by dev");
// send dev2host reg fis with BSY flag
repeat (100)
@ (posedge dev.clk);
for (i = 0; i < 2048; i = i + 1) begin
dev.transmit_data_pause[i] = 32'h0;
end
dev.transmit_data[0] = 32'h00800034; // BSY -> 1, type = dev2host reg
dev.transmit_data[1] = 32'hdeadbeef; // whatever
dev.transmit_data[2] = 32'hdeadbeef; // whatever
dev.transmit_data[3] = 32'hdeadbeef; // whatever
dev.transmit_data[4] = 32'hdeadbeef; // whatever
dev.linkTransmitFIS(66, 4, 0, status);
$display("[Test] Dev sent BSY flag");
// checks if BSY is set up // only on waves TODO
axi_read_addr(12'h555, {30'h11, 2'b00}, 4'h3, 2'b01);
repeat (50)
@ (posedge dev.clk);
repeat (1000)
@ (posedge dev.clk);
for (i = 0; i < 32; i = i + 1) begin
$display("data received : %h", dev.receive_data[i]);
end
$display("============= DONE =============");
$finish;
// test SAXI3 iface
afi_setup(3);
/* afi_setup(3);
axi_write_single(32'h10, 32'h0add9e55); // addr
axi_write_single(32'h14, 32'h12345678); // lba
axi_write_single(32'h18, 32'h00000020); // sector count
axi_write_single(32'h20, 32'h00100000); // dma type
axi_write_single(32'h24, 32'h00010000); // start
/* axi_write_single(32'h28, 32'hdeadbee2); // data
axi_write_single(32'h28, 32'hdeadbee2); // data
axi_write_single(32'h2c, 32'hdeadbee3); // data
axi_write_single(32'h1c, 32'hffffffff); // start */
end
/*
// control the device
reg [112:0] rprim;
integer status;
initial
#10000 $finish;
begin
@ (posedge dev.phy_ready);
repeat (30)
@ (posedge dev.clk);
dev.linkSendPrim("XRDY");
rprim = dev.linkGetPrim(0);
while (rprim != "RRDY") begin
if (rprim != "SYNC") begin
$display("Expected SYNC primitive, got %8s", rprim);
$finish;
end
@ (posedge dev.clk)
rprim = dev.linkGetPrim(0);
end
dev.linkSendPrim("SYNC");
repeat (30)
@ (posedge dev.clk);
for (i = 0; i < 2048; i = i + 1) begin
dev.transmit_data[i] = 32'hdeadbeef;
dev.transmit_data_pause[i] = 32'h0;
end
// dev.transmit_crc = 32'hfd60f8a6;
dev.transmit_crc = 32'hfd60f8a5;
dev.linkTransmitFIS(66, 12, status);
$display("Fis %d transmitted, status %d", 66, status);
repeat (1000)
@ (posedge dev.clk);
$display("============= DONE =============");
$finish;
end
*/
initial begin
#100000;
$display("============= TIMELIMIT =============");
$finish;
end
/*******************************************************************************
* Module: top
* Date: 2015-07-11
* Author: Alexey
* Description: top-level module, instantiates PS7 + sata host controller
*
* Copyright (c) 2015 Elphel, Inc.
* top.v 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.
*
* top.v file 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/> .
*******************************************************************************/
/*
* all signals' and modules' names and interconnections are taken from x393.v
* to make the final integration easier - just to make an instance of
* what is called now 'axi_regs' and connect it
*/
`include "system_defines.vh"
`include "axi_regs.v"
module top #(
`include "includes/x393_parameters.vh"
)
(
);
wire [3:0] fclk;
wire [3:0] frst;
wire axi_aclk;
wire axi_rst;
wire comb_rst;
wire [31:0] ARADDR;
wire ARVALID;
wire ARREADY;
wire [11:0] ARID;
wire [1:0] ARLOCK;
wire [3:0] ARCACHE;
wire [2:0] ARPROT;
wire [3:0] ARLEN;
wire [1:0] ARSIZE;
wire [1:0] ARBURST;
wire [3:0] ARQOS;
wire [31:0] RDATA;
wire RVALID;
wire RREADY;
wire [11:0] RID;
wire RLAST;
wire [1:0] RRESP;
wire [31:0] AWADDR;
wire AWVALID;
wire AWREADY;
wire [11:0] AWID;
wire [1:0] AWLOCK;
wire [3:0] AWCACHE;
wire [2:0] AWPROT;
wire [3:0] AWLEN;
wire [1:0] AWSIZE;
wire [1:0] AWBURST;
wire [3:0] AWQOS;
wire [31:0] WDATA;
wire WVALID;
wire WREADY;
wire [11:0] WID;
wire WLAST;
wire [3:0] WSTRB;
wire BVALID;
wire BREADY;
wire [11:0] BID;
wire [1:0] BRESP;
reg axi_rst_pre;
assign comb_rst=~frst[0] | frst[1];
always @(posedge comb_rst or posedge axi_aclk) begin
if (comb_rst) axi_rst_pre <= 1'b1;
else axi_rst_pre <= 1'b0;
end
BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0]));
BUFG bufg_axi_rst_i (.O(axi_rst),.I(axi_rst_pre));
axi_regs axi_regs(
.ACLK (axi_aclk),
.ARESETN (axi_rst),
.ARADDR (ARADDR),
.ARVALID (ARVALID),
.ARREADY (ARREADY),
.ARID (ARID),
.ARLOCK (ARLOCK),
.ARCACHE (ARCACHE),
.ARPROT (ARPROT),
.ARLEN (ARLEN),
.ARSIZE (ARSIZE),
.ARBURST (ARBURST),
.ARQOS (ARQOS),
.RDATA (RDATA),
.RVALID (RVALID),
.RREADY (RREADY),
.RID (RID),
.RLAST (RLAST),
.RRESP (RRESP),
.AWADDR (AWADDR),
.AWVALID (AWVALID),
.AWREADY (AWREADY),
.AWID (AWID),
.AWLOCK (AWLOCK),
.AWCACHE (AWCACHE),
.AWPROT (AWPROT),
.AWLEN (AWLEN),
.AWSIZE (AWSIZE),
.AWBURST (AWBURST),
.AWQOS (AWQOS),
.WDATA (WDATA),
.WVALID (WVALID),
.WREADY (WREADY),
.WID (WID),
.WLAST (WLAST),
.WSTRB (WSTRB),
.BVALID (BVALID),
.BREADY (BREADY),
.BID (BID),
.BRESP (BRESP)
);
PS7 ps7_i (
// EMIO interface
// CAN interface
.EMIOCAN0PHYTX(), // CAN 0 TX, output
.EMIOCAN0PHYRX(), // CAN 0 RX, input
.EMIOCAN1PHYTX(), // Can 1 TX, output
.EMIOCAN1PHYRX(), // CAN 1 RX, input
// GMII 0
.EMIOENET0GMIICRS(), // GMII 0 Carrier sense, input
.EMIOENET0GMIICOL(), // GMII 0 Collision detect, input
.EMIOENET0EXTINTIN(), // GMII 0 Controller Interrupt input, input
// GMII 0 TX signals
.EMIOENET0GMIITXCLK(), // GMII 0 TX clock, input
.EMIOENET0GMIITXD(), // GMII 0 Tx Data[7:0], output
.EMIOENET0GMIITXEN(), // GMII 0 Tx En, output
.EMIOENET0GMIITXER(), // GMII 0 Tx Err, output
// GMII 0 TX timestamp signals
.EMIOENET0SOFTX(), // GMII 0 Tx Tx Start-of-Frame, output
.EMIOENET0PTPDELAYREQTX(), // GMII 0 Tx PTP delay req frame detected, output
.EMIOENET0PTPPDELAYREQTX(), // GMII 0 Tx PTP peer delay frame detect, output
.EMIOENET0PTPPDELAYRESPTX(), // GMII 0 Tx PTP pear delay response frame detected, output
.EMIOENET0PTPSYNCFRAMETX(), // GMII 0 Tx PTP sync frame detected, output
// GMII 0 RX signals
.EMIOENET0GMIIRXCLK(), // GMII 0 Rx Clock, input
.EMIOENET0GMIIRXD(), // GMII 0 Rx Data (7:0), input
.EMIOENET0GMIIRXDV(), // GMII 0 Rx Data valid, input
.EMIOENET0GMIIRXER(), // GMII 0 Rx Error, input
// GMII 0 RX timestamp signals
.EMIOENET0SOFRX(), // GMII 0 Rx Start of Frame, output
.EMIOENET0PTPDELAYREQRX(), // GMII 0 Rx PTP delay req frame detected
.EMIOENET0PTPPDELAYREQRX(), // GMII 0 Rx PTP peer delay frame detected, output
.EMIOENET0PTPPDELAYRESPRX(), // GMII 0 Rx PTP peer delay responce frame detected, output
.EMIOENET0PTPSYNCFRAMERX(), // GMII 0 Rx PTP sync frame detected, output
// MDIO 0
.EMIOENET0MDIOMDC(), // MDIO 0 MD clock output, output
.EMIOENET0MDIOO(), // MDIO 0 MD data output, output
.EMIOENET0MDIOTN(), // MDIO 0 MD data 3-state, output
.EMIOENET0MDIOI(), // MDIO 0 MD data input, input
// GMII 1
.EMIOENET1GMIICRS(), // GMII 1 Carrier sense, input
.EMIOENET1GMIICOL(), // GMII 1 Collision detect, input
.EMIOENET1EXTINTIN(), // GMII 1 Controller Interrupt input, input
// GMII 1 TX signals
.EMIOENET1GMIITXCLK(), // GMII 1 TX clock, input
.EMIOENET1GMIITXD(), // GMII 1 Tx Data[7:0], output
.EMIOENET1GMIITXEN(), // GMII 1 Tx En, output
.EMIOENET1GMIITXER(), // GMII 1 Tx Err, output
// GMII 1 TX timestamp signals
.EMIOENET1SOFTX(), // GMII 1 Tx Tx Start-of-Frame, output
.EMIOENET1PTPDELAYREQTX(), // GMII 1 Tx PTP delay req frame detected, output
.EMIOENET1PTPPDELAYREQTX(), // GMII 1 Tx PTP peer delay frame detect, output
.EMIOENET1PTPPDELAYRESPTX(), // GMII 1 Tx PTP pear delay response frame detected, output
.EMIOENET1PTPSYNCFRAMETX(), // GMII 1 Tx PTP sync frame detected, output
// GMII 1 RX signals
.EMIOENET1GMIIRXCLK(), // GMII 1 Rx Clock, input
.EMIOENET1GMIIRXD(), // GMII 1 Rx Data (7:0), input
.EMIOENET1GMIIRXDV(), // GMII 1 Rx Data valid, input
.EMIOENET1GMIIRXER(), // GMII 1 Rx Error, input
// GMII 1 RX timestamp signals
.EMIOENET1SOFRX(), // GMII 1 Rx Start of Frame, output
.EMIOENET1PTPDELAYREQRX(), // GMII 1 Rx PTP delay req frame detected
.EMIOENET1PTPPDELAYREQRX(), // GMII 1 Rx PTP peer delay frame detected, output
.EMIOENET1PTPPDELAYRESPRX(), // GMII 1 Rx PTP peer delay responce frame detected, output
.EMIOENET1PTPSYNCFRAMERX(), // GMII 1 Rx PTP sync frame detected, output
// MDIO 1
.EMIOENET1MDIOMDC(), // MDIO 1 MD clock output, output
.EMIOENET1MDIOO(), // MDIO 1 MD data output, output
.EMIOENET1MDIOTN(), // MDIO 1 MD data 3-state, output
.EMIOENET1MDIOI(), // MDIO 1 MD data input, input
// EMIO GPIO
.EMIOGPIOO(), // EMIO GPIO Data out[63:0], output
.EMIOGPIOI(/*gpio_in[63:0]*/), // EMIO GPIO Data in[63:0], input
.EMIOGPIOTN(), // EMIO GPIO OutputEnable[63:0], output
// EMIO I2C 0
.EMIOI2C0SCLO(), // I2C 0 SCL OUT, output // manual says input
.EMIOI2C0SCLI(), // I2C 0 SCL IN, input // manual says output
.EMIOI2C0SCLTN(), // I2C 0 SCL EN, output // manual says input
.EMIOI2C0SDAO(), // I2C 0 SDA OUT, output // manual says input
.EMIOI2C0SDAI(), // I2C 0 SDA IN, input // manual says output
.EMIOI2C0SDATN(), // I2C 0 SDA EN, output // manual says input
// EMIO I2C 1
.EMIOI2C1SCLO(), // I2C 1 SCL OUT, output // manual says input
.EMIOI2C1SCLI(), // I2C 1 SCL IN, input // manual says output
.EMIOI2C1SCLTN(), // I2C 1 SCL EN, output // manual says input
.EMIOI2C1SDAO(), // I2C 1 SDA OUT, output // manual says input
.EMIOI2C1SDAI(), // I2C 1 SDA IN, input // manual says output
.EMIOI2C1SDATN(), // I2C 1 SDA EN, output // manual says input
// JTAG
.EMIOPJTAGTCK(), // JTAG TCK, input
.EMIOPJTAGTMS(), // JTAG TMS, input
.EMIOPJTAGTDI(), // JTAG TDI, input
.EMIOPJTAGTDO(), // JTAG TDO, output
.EMIOPJTAGTDTN(), // JTAG TDO OE, output
// SDIO 0
.EMIOSDIO0CLKFB(), // SDIO 0 Clock feedback, input
.EMIOSDIO0CLK(), // SDIO 0 Clock, output
.EMIOSDIO0CMDI(), // SDIO 0 Command in, input
.EMIOSDIO0CMDO(), // SDIO 0 Command out, output
.EMIOSDIO0CMDTN(), // SDIO 0 command OE, output
.EMIOSDIO0DATAI(), // SDIO 0 Data in [3:0], input
.EMIOSDIO0DATAO(), // SDIO 0 Data out [3:0], output
.EMIOSDIO0DATATN(), // SDIO 0 Data OE [3:0], output
.EMIOSDIO0CDN(), // SDIO 0 Card detect, input
.EMIOSDIO0WP(), // SDIO 0 Write protect, input
.EMIOSDIO0BUSPOW(), // SDIO 0 Power control, output
.EMIOSDIO0LED(), // SDIO 0 LED control, output
.EMIOSDIO0BUSVOLT(), // SDIO 0 Bus voltage [2:0], output
// SDIO 1
.EMIOSDIO1CLKFB(), // SDIO 1 Clock feedback, input
.EMIOSDIO1CLK(), // SDIO 1 Clock, output
.EMIOSDIO1CMDI(), // SDIO 1 Command in, input
.EMIOSDIO1CMDO(), // SDIO 1 Command out, output
.EMIOSDIO1CMDTN(), // SDIO 1 command OE, output
.EMIOSDIO1DATAI(), // SDIO 1 Data in [3:0], input
.EMIOSDIO1DATAO(), // SDIO 1 Data out [3:0], output
.EMIOSDIO1DATATN(), // SDIO 1 Data OE [3:0], output
.EMIOSDIO1CDN(), // SDIO 1 Card detect, input
.EMIOSDIO1WP(), // SDIO 1 Write protect, input
.EMIOSDIO1BUSPOW(), // SDIO 1 Power control, output
.EMIOSDIO1LED(), // SDIO 1 LED control, output
.EMIOSDIO1BUSVOLT(), // SDIO 1 Bus voltage [2:0], output
// SPI 0
.EMIOSPI0SCLKI(), // SPI 0 CLK in , input
.EMIOSPI0SCLKO(), // SPI 0 CLK out, output
.EMIOSPI0SCLKTN(), // SPI 0 CLK OE, output
.EMIOSPI0SI(), // SPI 0 MOSI in , input
.EMIOSPI0MO(), // SPI 0 MOSI out , output
.EMIOSPI0MOTN(), // SPI 0 MOSI OE, output
.EMIOSPI0MI(), // SPI 0 MISO in, input
.EMIOSPI0SO(), // SPI 0 MISO out, output
.EMIOSPI0STN(), // SPI 0 MISO OE, output
.EMIOSPI0SSIN(), // SPI 0 Slave select 0 in, input
.EMIOSPI0SSON(), // SPI 0 Slave select [2:0] out, output
.EMIOSPI0SSNTN(), // SPI 0 Slave select OE, output
// SPI 1
.EMIOSPI1SCLKI(), // SPI 1 CLK in , input
.EMIOSPI1SCLKO(), // SPI 1 CLK out, output
.EMIOSPI1SCLKTN(), // SPI 1 CLK OE, output
.EMIOSPI1SI(), // SPI 1 MOSI in , input
.EMIOSPI1MO(), // SPI 1 MOSI out , output
.EMIOSPI1MOTN(), // SPI 1 MOSI OE, output
.EMIOSPI1MI(), // SPI 1 MISO in, input
.EMIOSPI1SO(), // SPI 1 MISO out, output
.EMIOSPI1STN(), // SPI 1 MISO OE, output
.EMIOSPI1SSIN(), // SPI 1 Slave select 0 in, input
.EMIOSPI1SSON(), // SPI 1 Slave select [2:0] out, output
.EMIOSPI1SSNTN(), // SPI 1 Slave select OE, output
// TPIU signals (Trace)
.EMIOTRACECTL(), // Trace CTL, output
.EMIOTRACEDATA(), // Trace Data[31:0], output
.EMIOTRACECLK(), // Trace CLK, input
// Timers/counters
.EMIOTTC0CLKI(), // Counter/Timer 0 clock in [2:0], input
.EMIOTTC0WAVEO(), // Counter/Timer 0 wave out[2:0], output
.EMIOTTC1CLKI(), // Counter/Timer 1 clock in [2:0], input
.EMIOTTC1WAVEO(), // Counter/Timer 1 wave out[2:0], output
//UART 0
.EMIOUART0TX(), // UART 0 Transmit, output
.EMIOUART0RX(), // UART 0 Receive, input
.EMIOUART0CTSN(), // UART 0 Clear To Send, input
.EMIOUART0RTSN(), // UART 0 Ready to Send, output
.EMIOUART0DSRN(), // UART 0 Data Set Ready , input
.EMIOUART0DCDN(), // UART 0 Data Carrier Detect, input
.EMIOUART0RIN(), // UART 0 Ring Indicator, input
.EMIOUART0DTRN(), // UART 0 Data Terminal Ready, output
//UART 1
.EMIOUART1TX(), // UART 1 Transmit, output
.EMIOUART1RX(), // UART 1 Receive, input
.EMIOUART1CTSN(), // UART 1 Clear To Send, input
.EMIOUART1RTSN(), // UART 1 Ready to Send, output
.EMIOUART1DSRN(), // UART 1 Data Set Ready , input
.EMIOUART1DCDN(), // UART 1 Data Carrier Detect, input
.EMIOUART1RIN(), // UART 1 Ring Indicator, input
.EMIOUART1DTRN(), // UART 1 Data Terminal Ready, output
// USB 0
.EMIOUSB0PORTINDCTL(), // USB 0 Port Indicator [1:0], output
.EMIOUSB0VBUSPWRFAULT(), // USB 0 Power Fault, input
.EMIOUSB0VBUSPWRSELECT(), // USB 0 Power Select, output
// USB 1
.EMIOUSB1PORTINDCTL(), // USB 1 Port Indicator [1:0], output
.EMIOUSB1VBUSPWRFAULT(), // USB 1 Power Fault, input
.EMIOUSB1VBUSPWRSELECT(), // USB 1 Power Select, output
// Watchdog Timer
.EMIOWDTCLKI(), // Watchdog Timer Clock in, input
.EMIOWDTRSTO(), // Watchdog Timer Reset out, output
// DMAC 0
.DMA0ACLK(), // DMAC 0 Clock, input
.DMA0DRVALID(), // DMAC 0 DMA Request Valid, input
.DMA0DRLAST(), // DMAC 0 DMA Request Last, input
.DMA0DRTYPE(), // DMAC 0 DMA Request Type [1:0] ()single/burst/ackn flush/reserved), input
.DMA0DRREADY(), // DMAC 0 DMA Request Ready, output
.DMA0DAVALID(), // DMAC 0 DMA Acknowledge Valid (DA_TYPE[1:0] valid), output
.DMA0DAREADY(), // DMAC 0 DMA Acknowledge (peripheral can accept DA_TYPE[1:0]), input
.DMA0DATYPE(), // DMAC 0 DMA Ackbowledge TYpe (completed single AXI, completed burst AXI, flush request), output
.DMA0RSTN(), // DMAC 0 RESET output (reserved, do not use), output
// DMAC 1
.DMA1ACLK(), // DMAC 1 Clock, input
.DMA1DRVALID(), // DMAC 1 DMA Request Valid, input
.DMA1DRLAST(), // DMAC 1 DMA Request Last, input
.DMA1DRTYPE(), // DMAC 1 DMA Request Type [1:0] ()single/burst/ackn flush/reserved), input
.DMA1DRREADY(), // DMAC 1 DMA Request Ready, output
.DMA1DAVALID(), // DMAC 1 DMA Acknowledge Valid (DA_TYPE[1:0] valid), output
.DMA1DAREADY(), // DMAC 1 DMA Acknowledge (peripheral can accept DA_TYPE[1:0]), input
.DMA1DATYPE(), // DMAC 1 DMA Ackbowledge TYpe (completed single AXI, completed burst AXI, flush request), output
.DMA1RSTN(), // DMAC 1 RESET output (reserved, do not use), output
// DMAC 2
.DMA2ACLK(), // DMAC 2 Clock, input
.DMA2DRVALID(), // DMAC 2 DMA Request Valid, input
.DMA2DRLAST(), // DMAC 2 DMA Request Last, input
.DMA2DRTYPE(), // DMAC 2 DMA Request Type [1:0] ()single/burst/ackn flush/reserved), input
.DMA2DRREADY(), // DMAC 2 DMA Request Ready, output
.DMA2DAVALID(), // DMAC 2 DMA Acknowledge Valid (DA_TYPE[1:0] valid), output
.DMA2DAREADY(), // DMAC 2 DMA Acknowledge (peripheral can accept DA_TYPE[1:0]), input
.DMA2DATYPE(), // DMAC 2 DMA Ackbowledge TYpe (completed single AXI, completed burst AXI, flush request), output
.DMA2RSTN(), // DMAC 2 RESET output (reserved, do not use), output
// DMAC 3
.DMA3ACLK(), // DMAC 3 Clock, input
.DMA3DRVALID(), // DMAC 3 DMA Request Valid, input
.DMA3DRLAST(), // DMAC 3 DMA Request Last, input
.DMA3DRTYPE(), // DMAC 3 DMA Request Type [1:0] ()single/burst/ackn flush/reserved), input
.DMA3DRREADY(), // DMAC 3 DMA Request Ready, output
.DMA3DAVALID(), // DMAC 3 DMA Acknowledge Valid (DA_TYPE[1:0] valid), output
.DMA3DAREADY(), // DMAC 3 DMA Acknowledge (peripheral can accept DA_TYPE[1:0]), input
.DMA3DATYPE(), // DMAC 3 DMA Ackbowledge TYpe (completed single AXI, completed burst AXI, flush request), output
.DMA3RSTN(), // DMAC 3 RESET output (reserved, do not use), output
// Interrupt signals
.IRQF2P(), // Interrupts, OL to PS [19:0], input
.IRQP2F(), // Interrupts, OL to PS [28:0], output
// Event Signals
.EVENTEVENTI(), // EVENT Wake up one or both CPU from WFE state, input
.EVENTEVENTO(), // EVENT Asserted when one of the COUs executed SEV instruction, output
.EVENTSTANDBYWFE(), // EVENT CPU standby mode [1:0], asserted when CPU is waiting for an event, output
.EVENTSTANDBYWFI(), // EVENT CPU standby mode [1:0], asserted when CPU is waiting for an interrupt, output
// PL Resets and clocks
.FCLKCLK(fclk[3:0]), // PL Clocks [3:0], output
.FCLKCLKTRIGN(), // PL Clock Throttle Control [3:0], input
.FCLKRESETN(frst[3:0]), // PL General purpose user reset [3:0], output (active low)
// Debug signals
.FTMTP2FDEBUG(), // Debug General purpose debug output [31:0], output
.FTMTF2PDEBUG(), // Debug General purpose debug input [31:0], input
.FTMTP2FTRIG(), // Debug Trigger PS to PL [3:0], output
.FTMTP2FTRIGACK(), // Debug Trigger PS to PL acknowledge[3:0], input
.FTMTF2PTRIG(), // Debug Trigger PL to PS [3:0], input
.FTMTF2PTRIGACK(), // Debug Trigger PL to PS acknowledge[3:0], output
.FTMDTRACEINCLOCK(), // Debug Trace PL to PS Clock, input
.FTMDTRACEINVALID(), // Debug Trace PL to PS Clock, data&id valid, input
.FTMDTRACEINDATA(), // Debug Trace PL to PS data [31:0], input
.FTMDTRACEINATID(), // Debug Trace PL to PS ID [3:0], input
// DDR Urgent
.DDRARB(), // DDR Urgent[3:0], input
// SRAM interrupt (on rising edge)
.EMIOSRAMINTIN(), // SRAM interrupt #50 shared with NAND busy, input
// AXI interfaces
.FPGAIDLEN(1'b1), //Idle PL AXI interfaces (active low), input
// AXI PS Master GP0
// AXI PS Master GP0: Clock, Reset
.MAXIGP0ACLK(/*axi_aclk*/), // AXI PS Master GP0 Clock , input
// .MAXIGP0ACLK(/*fclk[0]*/), // AXI PS Master GP0 Clock , input
// .MAXIGP0ACLK(/*~fclk[0]*/), // AXI PS Master GP0 Clock , input
// .MAXIGP0ACLK(/*axi_naclk*/), // AXI PS Master GP0 Clock , input
//
.MAXIGP0ARESETN(), // AXI PS Master GP0 Reset, output
// AXI PS Master GP0: Read Address
.MAXIGP0ARADDR (/*axi_araddr[31:0]*/), // AXI PS Master GP0 ARADDR[31:0], output
.MAXIGP0ARVALID (/*axi_arvalid*/), // AXI PS Master GP0 ARVALID, output
.MAXIGP0ARREADY (/*axi_arready*/), // AXI PS Master GP0 ARREADY, input
.MAXIGP0ARID (/*axi_arid[11:0]*/), // AXI PS Master GP0 ARID[11:0], output
.MAXIGP0ARLOCK (), // AXI PS Master GP0 ARLOCK[1:0], output
.MAXIGP0ARCACHE (),// AXI PS Master GP0 ARCACHE[3:0], output
.MAXIGP0ARPROT(), // AXI PS Master GP0 ARPROT[2:0], output
.MAXIGP0ARLEN (/*axi_arlen[3:0]*/), // AXI PS Master GP0 ARLEN[3:0], output
.MAXIGP0ARSIZE (/*axi_arsize[1:0]*/), // AXI PS Master GP0 ARSIZE[1:0], output
.MAXIGP0ARBURST (/*axi_arburst[1:0]*/),// AXI PS Master GP0 ARBURST[1:0], output
.MAXIGP0ARQOS (), // AXI PS Master GP0 ARQOS[3:0], output
// AXI PS Master GP0: Read Data
.MAXIGP0RDATA (/*axi_rdata[31:0]*/), // AXI PS Master GP0 RDATA[31:0], input
.MAXIGP0RVALID (/*axi_rvalid*/), // AXI PS Master GP0 RVALID, input
.MAXIGP0RREADY (/*axi_rready*/), // AXI PS Master GP0 RREADY, output
.MAXIGP0RID (/*axi_rid[11:0]*/), // AXI PS Master GP0 RID[11:0], input
.MAXIGP0RLAST (/*axi_rlast*/), // AXI PS Master GP0 RLAST, input
.MAXIGP0RRESP (/*axi_rresp[1:0]*/), // AXI PS Master GP0 RRESP[1:0], input
// AXI PS Master GP0: Write Address
.MAXIGP0AWADDR (/*axi_awaddr[31:0]*/), // AXI PS Master GP0 AWADDR[31:0], output
.MAXIGP0AWVALID (/*axi_awvalid*/), // AXI PS Master GP0 AWVALID, output
.MAXIGP0AWREADY (/*axi_awready*/), // AXI PS Master GP0 AWREADY, input
.MAXIGP0AWID (/*axi_awid[11:0]*/), // AXI PS Master GP0 AWID[11:0], output
.MAXIGP0AWLOCK (), // AXI PS Master GP0 AWLOCK[1:0], output
.MAXIGP0AWCACHE (),// AXI PS Master GP0 AWCACHE[3:0], output
.MAXIGP0AWPROT (), // AXI PS Master GP0 AWPROT[2:0], output
.MAXIGP0AWLEN (/*axi_awlen[3:0]*/), // AXI PS Master GP0 AWLEN[3:0], output
.MAXIGP0AWSIZE (/*axi_awsize[1:0]*/), // AXI PS Master GP0 AWSIZE[1:0], output
.MAXIGP0AWBURST (/*axi_awburst[1:0]*/),// AXI PS Master GP0 AWBURST[1:0], output
.MAXIGP0AWQOS (), // AXI PS Master GP0 AWQOS[3:0], output
// AXI PS Master GP0: Write Data
.MAXIGP0WDATA (/*axi_wdata[31:0]*/), // AXI PS Master GP0 WDATA[31:0], output
.MAXIGP0WVALID (/*axi_wvalid*/), // AXI PS Master GP0 WVALID, output
.MAXIGP0WREADY (/*axi_wready*/), // AXI PS Master GP0 WREADY, input
.MAXIGP0WID (/*axi_wid[11:0]*/), // AXI PS Master GP0 WID[11:0], output
.MAXIGP0WLAST (/*axi_wlast*/), // AXI PS Master GP0 WLAST, output
.MAXIGP0WSTRB (/*axi_wstb[3:0]*/), // AXI PS Master GP0 WSTRB[3:0], output
// AXI PS Master GP0: Write Responce
.MAXIGP0BVALID (/*axi_bvalid*/), // AXI PS Master GP0 BVALID, input
.MAXIGP0BREADY (/*axi_bready*/), // AXI PS Master GP0 BREADY, output
.MAXIGP0BID (/*axi_bid[11:0]*/), // AXI PS Master GP0 BID[11:0], input
.MAXIGP0BRESP (/*axi_bresp[1:0]*/), // AXI PS Master GP0 BRESP[1:0], input
// AXI PS Master GP1
// AXI PS Master GP1: Clock, Reset
.MAXIGP1ACLK (axi_aclk), // AXI PS Master GP1 Clock , input
.MAXIGP1ARESETN (), // AXI PS Master GP1 Reset, output
// AXI PS Master GP1: Read Address
.MAXIGP1ARADDR (ARADDR), // AXI PS Master GP1 ARADDR[31:0], output
.MAXIGP1ARVALID (ARVALID), // AXI PS Master GP1 ARVALID, output
.MAXIGP1ARREADY (ARREADY), // AXI PS Master GP1 ARREADY, input
.MAXIGP1ARID (ARID), // AXI PS Master GP1 ARID[11:0], output
.MAXIGP1ARLOCK (ARLOCK), // AXI PS Master GP1 ARLOCK[1:0], output
.MAXIGP1ARCACHE (ARCACHE), // AXI PS Master GP1 ARCACHE[3:0], output
.MAXIGP1ARPROT (ARPROT), // AXI PS Master GP1 ARPROT[2:0], output
.MAXIGP1ARLEN (ARLEN), // AXI PS Master GP1 ARLEN[3:0], output
.MAXIGP1ARSIZE (ARSIZE), // AXI PS Master GP1 ARSIZE[1:0], output
.MAXIGP1ARBURST (ARBURST), // AXI PS Master GP1 ARBURST[1:0], output
.MAXIGP1ARQOS (ARQOS), // AXI PS Master GP1 ARQOS[3:0], output
// AXI PS Master GP1: Read Data
.MAXIGP1RDATA (RDATA), // AXI PS Master GP1 RDATA[31:0], input
.MAXIGP1RVALID (RVALID), // AXI PS Master GP1 RVALID, input
.MAXIGP1RREADY (RREADY), // AXI PS Master GP1 RREADY, output
.MAXIGP1RID (RID), // AXI PS Master GP1 RID[11:0], input
.MAXIGP1RLAST (RLAST), // AXI PS Master GP1 RLAST, input
.MAXIGP1RRESP (RRESP), // AXI PS Master GP1 RRESP[1:0], input
// AXI PS Master GP1: Write Address
.MAXIGP1AWADDR (AWADDR), // AXI PS Master GP1 AWADDR[31:0], output
.MAXIGP1AWVALID (AWVALID), // AXI PS Master GP1 AWVALID, output
.MAXIGP1AWREADY (AWREADY), // AXI PS Master GP1 AWREADY, input
.MAXIGP1AWID (AWID), // AXI PS Master GP1 AWID[11:0], output
.MAXIGP1AWLOCK (AWLOCK), // AXI PS Master GP1 AWLOCK[1:0], output
.MAXIGP1AWCACHE (AWCACHE), // AXI PS Master GP1 AWCACHE[3:0], output
.MAXIGP1AWPROT (AWPROT), // AXI PS Master GP1 AWPROT[2:0], output
.MAXIGP1AWLEN (AWLEN), // AXI PS Master GP1 AWLEN[3:0], output
.MAXIGP1AWSIZE (AWSIZE), // AXI PS Master GP1 AWSIZE[1:0], output
.MAXIGP1AWBURST (AWBURST), // AXI PS Master GP1 AWBURST[1:0], output
.MAXIGP1AWQOS (AWQOS), // AXI PS Master GP1 AWQOS[3:0], output
// AXI PS Master GP1: Write Data
.MAXIGP1WDATA (WDATA), // AXI PS Master GP1 WDATA[31:0], output
.MAXIGP1WVALID (WVALID), // AXI PS Master GP1 WVALID, output
.MAXIGP1WREADY (WREADY), // AXI PS Master GP1 WREADY, input
.MAXIGP1WID (WID), // AXI PS Master GP1 WID[11:0], output
.MAXIGP1WLAST (WLAST), // AXI PS Master GP1 WLAST, output
.MAXIGP1WSTRB (WSTRB), // AXI PS Master GP1 WSTRB[3:0], output
// AXI PS Master GP1: Write Responce
.MAXIGP1BVALID (BVALID), // AXI PS Master GP1 BVALID, input
.MAXIGP1BREADY (BREADY), // AXI PS Master GP1 BREADY, output
.MAXIGP1BID (BID), // AXI PS Master GP1 BID[11:0], input
.MAXIGP1BRESP (BRESP), // AXI PS Master GP1 BRESP[1:0], input
// AXI PS Slave GP0
// AXI PS Slave GP0: Clock, Reset
.SAXIGP0ACLK(), // AXI PS Slave GP0 Clock , input
.SAXIGP0ARESETN(), // AXI PS Slave GP0 Reset, output
// AXI PS Slave GP0: Read Address
.SAXIGP0ARADDR(), // AXI PS Slave GP0 ARADDR[31:0], input
.SAXIGP0ARVALID(), // AXI PS Slave GP0 ARVALID, input
.SAXIGP0ARREADY(), // AXI PS Slave GP0 ARREADY, output
.SAXIGP0ARID(), // AXI PS Slave GP0 ARID[5:0], input
.SAXIGP0ARLOCK(), // AXI PS Slave GP0 ARLOCK[1:0], input
.SAXIGP0ARCACHE(), // AXI PS Slave GP0 ARCACHE[3:0], input
.SAXIGP0ARPROT(), // AXI PS Slave GP0 ARPROT[2:0], input
.SAXIGP0ARLEN(), // AXI PS Slave GP0 ARLEN[3:0], input
.SAXIGP0ARSIZE(), // AXI PS Slave GP0 ARSIZE[1:0], input
.SAXIGP0ARBURST(), // AXI PS Slave GP0 ARBURST[1:0], input
.SAXIGP0ARQOS(), // AXI PS Slave GP0 ARQOS[3:0], input
// AXI PS Slave GP0: Read Data
.SAXIGP0RDATA(), // AXI PS Slave GP0 RDATA[31:0], output
.SAXIGP0RVALID(), // AXI PS Slave GP0 RVALID, output
.SAXIGP0RREADY(), // AXI PS Slave GP0 RREADY, input
.SAXIGP0RID(), // AXI PS Slave GP0 RID[5:0], output
.SAXIGP0RLAST(), // AXI PS Slave GP0 RLAST, output
.SAXIGP0RRESP(), // AXI PS Slave GP0 RRESP[1:0], output
// AXI PS Slave GP0: Write Address
.SAXIGP0AWADDR(), // AXI PS Slave GP0 AWADDR[31:0], input
.SAXIGP0AWVALID(), // AXI PS Slave GP0 AWVALID, input
.SAXIGP0AWREADY(), // AXI PS Slave GP0 AWREADY, output
.SAXIGP0AWID(), // AXI PS Slave GP0 AWID[5:0], input
.SAXIGP0AWLOCK(), // AXI PS Slave GP0 AWLOCK[1:0], input
.SAXIGP0AWCACHE(), // AXI PS Slave GP0 AWCACHE[3:0], input
.SAXIGP0AWPROT(), // AXI PS Slave GP0 AWPROT[2:0], input
.SAXIGP0AWLEN(), // AXI PS Slave GP0 AWLEN[3:0], input
.SAXIGP0AWSIZE(), // AXI PS Slave GP0 AWSIZE[1:0], input
.SAXIGP0AWBURST(), // AXI PS Slave GP0 AWBURST[1:0], input
.SAXIGP0AWQOS(), // AXI PS Slave GP0 AWQOS[3:0], input
// AXI PS Slave GP0: Write Data
.SAXIGP0WDATA(), // AXI PS Slave GP0 WDATA[31:0], input
.SAXIGP0WVALID(), // AXI PS Slave GP0 WVALID, input
.SAXIGP0WREADY(), // AXI PS Slave GP0 WREADY, output
.SAXIGP0WID(), // AXI PS Slave GP0 WID[5:0], input
.SAXIGP0WLAST(), // AXI PS Slave GP0 WLAST, input
.SAXIGP0WSTRB(), // AXI PS Slave GP0 WSTRB[3:0], input
// AXI PS Slave GP0: Write Responce
.SAXIGP0BVALID(), // AXI PS Slave GP0 BVALID, output
.SAXIGP0BREADY(), // AXI PS Slave GP0 BREADY, input
.SAXIGP0BID(), // AXI PS Slave GP0 BID[5:0], output //TODO: Update range !!!
.SAXIGP0BRESP(), // AXI PS Slave GP0 BRESP[1:0], output
// AXI PS Slave GP1
// AXI PS Slave GP1: Clock, Reset
.SAXIGP1ACLK(), // AXI PS Slave GP1 Clock , input
.SAXIGP1ARESETN(), // AXI PS Slave GP1 Reset, output
// AXI PS Slave GP1: Read Address
.SAXIGP1ARADDR(), // AXI PS Slave GP1 ARADDR[31:0], input
.SAXIGP1ARVALID(), // AXI PS Slave GP1 ARVALID, input
.SAXIGP1ARREADY(), // AXI PS Slave GP1 ARREADY, output
.SAXIGP1ARID(), // AXI PS Slave GP1 ARID[5:0], input
.SAXIGP1ARLOCK(), // AXI PS Slave GP1 ARLOCK[1:0], input
.SAXIGP1ARCACHE(), // AXI PS Slave GP1 ARCACHE[3:0], input
.SAXIGP1ARPROT(), // AXI PS Slave GP1 ARPROT[2:0], input
.SAXIGP1ARLEN(), // AXI PS Slave GP1 ARLEN[3:0], input
.SAXIGP1ARSIZE(), // AXI PS Slave GP1 ARSIZE[1:0], input
.SAXIGP1ARBURST(), // AXI PS Slave GP1 ARBURST[1:0], input
.SAXIGP1ARQOS(), // AXI PS Slave GP1 ARQOS[3:0], input
// AXI PS Slave GP1: Read Data
.SAXIGP1RDATA(), // AXI PS Slave GP1 RDATA[31:0], output
.SAXIGP1RVALID(), // AXI PS Slave GP1 RVALID, output
.SAXIGP1RREADY(), // AXI PS Slave GP1 RREADY, input
.SAXIGP1RID(), // AXI PS Slave GP1 RID[5:0], output
.SAXIGP1RLAST(), // AXI PS Slave GP1 RLAST, output
.SAXIGP1RRESP(), // AXI PS Slave GP1 RRESP[1:0], output
// AXI PS Slave GP1: Write Address
.SAXIGP1AWADDR(), // AXI PS Slave GP1 AWADDR[31:0], input
.SAXIGP1AWVALID(), // AXI PS Slave GP1 AWVALID, input
.SAXIGP1AWREADY(), // AXI PS Slave GP1 AWREADY, output
.SAXIGP1AWID(), // AXI PS Slave GP1 AWID[5:0], input
.SAXIGP1AWLOCK(), // AXI PS Slave GP1 AWLOCK[1:0], input
.SAXIGP1AWCACHE(), // AXI PS Slave GP1 AWCACHE[3:0], input
.SAXIGP1AWPROT(), // AXI PS Slave GP1 AWPROT[2:0], input
.SAXIGP1AWLEN(), // AXI PS Slave GP1 AWLEN[3:0], input
.SAXIGP1AWSIZE(), // AXI PS Slave GP1 AWSIZE[1:0], input
.SAXIGP1AWBURST(), // AXI PS Slave GP1 AWBURST[1:0], input
.SAXIGP1AWQOS(), // AXI PS Slave GP1 AWQOS[3:0], input
// AXI PS Slave GP1: Write Data
.SAXIGP1WDATA(), // AXI PS Slave GP1 WDATA[31:0], input
.SAXIGP1WVALID(), // AXI PS Slave GP1 WVALID, input
.SAXIGP1WREADY(), // AXI PS Slave GP1 WREADY, output
.SAXIGP1WID(), // AXI PS Slave GP1 WID[5:0], input
.SAXIGP1WLAST(), // AXI PS Slave GP1 WLAST, input
.SAXIGP1WSTRB(), // AXI PS Slave GP1 WSTRB[3:0], input
// AXI PS Slave GP1: Write Responce
.SAXIGP1BVALID(), // AXI PS Slave GP1 BVALID, output
.SAXIGP1BREADY(), // AXI PS Slave GP1 BREADY, input
.SAXIGP1BID(), // AXI PS Slave GP1 BID[5:0], output
.SAXIGP1BRESP(), // AXI PS Slave GP1 BRESP[1:0], output
// AXI PS Slave HP0
// AXI PS Slave HP0: Clock, Reset
.SAXIHP0ACLK(), // AXI PS Slave HP0 Clock , input
.SAXIHP0ARESETN(), // AXI PS Slave HP0 Reset, output
// AXI PS Slave HP0: Read Address
.SAXIHP0ARADDR(), // AXI PS Slave HP0 ARADDR[31:0], input
.SAXIHP0ARVALID(), // AXI PS Slave HP0 ARVALID, input
.SAXIHP0ARREADY(), // AXI PS Slave HP0 ARREADY, output
.SAXIHP0ARID(), // AXI PS Slave HP0 ARID[5:0], input
.SAXIHP0ARLOCK(), // AXI PS Slave HP0 ARLOCK[1:0], input
.SAXIHP0ARCACHE(), // AXI PS Slave HP0 ARCACHE[3:0], input
.SAXIHP0ARPROT(), // AXI PS Slave HP0 ARPROT[2:0], input
.SAXIHP0ARLEN(), // AXI PS Slave HP0 ARLEN[3:0], input
.SAXIHP0ARSIZE(), // AXI PS Slave HP0 ARSIZE[2:0], input
.SAXIHP0ARBURST(), // AXI PS Slave HP0 ARBURST[1:0], input
.SAXIHP0ARQOS(), // AXI PS Slave HP0 ARQOS[3:0], input
// AXI PS Slave HP0: Read Data
.SAXIHP0RDATA(), // AXI PS Slave HP0 RDATA[63:0], output
.SAXIHP0RVALID(), // AXI PS Slave HP0 RVALID, output
.SAXIHP0RREADY(), // AXI PS Slave HP0 RREADY, input
.SAXIHP0RID(), // AXI PS Slave HP0 RID[5:0], output
.SAXIHP0RLAST(), // AXI PS Slave HP0 RLAST, output
.SAXIHP0RRESP(), // AXI PS Slave HP0 RRESP[1:0], output
.SAXIHP0RCOUNT(), // AXI PS Slave HP0 RCOUNT[7:0], output
.SAXIHP0RACOUNT(), // AXI PS Slave HP0 RACOUNT[2:0], output
.SAXIHP0RDISSUECAP1EN(), // AXI PS Slave HP0 RDISSUECAP1EN, input
// AXI PS Slave HP0: Write Address
.SAXIHP0AWADDR(), // AXI PS Slave HP0 AWADDR[31:0], input
.SAXIHP0AWVALID(), // AXI PS Slave HP0 AWVALID, input
.SAXIHP0AWREADY(), // AXI PS Slave HP0 AWREADY, output
.SAXIHP0AWID(), // AXI PS Slave HP0 AWID[5:0], input
.SAXIHP0AWLOCK(), // AXI PS Slave HP0 AWLOCK[1:0], input
.SAXIHP0AWCACHE(), // AXI PS Slave HP0 AWCACHE[3:0], input
.SAXIHP0AWPROT(), // AXI PS Slave HP0 AWPROT[2:0], input
.SAXIHP0AWLEN(), // AXI PS Slave HP0 AWLEN[3:0], input
.SAXIHP0AWSIZE(), // AXI PS Slave HP0 AWSIZE[1:0], input
.SAXIHP0AWBURST(), // AXI PS Slave HP0 AWBURST[1:0], input
.SAXIHP0AWQOS(), // AXI PS Slave HP0 AWQOS[3:0], input
// AXI PS Slave HP0: Write Data
.SAXIHP0WDATA(), // AXI PS Slave HP0 WDATA[63:0], input
.SAXIHP0WVALID(), // AXI PS Slave HP0 WVALID, input
.SAXIHP0WREADY(), // AXI PS Slave HP0 WREADY, output
.SAXIHP0WID(), // AXI PS Slave HP0 WID[5:0], input
.SAXIHP0WLAST(), // AXI PS Slave HP0 WLAST, input
.SAXIHP0WSTRB(), // AXI PS Slave HP0 WSTRB[7:0], input
.SAXIHP0WCOUNT(), // AXI PS Slave HP0 WCOUNT[7:0], output
.SAXIHP0WACOUNT(), // AXI PS Slave HP0 WACOUNT[5:0], output
.SAXIHP0WRISSUECAP1EN(), // AXI PS Slave HP0 WRISSUECAP1EN, input
// AXI PS Slave HP0: Write Responce
.SAXIHP0BVALID(), // AXI PS Slave HP0 BVALID, output
.SAXIHP0BREADY(), // AXI PS Slave HP0 BREADY, input
.SAXIHP0BID(), // AXI PS Slave HP0 BID[5:0], output
.SAXIHP0BRESP(), // AXI PS Slave HP0 BRESP[1:0], output
// AXI PS Slave HP1
// AXI PS Slave 1: Clock, Reset
.SAXIHP1ACLK(), // AXI PS Slave HP1 Clock , input
.SAXIHP1ARESETN(), // AXI PS Slave HP1 Reset, output
// AXI PS Slave HP1: Read Address
.SAXIHP1ARADDR(), // AXI PS Slave HP1 ARADDR[31:0], input
.SAXIHP1ARVALID(), // AXI PS Slave HP1 ARVALID, input
.SAXIHP1ARREADY(), // AXI PS Slave HP1 ARREADY, output
.SAXIHP1ARID(), // AXI PS Slave HP1 ARID[5:0], input
.SAXIHP1ARLOCK(), // AXI PS Slave HP1 ARLOCK[1:0], input
.SAXIHP1ARCACHE(), // AXI PS Slave HP1 ARCACHE[3:0], input
.SAXIHP1ARPROT(), // AXI PS Slave HP1 ARPROT[2:0], input
.SAXIHP1ARLEN(), // AXI PS Slave HP1 ARLEN[3:0], input
.SAXIHP1ARSIZE(), // AXI PS Slave HP1 ARSIZE[2:0], input
.SAXIHP1ARBURST(), // AXI PS Slave HP1 ARBURST[1:0], input
.SAXIHP1ARQOS(), // AXI PS Slave HP1 ARQOS[3:0], input
// AXI PS Slave HP1: Read Data
.SAXIHP1RDATA(), // AXI PS Slave HP1 RDATA[63:0], output
.SAXIHP1RVALID(), // AXI PS Slave HP1 RVALID, output
.SAXIHP1RREADY(), // AXI PS Slave HP1 RREADY, input
.SAXIHP1RID(), // AXI PS Slave HP1 RID[5:0], output
.SAXIHP1RLAST(), // AXI PS Slave HP1 RLAST, output
.SAXIHP1RRESP(), // AXI PS Slave HP1 RRESP[1:0], output
.SAXIHP1RCOUNT(), // AXI PS Slave HP1 RCOUNT[7:0], output
.SAXIHP1RACOUNT(), // AXI PS Slave HP1 RACOUNT[2:0], output
.SAXIHP1RDISSUECAP1EN(), // AXI PS Slave HP1 RDISSUECAP1EN, input
// AXI PS Slave HP1: Write Address
.SAXIHP1AWADDR(), // AXI PS Slave HP1 AWADDR[31:0], input
.SAXIHP1AWVALID(), // AXI PS Slave HP1 AWVALID, input
.SAXIHP1AWREADY(), // AXI PS Slave HP1 AWREADY, output
.SAXIHP1AWID(), // AXI PS Slave HP1 AWID[5:0], input
.SAXIHP1AWLOCK(), // AXI PS Slave HP1 AWLOCK[1:0], input
.SAXIHP1AWCACHE(), // AXI PS Slave HP1 AWCACHE[3:0], input
.SAXIHP1AWPROT(), // AXI PS Slave HP1 AWPROT[2:0], input
.SAXIHP1AWLEN(), // AXI PS Slave HP1 AWLEN[3:0], input
.SAXIHP1AWSIZE(), // AXI PS Slave HP1 AWSIZE[1:0], input
.SAXIHP1AWBURST(), // AXI PS Slave HP1 AWBURST[1:0], input
.SAXIHP1AWQOS(), // AXI PS Slave HP1 AWQOS[3:0], input
// AXI PS Slave HP1: Write Data
.SAXIHP1WDATA(), // AXI PS Slave HP1 WDATA[63:0], input
.SAXIHP1WVALID(), // AXI PS Slave HP1 WVALID, input
.SAXIHP1WREADY(), // AXI PS Slave HP1 WREADY, output
.SAXIHP1WID(), // AXI PS Slave HP1 WID[5:0], input
.SAXIHP1WLAST(), // AXI PS Slave HP1 WLAST, input
.SAXIHP1WSTRB(), // AXI PS Slave HP1 WSTRB[7:0], input
.SAXIHP1WCOUNT(), // AXI PS Slave HP1 WCOUNT[7:0], output
.SAXIHP1WACOUNT(), // AXI PS Slave HP1 WACOUNT[5:0], output
.SAXIHP1WRISSUECAP1EN(), // AXI PS Slave HP1 WRISSUECAP1EN, input
// AXI PS Slave HP1: Write Responce
.SAXIHP1BVALID(), // AXI PS Slave HP1 BVALID, output
.SAXIHP1BREADY(), // AXI PS Slave HP1 BREADY, input
.SAXIHP1BID(), // AXI PS Slave HP1 BID[5:0], output
.SAXIHP1BRESP(), // AXI PS Slave HP1 BRESP[1:0], output
// AXI PS Slave HP2
// AXI PS Slave HP2: Clock, Reset
.SAXIHP2ACLK(), // AXI PS Slave HP2 Clock , input
.SAXIHP2ARESETN(), // AXI PS Slave HP2 Reset, output
// AXI PS Slave HP2: Read Address
.SAXIHP2ARADDR(), // AXI PS Slave HP2 ARADDR[31:0], input
.SAXIHP2ARVALID(), // AXI PS Slave HP2 ARVALID, input
.SAXIHP2ARREADY(), // AXI PS Slave HP2 ARREADY, output
.SAXIHP2ARID(), // AXI PS Slave HP2 ARID[5:0], input
.SAXIHP2ARLOCK(), // AXI PS Slave HP2 ARLOCK[1:0], input
.SAXIHP2ARCACHE(), // AXI PS Slave HP2 ARCACHE[3:0], input
.SAXIHP2ARPROT(), // AXI PS Slave HP2 ARPROT[2:0], input
.SAXIHP2ARLEN(), // AXI PS Slave HP2 ARLEN[3:0], input
.SAXIHP2ARSIZE(), // AXI PS Slave HP2 ARSIZE[2:0], input
.SAXIHP2ARBURST(), // AXI PS Slave HP2 ARBURST[1:0], input
.SAXIHP2ARQOS(), // AXI PS Slave HP2 ARQOS[3:0], input
// AXI PS Slave HP2: Read Data
.SAXIHP2RDATA(), // AXI PS Slave HP2 RDATA[63:0], output
.SAXIHP2RVALID(), // AXI PS Slave HP2 RVALID, output
.SAXIHP2RREADY(), // AXI PS Slave HP2 RREADY, input
.SAXIHP2RID(), // AXI PS Slave HP2 RID[5:0], output
.SAXIHP2RLAST(), // AXI PS Slave HP2 RLAST, output
.SAXIHP2RRESP(), // AXI PS Slave HP2 RRESP[1:0], output
.SAXIHP2RCOUNT(), // AXI PS Slave HP2 RCOUNT[7:0], output
.SAXIHP2RACOUNT(), // AXI PS Slave HP2 RACOUNT[2:0], output
.SAXIHP2RDISSUECAP1EN(), // AXI PS Slave HP2 RDISSUECAP1EN, input
// AXI PS Slave HP2: Write Address
.SAXIHP2AWADDR(), // AXI PS Slave HP2 AWADDR[31:0], input
.SAXIHP2AWVALID(), // AXI PS Slave HP2 AWVALID, input
.SAXIHP2AWREADY(), // AXI PS Slave HP2 AWREADY, output
.SAXIHP2AWID(), // AXI PS Slave HP2 AWID[5:0], input
.SAXIHP2AWLOCK(), // AXI PS Slave HP2 AWLOCK[1:0], input
.SAXIHP2AWCACHE(), // AXI PS Slave HP2 AWCACHE[3:0], input
.SAXIHP2AWPROT(), // AXI PS Slave HP2 AWPROT[2:0], input
.SAXIHP2AWLEN(), // AXI PS Slave HP2 AWLEN[3:0], input
.SAXIHP2AWSIZE(), // AXI PS Slave HP2 AWSIZE[1:0], input
.SAXIHP2AWBURST(), // AXI PS Slave HP2 AWBURST[1:0], input
.SAXIHP2AWQOS(), // AXI PS Slave HP2 AWQOS[3:0], input
// AXI PS Slave HP2: Write Data
.SAXIHP2WDATA(), // AXI PS Slave HP2 WDATA[63:0], input
.SAXIHP2WVALID(), // AXI PS Slave HP2 WVALID, input
.SAXIHP2WREADY(), // AXI PS Slave HP2 WREADY, output
.SAXIHP2WID(), // AXI PS Slave HP2 WID[5:0], input
.SAXIHP2WLAST(), // AXI PS Slave HP2 WLAST, input
.SAXIHP2WSTRB(), // AXI PS Slave HP2 WSTRB[7:0], input
.SAXIHP2WCOUNT(), // AXI PS Slave HP2 WCOUNT[7:0], output
.SAXIHP2WACOUNT(), // AXI PS Slave HP2 WACOUNT[5:0], output
.SAXIHP2WRISSUECAP1EN(), // AXI PS Slave HP2 WRISSUECAP1EN, input
// AXI PS Slave HP2: Write Responce
.SAXIHP2BVALID(), // AXI PS Slave HP2 BVALID, output
.SAXIHP2BREADY(), // AXI PS Slave HP2 BREADY, input
.SAXIHP2BID(), // AXI PS Slave HP2 BID[5:0], output
.SAXIHP2BRESP(), // AXI PS Slave HP2 BRESP[1:0], output
// AXI PS Slave HP3
// AXI PS Slave HP3: Clock, Reset
.SAXIHP3ACLK(), // AXI PS Slave HP3 Clock , input
.SAXIHP3ARESETN(), // AXI PS Slave HP3 Reset, output
// AXI PS Slave HP3: Read Address
.SAXIHP3ARADDR(), // AXI PS Slave HP3 ARADDR[31:0], input
.SAXIHP3ARVALID(), // AXI PS Slave HP3 ARVALID, input
.SAXIHP3ARREADY(), // AXI PS Slave HP3 ARREADY, output
.SAXIHP3ARID(), // AXI PS Slave HP3 ARID[5:0], input
.SAXIHP3ARLOCK(), // AXI PS Slave HP3 ARLOCK[1:0], input
.SAXIHP3ARCACHE(), // AXI PS Slave HP3 ARCACHE[3:0], input
.SAXIHP3ARPROT(), // AXI PS Slave HP3 ARPROT[2:0], input
.SAXIHP3ARLEN(), // AXI PS Slave HP3 ARLEN[3:0], input
.SAXIHP3ARSIZE(), // AXI PS Slave HP3 ARSIZE[2:0], input
.SAXIHP3ARBURST(), // AXI PS Slave HP3 ARBURST[1:0], input
.SAXIHP3ARQOS(), // AXI PS Slave HP3 ARQOS[3:0], input
// AXI PS Slave HP3: Read Data
.SAXIHP3RDATA(), // AXI PS Slave HP3 RDATA[63:0], output
.SAXIHP3RVALID(), // AXI PS Slave HP3 RVALID, output
.SAXIHP3RREADY(), // AXI PS Slave HP3 RREADY, input
.SAXIHP3RID(), // AXI PS Slave HP3 RID[5:0], output
.SAXIHP3RLAST(), // AXI PS Slave HP3 RLAST, output
.SAXIHP3RRESP(), // AXI PS Slave HP3 RRESP[1:0], output
.SAXIHP3RCOUNT(), // AXI PS Slave HP3 RCOUNT[7:0], output
.SAXIHP3RACOUNT(), // AXI PS Slave HP3 RACOUNT[2:0], output
.SAXIHP3RDISSUECAP1EN(), // AXI PS Slave HP3 RDISSUECAP1EN, input
// AXI PS Slave HP3: Write Address
.SAXIHP3AWADDR(), // AXI PS Slave HP3 AWADDR[31:0], input
.SAXIHP3AWVALID(), // AXI PS Slave HP3 AWVALID, input
.SAXIHP3AWREADY(), // AXI PS Slave HP3 AWREADY, output
.SAXIHP3AWID(), // AXI PS Slave HP3 AWID[5:0], input
.SAXIHP3AWLOCK(), // AXI PS Slave HP3 AWLOCK[1:0], input
.SAXIHP3AWCACHE(), // AXI PS Slave HP3 AWCACHE[3:0], input
.SAXIHP3AWPROT(), // AXI PS Slave HP3 AWPROT[2:0], input
.SAXIHP3AWLEN(), // AXI PS Slave HP3 AWLEN[3:0], input
.SAXIHP3AWSIZE(), // AXI PS Slave HP3 AWSIZE[1:0], input
.SAXIHP3AWBURST(), // AXI PS Slave HP3 AWBURST[1:0], input
.SAXIHP3AWQOS(), // AXI PS Slave HP3 AWQOS[3:0], input
// AXI PS Slave HP3: Write Data
.SAXIHP3WDATA(), // AXI PS Slave HP3 WDATA[63:0], input
.SAXIHP3WVALID(), // AXI PS Slave HP3 WVALID, input
.SAXIHP3WREADY(), // AXI PS Slave HP3 WREADY, output
.SAXIHP3WID(), // AXI PS Slave HP3 WID[5:0], input
.SAXIHP3WLAST(), // AXI PS Slave HP3 WLAST, input
.SAXIHP3WSTRB(), // AXI PS Slave HP3 WSTRB[7:0], input
.SAXIHP3WCOUNT(), // AXI PS Slave HP3 WCOUNT[7:0], output
.SAXIHP3WACOUNT(), // AXI PS Slave HP3 WACOUNT[5:0], output
.SAXIHP3WRISSUECAP1EN(), // AXI PS Slave HP3 WRISSUECAP1EN, input
// AXI PS Slave HP3: Write Responce
.SAXIHP3BVALID(), // AXI PS Slave HP3 BVALID, output
.SAXIHP3BREADY(), // AXI PS Slave HP3 BREADY, input
.SAXIHP3BID(), // AXI PS Slave HP3 BID[5:0], output
.SAXIHP3BRESP(), // AXI PS Slave HP3 BRESP[1:0], output
// AXI PS Slave ACP
// AXI PS Slave ACP: Clock, Reset
.SAXIACPACLK(), // AXI PS Slave ACP Clock, input
.SAXIACPARESETN(), // AXI PS Slave ACP Reset, output
// AXI PS Slave ACP: Read Address
.SAXIACPARADDR(), // AXI PS Slave ACP ARADDR[31:0], input
.SAXIACPARVALID(), // AXI PS Slave ACP ARVALID, input
.SAXIACPARREADY(), // AXI PS Slave ACP ARREADY, output
.SAXIACPARID(), // AXI PS Slave ACP ARID[2:0], input
.SAXIACPARLOCK(), // AXI PS Slave ACP ARLOCK[1:0], input
.SAXIACPARCACHE(), // AXI PS Slave ACP ARCACHE[3:0], input
.SAXIACPARPROT(), // AXI PS Slave ACP ARPROT[2:0], input
.SAXIACPARLEN(), // AXI PS Slave ACP ARLEN[3:0], input
.SAXIACPARSIZE(), // AXI PS Slave ACP ARSIZE[2:0], input
.SAXIACPARBURST(), // AXI PS Slave ACP ARBURST[1:0], input
.SAXIACPARQOS(), // AXI PS Slave ACP ARQOS[3:0], input
.SAXIACPARUSER(), // AXI PS Slave ACP ARUSER[4:0], input
// AXI PS Slave ACP: Read Data
.SAXIACPRDATA(), // AXI PS Slave ACP RDATA[63:0], output
.SAXIACPRVALID(), // AXI PS Slave ACP RVALID, output
.SAXIACPRREADY(), // AXI PS Slave ACP RREADY, input
.SAXIACPRID(), // AXI PS Slave ACP RID[2:0], output
.SAXIACPRLAST(), // AXI PS Slave ACP RLAST, output
.SAXIACPRRESP(), // AXI PS Slave ACP RRESP[1:0], output
// AXI PS Slave ACP: Write Address
.SAXIACPAWADDR(), // AXI PS Slave ACP AWADDR[31:0], input
.SAXIACPAWVALID(), // AXI PS Slave ACP AWVALID, input
.SAXIACPAWREADY(), // AXI PS Slave ACP AWREADY, output
.SAXIACPAWID(), // AXI PS Slave ACP AWID[2:0], input
.SAXIACPAWLOCK(), // AXI PS Slave ACP AWLOCK[1:0], input
.SAXIACPAWCACHE(), // AXI PS Slave ACP AWCACHE[3:0], input
.SAXIACPAWPROT(), // AXI PS Slave ACP AWPROT[2:0], input
.SAXIACPAWLEN(), // AXI PS Slave ACP AWLEN[3:0], input
.SAXIACPAWSIZE(), // AXI PS Slave ACP AWSIZE[1:0], input
.SAXIACPAWBURST(), // AXI PS Slave ACP AWBURST[1:0], input
.SAXIACPAWQOS(), // AXI PS Slave ACP AWQOS[3:0], input
.SAXIACPAWUSER(), // AXI PS Slave ACP AWUSER[4:0], input
// AXI PS Slave ACP: Write Data
.SAXIACPWDATA(), // AXI PS Slave ACP WDATA[63:0], input
.SAXIACPWVALID(), // AXI PS Slave ACP WVALID, input
.SAXIACPWREADY(), // AXI PS Slave ACP WREADY, output
.SAXIACPWID(), // AXI PS Slave ACP WID[2:0], input
.SAXIACPWLAST(), // AXI PS Slave ACP WLAST, input
.SAXIACPWSTRB(), // AXI PS Slave ACP WSTRB[7:0], input
// AXI PS Slave ACP: Write Responce
.SAXIACPBVALID(), // AXI PS Slave ACP BVALID, output
.SAXIACPBREADY(), // AXI PS Slave ACP BREADY, input
.SAXIACPBID(), // AXI PS Slave ACP BID[2:0], output
.SAXIACPBRESP(), // AXI PS Slave ACP BRESP[1:0], output
// Direct connection to PS package pads
.DDRA(), // PS DDRA[14:0], inout
.DDRBA(), // PS DDRBA[2:0], inout
.DDRCASB(), // PS DDRCASB, inout
.DDRCKE(), // PS DDRCKE, inout
.DDRCKP(), // PS DDRCKP, inout
.DDRCKN(), // PS DDRCKN, inout
.DDRCSB(), // PS DDRCSB, inout
.DDRDM(), // PS DDRDM[3:0], inout
.DDRDQ(), // PS DDRDQ[31:0], inout
.DDRDQSP(), // PS DDRDQSP[3:0], inout
.DDRDQSN(), // PS DDRDQSN[3:0], inout
.DDRDRSTB(), // PS DDRDRSTB, inout
.DDRODT(), // PS DDRODT, inout
.DDRRASB(), // PS DDRRASB, inout
.DDRVRN(), // PS DDRVRN, inout
.DDRVRP(), // PS DDRVRP, inout
.DDRWEB(), // PS DDRWEB, inout
.MIO(), // PS MIO[53:0], inout // clg225 has less
.PSCLK(), // PS PSCLK, inout
.PSPORB(), // PS PSPORB, inout
.PSSRSTB() // PS PSSRSTB, inout
);
endmodule
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