diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f4408c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +**/*.log +**/*.lx2 + + +**/CVS/* diff --git a/docs/source/regs.rst b/docs/source/regs.rst index 90246ea..ec254fc 100644 --- a/docs/source/regs.rst +++ b/docs/source/regs.rst @@ -10,11 +10,12 @@ Description: .. table:: :widths: 25 10 10 10 50 - ======= ======== ======== ========== ================================================ - Name Index Type Reset Description - ======= ======== ======== ========== ================================================ - SWRESET [0] RW 0x1 Main reset. Must be cleared prior to operation. - ======= ======== ======== ========== ================================================ + =========== ======== ======== ========== ================================================ + Name Index Type Reset Description + =========== ======== ======== ========== ================================================ + SWRESET [0] RW 0x1 Main reset. Must be cleared prior to operation. + SWRESET_MUX [1] RW 0x0 0 - Use logic, 1 - Use register + =========== ======== ======== ========== ================================================ ENABLE @@ -27,11 +28,12 @@ Description: .. table:: :widths: 25 10 10 10 50 - ====== ======== ======== ========== ====================================================================================================== - Name Index Type Reset Description - ====== ======== ======== ========== ====================================================================================================== - ENABLE [0] RW 0x0 Main enable. Must be set prior to operation. Any configurations should be performed prior to enabling. - ====== ======== ======== ========== ====================================================================================================== + ========== ======== ======== ========== ====================================================================================================== + Name Index Type Reset Description + ========== ======== ======== ========== ====================================================================================================== + ENABLE [0] RW 0x0 Main enable. Must be set prior to operation. Any configurations should be performed prior to enabling. + ENABLE_MUX [1] RW 0x0 0 - Use logic, 1 - Use register + ========== ======== ======== ========== ====================================================================================================== INTERRUPT_STATUS @@ -137,10 +139,27 @@ Description: ============= ======== ======== ========== ======================================= +SHORT_PACKET_MAX +---------------- + +Address: 0x1c + +Description: + +.. table:: + :widths: 25 10 10 10 50 + + ================ ======== ======== ========== =================================================================== + Name Index Type Reset Description + ================ ======== ======== ========== =================================================================== + SHORT_PACKET_MAX [7:0] RW 0x2f This setting allows you to change the window for short/long packets + ================ ======== ======== ========== =================================================================== + + SW_ATTR_ADDR_DATA ----------------- -Address: 0x1c +Address: 0x20 Description: @@ -158,7 +177,7 @@ Description: SW_ATTR_CONTROLS ---------------- -Address: 0x20 +Address: 0x24 Description: @@ -176,7 +195,7 @@ Description: SW_ATTR_DATA_READ ----------------- -Address: 0x24 +Address: 0x28 Description: @@ -193,7 +212,7 @@ Description: SW_ATTR_FIFO_STATUS ------------------- -Address: 0x28 +Address: 0x2c Description: @@ -213,7 +232,7 @@ Description: SW_ATTR_SHADOW_UPDATE --------------------- -Address: 0x2c +Address: 0x30 Description: @@ -230,7 +249,7 @@ Description: SW_ATTR_EFFECTIVE_UPDATE ------------------------ -Address: 0x30 +Address: 0x34 Description: @@ -247,7 +266,7 @@ Description: STATE_STATUS ------------ -Address: 0x34 +Address: 0x38 Description: @@ -268,7 +287,7 @@ Description: DEBUG_BUS_CTRL -------------- -Address: 0x38 +Address: 0x3c Description: Debug observation bus selection for signals that have a mux override @@ -278,14 +297,14 @@ Description: Debug observation bus selection for signals that have a mux overrid ================== ======== ======== ========== ================================ Name Index Type Reset Description ================== ======== ======== ========== ================================ - DEBUG_BUS_CTRL_SEL [1:0] RW 0x0 Select signal for DEBUG_BUS_CTRL + DEBUG_BUS_CTRL_SEL [2:0] RW 0x0 Select signal for DEBUG_BUS_CTRL ================== ======== ======== ========== ================================ DEBUG_BUS_STATUS ---------------- -Address: 0x3c +Address: 0x40 Description: Debug observation bus for signals that have a mux override diff --git a/docs/source/slink_attributes.rst b/docs/source/slink_attributes.rst index 517006a..25b2cd8 100644 --- a/docs/source/slink_attributes.rst +++ b/docs/source/slink_attributes.rst @@ -11,18 +11,18 @@ S-Link Attributes 0x2 active_txs 3 0 NUM_TX_LANES_CLOG2 Active TX lanes 0x3 active_rxs 3 0 NUM_RX_LANES_CLOG2 Active RX lanes 0x8 hard_reset_us 10 0 100 Time (in us) at which a Hard Reset Condition is detected. - 0x10 px_clk_trail 8 0 32 Number of clock cycles to run the bitclk when going to a P state that doesn't supply the bitclk - 0x20 p1_ts1_tx 16 0 32 TS1s to send if exiting from P1 - 0x21 p1_ts1_rx 16 0 32 TS1s to receive if exiting from P1 - 0x22 p1_ts2_tx 16 0 4 TS2s to send if exiting from P1 - 0x23 p1_ts2_rx 16 0 4 TS2s to receive if exiting from P1 - 0x24 p2_ts1_tx 16 0 64 TS1s to send if exiting from P2 - 0x25 p2_ts1_rx 16 0 64 TS1s to receive if exiting from P2 - 0x26 p2_ts2_tx 16 0 8 TS2s to send if exiting from P2 - 0x27 p2_ts2_rx 16 0 8 TS2s to receive if exiting from P2 - 0x28 p3r_ts1_tx 16 0 128 TS1s to send if exiting from P3 or when coming out of reset - 0x29 p3r_ts1_rx 16 0 128 TS1s to receive if exiting from P3 or when coming out of reset - 0x2a p3r_ts2_tx 16 0 16 TS2s to send if exiting from P3 or when coming out of reset - 0x2b p3r_ts2_rx 16 0 16 TS2s to receive if exiting from P3 or when coming out of reset - 0x30 sync_freq 8 0 15 How often SYNC Ordered Sets are sent during training + 0x10 px_clk_trail 8 0 PX_CLK_TRAIL_RESET Number of clock cycles to run the bitclk when going to a P state that doesn't supply the bitclk + 0x20 p1_ts1_tx 16 0 P1_TS1_TX_RESET TS1s to send if exiting from P1 + 0x21 p1_ts1_rx 16 0 P1_TS1_RX_RESET TS1s to receive if exiting from P1 + 0x22 p1_ts2_tx 16 0 P1_TS2_TX_RESET TS2s to send if exiting from P1 + 0x23 p1_ts2_rx 16 0 P1_TS2_RX_RESET TS2s to receive if exiting from P1 + 0x24 p2_ts1_tx 16 0 P2_TS1_TX_RESET TS1s to send if exiting from P2 + 0x25 p2_ts1_rx 16 0 P2_TS1_RX_RESET TS1s to receive if exiting from P2 + 0x26 p2_ts2_tx 16 0 P2_TS2_TX_RESET TS2s to send if exiting from P2 + 0x27 p2_ts2_rx 16 0 P2_TS2_RX_RESET TS2s to receive if exiting from P2 + 0x28 p3r_ts1_tx 16 0 P3R_TS1_TX_RESET TS1s to send if exiting from P3 or when coming out of reset + 0x29 p3r_ts1_rx 16 0 P3R_TS1_RX_RESET TS1s to receive if exiting from P3 or when coming out of reset + 0x2a p3r_ts2_tx 16 0 P3R_TS2_TX_RESET TS2s to send if exiting from P3 or when coming out of reset + 0x2b p3r_ts2_rx 16 0 P3R_TS2_RX_RESET TS2s to receive if exiting from P3 or when coming out of reset + 0x30 sync_freq 8 0 SYNC_FREQ_RESET How often SYNC Ordered Sets are sent during training ======== ============= ====== ======== ================== =============================================================================================== diff --git a/rtl/app/amba/slink_apb_ini.v b/rtl/app/amba/slink_apb_ini.v new file mode 100644 index 0000000..d905f5b --- /dev/null +++ b/rtl/app/amba/slink_apb_ini.v @@ -0,0 +1,261 @@ +module slink_apb_ini #( + parameter TX_APP_DATA_WIDTH = 128, + parameter RX_APP_DATA_WIDTH = 128, + + parameter [7:0] APB_READ_DT = 8'h24, + parameter [7:0] APB_READ_RSP_DT = 8'h25, + parameter [7:0] APB_WRITE_DT = 8'h26, + parameter [7:0] APB_WRITE_RSP_DT = 8'h27 +)( + input wire apb_clk, + input wire apb_reset, + output reg [31:0] apb_paddr, + output reg apb_pwrite, + output reg apb_psel, + output reg apb_penable, + output reg [31:0] apb_pwdata, + input wire [31:0] apb_prdata, + input wire apb_pready, + input wire apb_pslverr, + + input wire enable, + + input wire [7:0] swi_cr_id, + input wire [7:0] swi_crack_id, + input wire [7:0] swi_ack_id, + input wire [7:0] swi_nack_id, + + output wire nack_sent, + output wire nack_seen, + output reg invalid_resp_pkt, + + input wire link_clk, + input wire link_reset, + + output wire tx_sop, + output wire [7:0] tx_data_id, + output wire [15:0] tx_word_count, + output wire [TX_APP_DATA_WIDTH-1:0] tx_app_data, + input wire tx_advance, + + input wire rx_sop, + input wire [7:0] rx_data_id, + input wire [15:0] rx_word_count, + input wire [RX_APP_DATA_WIDTH-1:0] rx_app_data, + input wire rx_valid, + input wire rx_crc_corrupted +); + +//localparam A2L_DATA_WIDTH = 64 + 24; +localparam A2L_DATA_WIDTH = 33 + 24; +localparam L2A_DATA_WIDTH = 64 + 24; + +localparam [15:0] APB_READ_RSP_WC = 5; +localparam [15:0] APB_WRITE_RSP_WC = 1; + +localparam IDLE = 'd0, + APB_READ = 'd1, + APB_WRITE = 'd2, + HOLD_STATE = 'd3; + +/* +Byte [ 7: 0] | [15: 8] | [23:16] | [31:24] | [39:32] | [47:40] | [55:48] | [63:56] | [71:64] +APB READ [ ADDR ] +APB READ Response [ DATA ] [SLVERR] +APB WRITE [ ADDR ] [ DATA ] [PSTRB??] +APB WRITE Response [SLVERR] +*/ + +reg [2:0] state, nstate; +wire enable_apb_clk; + +reg [A2L_DATA_WIDTH-1:0] a2l_data; +reg a2l_valid; +wire a2l_ready; + +wire [L2A_DATA_WIDTH-1:0] l2a_data; +wire [L2A_DATA_WIDTH-24-1:0] l2a_data_dtwc_stripped; +wire l2a_valid; +reg l2a_accept; + +wire read_data_pkt; +wire write_data_pkt; +reg was_write, was_write_in; + +reg [31:0] apb_prdata_reg, apb_prdata_reg_in; +reg apb_pslverr_reg, apb_pslverr_reg_in; + + +slink_demet_reset u_slink_demet_reset_enable ( + .clk ( apb_clk ), + .reset ( apb_reset ), + .sig_in ( enable ), + .sig_out ( enable_apb_clk )); + +always @(posedge apb_clk or posedge apb_reset) begin + if(apb_reset) begin + state <= IDLE; + was_write <= 1'b0; + apb_prdata_reg <= 32'd0; + apb_pslverr_reg <= 1'b0; + end else begin + state <= nstate; + was_write <= was_write_in; + apb_prdata_reg <= apb_prdata_reg_in; + apb_pslverr_reg <= apb_pslverr_reg_in; + end +end + +assign write_data_pkt = l2a_data[7:0] == APB_WRITE_DT; +assign read_data_pkt = l2a_data[7:0] == APB_READ_DT; +assign l2a_data_dtwc_stripped = l2a_data[L2A_DATA_WIDTH-1:24]; + +always @(*) begin + nstate = state; + apb_psel = 1'b0; + apb_penable = 1'b0; + apb_pwrite = 1'b0; + apb_paddr = 32'd0; + apb_pwdata = 32'd0; + l2a_accept = 1'b0; + a2l_data = {A2L_DATA_WIDTH{1'b0}}; + a2l_valid = 1'b0; + was_write_in = was_write; + apb_prdata_reg_in = apb_prdata_reg; + apb_pslverr_reg_in = apb_pslverr_reg; + invalid_resp_pkt = 1'b0; + + case(state) + //--------------------------------- + IDLE : begin + if(enable_apb_clk) begin + if(l2a_valid) begin + if(write_data_pkt) begin + apb_psel = 1'b1; + apb_paddr = l2a_data_dtwc_stripped[31:0]; + apb_pwdata = l2a_data_dtwc_stripped[63:32]; + apb_pwrite = 1'b1; + nstate = APB_WRITE; + end else if(read_data_pkt) begin + apb_psel = 1'b1; + apb_paddr = l2a_data_dtwc_stripped[31:0]; + nstate = APB_READ; + end else begin + invalid_resp_pkt = 1'b1; + end + end + end + end + + //--------------------------------- + APB_WRITE : begin + apb_psel = 1'b1; + apb_paddr = l2a_data_dtwc_stripped[31:0]; + apb_pwdata = l2a_data_dtwc_stripped[63:32]; + apb_pwrite = 1'b1; + apb_penable = 1'b1; + was_write_in = 1'b1; + + if(apb_pready) begin //should it check pslverr here? + l2a_accept = 1'b1; + if(a2l_ready) begin + a2l_data = {{A2L_DATA_WIDTH-25{1'b0}}, apb_pslverr, APB_WRITE_RSP_WC, APB_WRITE_RSP_DT}; + a2l_valid = 1'b1; + nstate = IDLE; + end else begin + apb_pslverr_reg_in = apb_pslverr; + nstate = HOLD_STATE; + end + end + end + + //--------------------------------- + APB_READ : begin + apb_psel = 1'b1; + apb_paddr = l2a_data_dtwc_stripped[31:0]; + apb_pwrite = 1'b0; + apb_penable = 1'b1; + was_write_in = 1'b0; + + if(apb_pready) begin //should it check pslverr here? + l2a_accept = 1'b1; + if(a2l_ready) begin + a2l_data = {{A2L_DATA_WIDTH-57{1'b0}}, apb_pslverr, apb_prdata, APB_READ_RSP_WC, APB_READ_RSP_DT}; + a2l_valid = 1'b1; + nstate = IDLE; + end else begin + apb_pslverr_reg_in = apb_pslverr; + apb_prdata_reg_in = apb_prdata; + nstate = HOLD_STATE; + end + end + end + + //HOLD STATE for cases where we need to stop the transaction + //but can't send the data back + HOLD_STATE : begin + if(a2l_ready) begin + if(was_write) begin + a2l_data = {{A2L_DATA_WIDTH-25{1'b0}}, apb_pslverr_reg, APB_WRITE_RSP_WC, APB_WRITE_RSP_DT}; + a2l_valid = 1'b1; + end else begin + a2l_data = {{A2L_DATA_WIDTH-57{1'b0}}, apb_pslverr_reg, apb_prdata_reg, APB_READ_RSP_WC, APB_READ_RSP_DT}; + a2l_valid = 1'b1; + end + nstate = IDLE; + end + end + + + default : begin + nstate = IDLE; + end + endcase +end + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( A2L_DATA_WIDTH ), + .A2L_DEPTH ( 2 ), + .L2A_DATA_WIDTH ( L2A_DATA_WIDTH ), + .L2A_DEPTH ( 2 ), //see if 2 works + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ) + +) u_slink_generic_fc_sm ( + .app_clk ( apb_clk ), + .app_reset ( apb_reset ), + .enable ( enable ), + .swi_cr_id ( swi_cr_id ), + .swi_crack_id ( swi_crack_id ), + .swi_ack_id ( swi_ack_id ), + .swi_nack_id ( swi_nack_id ), + .swi_data_id ( 8'hff ), + .swi_word_count ( 16'd0 ), + .a2l_valid ( a2l_valid ), + .a2l_ready ( a2l_ready ), + .a2l_data ( a2l_data ), + .l2a_valid ( l2a_valid ), + .l2a_accept ( l2a_accept ), + .l2a_data ( l2a_data ), + .tx_fifo_empty ( ), + .rx_fifo_empty ( ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( nack_sent ), + .nack_seen ( nack_seen ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted )); + + + +endmodule diff --git a/rtl/app/amba/slink_apb_tgt.v b/rtl/app/amba/slink_apb_tgt.v new file mode 100644 index 0000000..2aa6031 --- /dev/null +++ b/rtl/app/amba/slink_apb_tgt.v @@ -0,0 +1,238 @@ +module slink_apb_tgt #( + parameter TX_APP_DATA_WIDTH = 128, + parameter RX_APP_DATA_WIDTH = 128, + + parameter [7:0] APB_READ_DT = 8'h24, + parameter [7:0] APB_READ_RSP_DT = 8'h25, + parameter [7:0] APB_WRITE_DT = 8'h26, + parameter [7:0] APB_WRITE_RSP_DT = 8'h27 +)( + input wire apb_clk, + input wire apb_reset, + input wire [31:0] apb_paddr, + input wire apb_pwrite, + input wire apb_psel, + input wire apb_penable, + input wire [31:0] apb_pwdata, + output reg [31:0] apb_prdata, + output reg apb_pready, + output reg apb_pslverr, + + input wire enable, + + input wire [7:0] swi_cr_id, + input wire [7:0] swi_crack_id, + input wire [7:0] swi_ack_id, + input wire [7:0] swi_nack_id, + + output wire nack_sent, + output wire nack_seen, + output reg invalid_resp_pkt, + + input wire link_clk, + input wire link_reset, + + output wire tx_sop, + output wire [7:0] tx_data_id, + output wire [15:0] tx_word_count, + output wire [TX_APP_DATA_WIDTH-1:0] tx_app_data, + input wire tx_advance, + + input wire rx_sop, + input wire [7:0] rx_data_id, + input wire [15:0] rx_word_count, + input wire [RX_APP_DATA_WIDTH-1:0] rx_app_data, + input wire rx_valid, + input wire rx_crc_corrupted +); + +localparam A2L_DATA_WIDTH = 64 + 24; +localparam L2A_DATA_WIDTH = 33 + 24; + +localparam [15:0] APB_READ_WC = 4; +localparam [15:0] APB_WRITE_WC = 8; + +localparam IDLE = 'd0, + APB_READ = 'd1, + APB_WRITE = 'd2, + APB_STALL = 'd3; + + +/* +Byte [ 7: 0] | [15: 8] | [23:16] | [31:24] | [39:32] | [47:40] | [55:48] | [63:56] | [71:64] +APB READ [ ADDR ] +APB READ Response [ DATA ] [SLVERR] +APB WRITE [ ADDR ] [ DATA ] [PSTRB??] +APB WRITE Response [SLVERR] +*/ + +reg [2:0] state, nstate; +wire enable_apb_clk; + +reg [A2L_DATA_WIDTH-1:0] a2l_data; +reg [A2L_DATA_WIDTH-24-1:0] a2l_data_dtwc_stripped; +reg a2l_valid; +wire a2l_ready; + +wire [L2A_DATA_WIDTH-1:0] l2a_data; +wire [L2A_DATA_WIDTH-24-1:0] l2a_data_dtwc_stripped; +wire l2a_valid; +reg l2a_accept; + +wire read_rsp_pkt; +wire write_rsp_pkt; + +slink_demet_reset u_slink_demet_reset_enable ( + .clk ( apb_clk ), + .reset ( apb_reset ), + .sig_in ( enable ), + .sig_out ( enable_apb_clk )); + +always @(posedge apb_clk or posedge apb_reset) begin + if(apb_reset) begin + state <= IDLE; + end else begin + state <= nstate; + end +end + +assign write_rsp_pkt = l2a_data[7:0] == APB_WRITE_RSP_DT; +assign read_rsp_pkt = l2a_data[7:0] == APB_READ_RSP_DT; +assign l2a_data_dtwc_stripped = l2a_data[L2A_DATA_WIDTH-1:24]; + + +always @(*) begin + nstate = state; + apb_prdata = 32'd0; + apb_pready = 1'b0; + apb_pslverr = 1'b0; + a2l_data_dtwc_stripped = {A2L_DATA_WIDTH-24{1'b0}}; + a2l_data = {A2L_DATA_WIDTH{1'b0}}; + a2l_valid = 1'b0; + + l2a_accept = 1'b0; + invalid_resp_pkt = 1'b0; + + case(state) + //--------------------------------- + IDLE : begin + if(enable_apb_clk) begin + if(apb_psel && ~apb_penable) begin //should I add an error for psel and enable? + if(apb_pwrite) begin + a2l_data_dtwc_stripped = {apb_pwdata, apb_paddr}; + a2l_data = {a2l_data_dtwc_stripped, APB_WRITE_WC, APB_WRITE_DT}; + a2l_valid = 1'b1; + nstate = a2l_ready ? APB_WRITE : APB_STALL; + end else begin + a2l_data_dtwc_stripped = {32'd0, apb_paddr}; + a2l_data = {a2l_data_dtwc_stripped, APB_READ_WC, APB_READ_DT}; + a2l_valid = 1'b1; + nstate = a2l_ready ? APB_READ : APB_STALL; + end + end + end + end + + //--------------------------------- + //If a2l_ready is not asserted just wait here until we are good to go + APB_STALL : begin + if(apb_pwrite) begin + a2l_data_dtwc_stripped = {apb_pwdata, apb_paddr}; + a2l_data = {a2l_data_dtwc_stripped, APB_WRITE_WC, APB_WRITE_DT}; + a2l_valid = 1'b1; + nstate = a2l_ready ? APB_WRITE : APB_STALL; + end else begin + a2l_data_dtwc_stripped = {32'd0, apb_paddr}; + a2l_data = {a2l_data_dtwc_stripped, APB_READ_WC, APB_READ_DT}; + a2l_valid = 1'b1; + nstate = a2l_ready ? APB_READ : APB_STALL; + end + end + + //--------------------------------- + APB_WRITE : begin + if(l2a_valid) begin + if(write_rsp_pkt) begin + apb_pready = 1'b1; + apb_pslverr = l2a_data_dtwc_stripped[0]; + l2a_accept = 1'b1; + nstate = IDLE; + end else begin + invalid_resp_pkt= 1'b1; + end + end + end + + + //--------------------------------- + APB_READ : begin + if(l2a_valid) begin + if(read_rsp_pkt) begin + apb_pready = 1'b1; + apb_prdata = l2a_data_dtwc_stripped[31:0]; + apb_pslverr = l2a_data_dtwc_stripped[32]; + l2a_accept = 1'b1; + nstate = IDLE; + end else begin + invalid_resp_pkt= 1'b1; + end + end + end + + default : begin + nstate = IDLE; + end + + endcase + + if(~enable_apb_clk) begin + nstate = IDLE; + end +end + + + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( A2L_DATA_WIDTH ), + .A2L_DEPTH ( 2 ), + .L2A_DATA_WIDTH ( L2A_DATA_WIDTH ), + .L2A_DEPTH ( 2 ), //see if 2 works + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ) + +) u_slink_generic_fc_sm ( + .app_clk ( apb_clk ), + .app_reset ( apb_reset ), + .enable ( enable ), + .swi_cr_id ( swi_cr_id ), + .swi_crack_id ( swi_crack_id ), + .swi_ack_id ( swi_ack_id ), + .swi_nack_id ( swi_nack_id ), + .swi_data_id ( 8'hff ), + .swi_word_count ( 16'd0 ), + .a2l_valid ( a2l_valid ), + .a2l_ready ( a2l_ready ), + .a2l_data ( a2l_data ), + .l2a_valid ( l2a_valid ), + .l2a_accept ( l2a_accept ), + .l2a_data ( l2a_data ), + .tx_fifo_empty ( ), + .rx_fifo_empty ( ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( nack_sent ), + .nack_seen ( nack_seen ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted )); + +endmodule diff --git a/rtl/app/amba/slink_axi_ini.v b/rtl/app/amba/slink_axi_ini.v new file mode 100644 index 0000000..becc051 --- /dev/null +++ b/rtl/app/amba/slink_axi_ini.v @@ -0,0 +1,230 @@ +module slink_axi_ini #( + parameter AXI_ADDR_WIDTH = 32, //8/16/24/32/40/48/56/64 (I hope to be retired by the time we need 128) + parameter AXI_DATA_WIDTH = 64, //32/64/128/256/512/1024 + parameter APPLICATION_DEPTH = 8, + parameter SEPARATE_AXI_CHANNELS = 0, //0 - One main main for all transmit traffic, 1 - Each channel has it's own traffic path + + parameter TX_APP_DATA_WIDTH = 32, + parameter RX_APP_DATA_WIDTH = 32, + + + parameter AW_PKT_DT = 8'h20, + parameter W_PKT_DT = 8'h21, + parameter B_PKT_DT = 8'h22, + parameter AR_PKT_DT = 8'h23, + parameter R_PKT_DT = 8'h24 +)( + input wire axi_clk, + input wire axi_reset, + + output wire [7:0] ini_awid, + output wire [AXI_ADDR_WIDTH-1:0] ini_awaddr, + output wire [7:0] ini_awlen, + output wire [2:0] ini_awsize, + output wire [1:0] ini_awburst, + output wire [1:0] ini_awlock, + output wire [3:0] ini_awcache, + output wire [2:0] ini_awprot, + output wire [3:0] ini_awqos, + output wire [3:0] ini_awregion, + output wire ini_awvalid, + input wire ini_awready, + + output wire [7:0] ini_wid, + output wire [AXI_DATA_WIDTH-1:0] ini_wdata, + output wire [(AXI_DATA_WIDTH/8)-1:0] ini_wstrb, + output wire ini_wlast, + output wire ini_wvalid, + input wire ini_wready, + + input wire [7:0] ini_bid, + input wire [1:0] ini_bresp, + input wire ini_bvalid, + output wire ini_bready, + + output wire [7:0] ini_arid, + output wire [AXI_ADDR_WIDTH-1:0] ini_araddr, + output wire [7:0] ini_arlen, + output wire [2:0] ini_arsize, + output wire [1:0] ini_arburst, + output wire [1:0] ini_arlock, + output wire [3:0] ini_arcache, + output wire [2:0] ini_arprot, + output wire [3:0] ini_arqos, + output wire [3:0] ini_arregion, + output wire ini_arvalid, + input wire ini_arready, + + input wire [7:0] ini_rid, + input wire [AXI_DATA_WIDTH-1:0] ini_rdata, + input wire [1:0] ini_rresp, + input wire ini_rlast, + input wire ini_rvalid, + output wire ini_rready, + + input wire enable, + + input wire link_clk, + input wire link_reset, + + output wire tx_sop, + output wire [7:0] tx_data_id, + output wire [15:0] tx_word_count, + output wire [TX_APP_DATA_WIDTH-1:0] tx_app_data, + input wire tx_advance, + + input wire rx_sop, + input wire [7:0] rx_data_id, + input wire [15:0] rx_word_count, + input wire [RX_APP_DATA_WIDTH-1:0] rx_app_data, + input wire rx_valid, + input wire rx_crc_corrupted + + +); + +localparam DATA_CHANNEL_WIDTH = 1 + 8 + AXI_DATA_WIDTH + (AXI_DATA_WIDTH/8); //W channel is always larger than R/B due to WSTRB's +localparam ADDR_CHANNEL_WIDTH = 38 + AXI_ADDR_WIDTH; //AW/AR are same size + +localparam AW_PKT_WC = 6 + (AXI_ADDR_WIDTH/8); +localparam WSTRB_WC = AXI_DATA_WIDTH == 8 ? 1 : + AXI_DATA_WIDTH == 16 ? 1 : + AXI_DATA_WIDTH == 32 ? 1 : + AXI_DATA_WIDTH == 64 ? 1 : + AXI_DATA_WIDTH == 128 ? 2 : + AXI_DATA_WIDTH == 256 ? 4 : + AXI_DATA_WIDTH == 512 ? 8 : 16; +localparam W_PKT_WC = 2 + (AXI_DATA_WIDTH/8) + WSTRB_WC; +localparam B_PKT_WC = 3; +localparam AR_PKT_WC = 6 + (AXI_ADDR_WIDTH/8); +localparam R_PKT_WC = 2 + (AXI_DATA_WIDTH/8); + + +generate + if(SEPARATE_AXI_CHANNELS == 0) begin : gen_single_axi_channel + localparam DATA_IS_LARGER = DATA_CHANNEL_WIDTH >= ADDR_CHANNEL_WIDTH; + + //Swapped from Target + localparam L2A_FC_DATA_PATH_WIDTH = DATA_IS_LARGER ? DATA_CHANNEL_WIDTH + 24 : + ADDR_CHANNEL_WIDTH + 24; + localparam A2L_FC_DATA_PATH_WIDTH = 2 + 8 + AXI_DATA_WIDTH + 24; //Read Data channel + + wire [A2L_FC_DATA_PATH_WIDTH-1:0] ini_b_data; + wire [A2L_FC_DATA_PATH_WIDTH-1:0] ini_r_data; + + wire a2l_valid; + wire a2l_ready; + wire [A2L_FC_DATA_PATH_WIDTH-1:0] a2l_data; + + wire l2a_valid; + wire l2a_accept; + wire [L2A_FC_DATA_PATH_WIDTH-1:0] l2a_data; + + assign ini_b_data = {{(A2L_FC_DATA_PATH_WIDTH-24-8-2){1'b0}}, + ini_bresp, + ini_bid, + B_PKT_WC[15:0], + B_PKT_DT}; + + assign ini_r_data = {ini_rdata, + ini_rlast, + ini_rresp, + ini_rid, + B_PKT_WC[15:0], + B_PKT_DT}; + + + assign ini_bready = a2l_ready; + assign ini_rready = a2l_ready & ~ini_bready; + + assign a2l_data = (ini_bready && ini_bvalid) ? ini_b_data : + (ini_rready && ini_rvalid) ? ini_r_data :{A2L_FC_DATA_PATH_WIDTH{1'b0}}; + assign a2l_valid = (ini_bready && ini_bvalid) || + (ini_rready && ini_rvalid); + + + + assign ini_awid = l2a_data[31:24]; + assign ini_awlen = l2a_data[39:32]; + assign ini_awsize = l2a_data[42:40]; + assign ini_awburst = l2a_data[44:43]; + assign ini_awlock = l2a_data[46:45]; + assign ini_awcache = l2a_data[50:47]; + assign ini_awprot = l2a_data[53:51]; + assign ini_awqos = l2a_data[57:54]; + assign ini_awregion = l2a_data[61:58]; + assign ini_awaddr = l2a_data[62+AXI_ADDR_WIDTH:62]; + assign ini_awvalid = (l2a_data[ 7: 0] == AW_PKT_DT) && l2a_valid; + + + assign ini_wid = l2a_data[31:24]; + assign ini_wlast = l2a_data[32]; + assign ini_wstrb = l2a_data[33+(AXI_DATA_WIDTH/8)-1:33]; + assign ini_wdata = l2a_data[33+(AXI_DATA_WIDTH/8)+1+AXI_DATA_WIDTH-1 : 33+(AXI_DATA_WIDTH/8)]; + assign ini_wvalid = (l2a_data[ 7: 0] == W_PKT_DT) && l2a_valid; + + assign ini_arid = l2a_data[31:24]; + assign ini_arlen = l2a_data[39:32]; + assign ini_arsize = l2a_data[42:40]; + assign ini_arburst = l2a_data[44:43]; + assign ini_arlock = l2a_data[46:45]; + assign ini_arcache = l2a_data[50:47]; + assign ini_arprot = l2a_data[53:51]; + assign ini_arqos = l2a_data[57:54]; + assign ini_arregion = l2a_data[61:58]; + assign ini_araddr = l2a_data[62+AXI_ADDR_WIDTH:62]; + assign ini_arvalid = (l2a_data[ 7: 0] == AR_PKT_DT) && l2a_valid; + + assign l2a_accept = ini_awvalid ? ini_awready : + ini_wvalid ? ini_wready : + ini_arvalid ? ini_arready : 1'b0; + + slink_generic_fc_sm #( + //parameters + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .A2L_DEPTH ( APPLICATION_DEPTH ), + .A2L_DATA_WIDTH ( A2L_FC_DATA_PATH_WIDTH ), + .L2A_DEPTH ( APPLICATION_DEPTH ), + .L2A_DATA_WIDTH ( L2A_FC_DATA_PATH_WIDTH ) + ) u_slink_generic_fc_sm ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + + .swi_cr_id ( 8'h12 ), + .swi_crack_id ( 8'h13 ), + .swi_ack_id ( 8'h10 ), + .swi_nack_id ( 8'h11 ), + + .a2l_valid ( a2l_valid ), + .a2l_ready ( a2l_ready ), + .a2l_data ( a2l_data ), + + .l2a_valid ( l2a_valid ), + .l2a_accept ( l2a_accept ), + .l2a_data ( l2a_data ), + + .tx_fifo_empty ( ), + .rx_fifo_empty ( ), + + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted )); + + end else begin : gen_multi_axi_channel + + end +endgenerate + +endmodule diff --git a/rtl/app/amba/slink_axi_tgt.v b/rtl/app/amba/slink_axi_tgt.v new file mode 100644 index 0000000..78d0f3e --- /dev/null +++ b/rtl/app/amba/slink_axi_tgt.v @@ -0,0 +1,640 @@ +module slink_axi_tgt #( + parameter AXI_ADDR_WIDTH = 32, //8/16/24/32/40/48/56/64 (I hope to be retired by the time we need 128) + parameter AXI_DATA_WIDTH = 64, //32/64/128/256/512/1024 + parameter DATA_CH_APP_DEPTH = 16, + parameter ADDR_CH_APP_DEPTH = 4, + + parameter TX_APP_DATA_WIDTH = 32, + parameter RX_APP_DATA_WIDTH = 32 +)( + input wire axi_clk, + input wire axi_reset, + + //-------------------------------------- + // AXI Target + //-------------------------------------- + input wire [7:0] tgt_awid, + input wire [AXI_ADDR_WIDTH-1:0] tgt_awaddr, + input wire [7:0] tgt_awlen, + input wire [2:0] tgt_awsize, + input wire [1:0] tgt_awburst, + input wire [1:0] tgt_awlock, + input wire [3:0] tgt_awcache, + input wire [2:0] tgt_awprot, + input wire [3:0] tgt_awqos, + input wire [3:0] tgt_awregion, + input wire tgt_awvalid, + output wire tgt_awready, + + input wire [7:0] tgt_wid, + input wire [AXI_DATA_WIDTH-1:0] tgt_wdata, + input wire [(AXI_DATA_WIDTH/8)-1:0] tgt_wstrb, + input wire tgt_wlast, + input wire tgt_wvalid, + output wire tgt_wready, + + output wire [7:0] tgt_bid, + output wire [1:0] tgt_bresp, + output wire tgt_bvalid, + input wire tgt_bready, + + input wire [7:0] tgt_arid, + input wire [AXI_ADDR_WIDTH-1:0] tgt_araddr, + input wire [7:0] tgt_arlen, + input wire [2:0] tgt_arsize, + input wire [1:0] tgt_arburst, + input wire [1:0] tgt_arlock, + input wire [3:0] tgt_arcache, + input wire [2:0] tgt_arprot, + input wire [3:0] tgt_arqos, + input wire [3:0] tgt_arregion, + input wire tgt_arvalid, + output wire tgt_arready, + + output wire [7:0] tgt_rid, + output wire [AXI_DATA_WIDTH-1:0] tgt_rdata, + output wire [1:0] tgt_rresp, + output wire tgt_rlast, + output wire tgt_rvalid, + input wire tgt_rready, + + //-------------------------------------- + // AXI Initiator + //-------------------------------------- + output wire [7:0] ini_awid, + output wire [AXI_ADDR_WIDTH-1:0] ini_awaddr, + output wire [7:0] ini_awlen, + output wire [2:0] ini_awsize, + output wire [1:0] ini_awburst, + output wire [1:0] ini_awlock, + output wire [3:0] ini_awcache, + output wire [2:0] ini_awprot, + output wire [3:0] ini_awqos, + output wire [3:0] ini_awregion, + output wire ini_awvalid, + input wire ini_awready, + + output wire [7:0] ini_wid, + output wire [AXI_DATA_WIDTH-1:0] ini_wdata, + output wire [(AXI_DATA_WIDTH/8)-1:0] ini_wstrb, + output wire ini_wlast, + output wire ini_wvalid, + input wire ini_wready, + + input wire [7:0] ini_bid, + input wire [1:0] ini_bresp, + input wire ini_bvalid, + output wire ini_bready, + + output wire [7:0] ini_arid, + output wire [AXI_ADDR_WIDTH-1:0] ini_araddr, + output wire [7:0] ini_arlen, + output wire [2:0] ini_arsize, + output wire [1:0] ini_arburst, + output wire [1:0] ini_arlock, + output wire [3:0] ini_arcache, + output wire [2:0] ini_arprot, + output wire [3:0] ini_arqos, + output wire [3:0] ini_arregion, + output wire ini_arvalid, + input wire ini_arready, + + input wire [7:0] ini_rid, + input wire [AXI_DATA_WIDTH-1:0] ini_rdata, + input wire [1:0] ini_rresp, + input wire ini_rlast, + input wire ini_rvalid, + output wire ini_rready, + + + //-------------------------------------- + // Controls + //-------------------------------------- + input wire enable, + + input wire [7:0] swi_aw_cr_id, + input wire [7:0] swi_aw_crack_id, + input wire [7:0] swi_aw_ack_id, + input wire [7:0] swi_aw_nack_id, + input wire [7:0] swi_aw_data_id, + + input wire [7:0] swi_w_cr_id, + input wire [7:0] swi_w_crack_id, + input wire [7:0] swi_w_ack_id, + input wire [7:0] swi_w_nack_id, + input wire [7:0] swi_w_data_id, + + input wire [7:0] swi_b_cr_id, + input wire [7:0] swi_b_crack_id, + input wire [7:0] swi_b_ack_id, + input wire [7:0] swi_b_nack_id, + input wire [7:0] swi_b_data_id, + + input wire [7:0] swi_ar_cr_id, + input wire [7:0] swi_ar_crack_id, + input wire [7:0] swi_ar_ack_id, + input wire [7:0] swi_ar_nack_id, + input wire [7:0] swi_ar_data_id, + + input wire [7:0] swi_r_cr_id, + input wire [7:0] swi_r_crack_id, + input wire [7:0] swi_r_ack_id, + input wire [7:0] swi_r_nack_id, + input wire [7:0] swi_r_data_id, + + //-------------------------------------- + // Link Layer + //-------------------------------------- + input wire link_clk, + input wire link_reset, + + output wire tx_sop, + output wire [7:0] tx_data_id, + output wire [15:0] tx_word_count, + output wire [TX_APP_DATA_WIDTH-1:0] tx_app_data, + input wire tx_advance, + + input wire rx_sop, + input wire [7:0] rx_data_id, + input wire [15:0] rx_word_count, + input wire [RX_APP_DATA_WIDTH-1:0] rx_app_data, + input wire rx_valid, + input wire rx_crc_corrupted + + +); + + + +localparam WDATA_CHANNEL_WIDTH = 1 + 8 + AXI_DATA_WIDTH + (AXI_DATA_WIDTH/8); //W channel is always larger than R/B due to WSTRB's +localparam RDATA_CHANNEL_WIDTH = 1 + 8 + AXI_DATA_WIDTH + 2; +localparam ADDR_CHANNEL_WIDTH = 38 + AXI_ADDR_WIDTH; //AW/AR are same size +localparam B_CHANNEL_WIDTH = 10; + +localparam [15:0] AW_PKT_WC = 5 + (AXI_ADDR_WIDTH/8); +localparam [15:0] WSTRB_WC = AXI_DATA_WIDTH == 8 ? 1 : + AXI_DATA_WIDTH == 16 ? 1 : + AXI_DATA_WIDTH == 32 ? 1 : + AXI_DATA_WIDTH == 64 ? 1 : + AXI_DATA_WIDTH == 128 ? 2 : + AXI_DATA_WIDTH == 256 ? 4 : + AXI_DATA_WIDTH == 512 ? 8 : 16; +localparam [15:0] W_PKT_WC = 2 + (AXI_DATA_WIDTH/8) + WSTRB_WC; +localparam [15:0] B_PKT_WC = 2; +localparam [15:0] AR_PKT_WC = 5 + (AXI_ADDR_WIDTH/8); +localparam [15:0] R_PKT_WC = 2 + (AXI_DATA_WIDTH/8); + + + + +//------------------------------------------ +// ADDR Write Channel +//------------------------------------------ +wire aw_tx_sop; +wire [7:0] aw_tx_data_id; +wire [15:0] aw_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] aw_tx_app_data; +wire aw_tx_advance; + +wire aw_rx_sop; +wire [7:0] aw_rx_data_id; +wire [15:0] aw_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] aw_rx_app_data; +wire aw_rx_valid; +wire aw_rx_crc_corrupted; + +wire aw_a2l_valid; +wire aw_a2l_ready; +wire [ADDR_CHANNEL_WIDTH-1:0] aw_a2l_data; + +wire aw_l2a_valid; +wire aw_l2a_accept; +wire [ADDR_CHANNEL_WIDTH-1:0] aw_l2a_data; + +assign aw_a2l_data = {tgt_awaddr, + tgt_awregion, + tgt_awqos, + tgt_awprot, + tgt_awcache, + tgt_awlock, + tgt_awburst, + tgt_awsize, + tgt_awlen, + tgt_awid}; +assign tgt_awready = aw_a2l_ready; + +assign aw_a2l_valid = tgt_awvalid; + + +assign ini_awvalid = aw_l2a_valid; +assign ini_awaddr = aw_l2a_data[38+AXI_ADDR_WIDTH-1:38]; +assign ini_awregion = aw_l2a_data[37:34]; +assign ini_awqos = aw_l2a_data[33:30]; +assign ini_awprot = aw_l2a_data[29:27]; +assign ini_awcache = aw_l2a_data[26:23]; +assign ini_awlock = aw_l2a_data[22:21]; +assign ini_awburst = aw_l2a_data[20:19]; +assign ini_awsize = aw_l2a_data[18:16]; +assign ini_awlen = aw_l2a_data[15: 8]; +assign ini_awid = aw_l2a_data[ 7: 0]; + +assign aw_l2a_accept= ini_awready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( ADDR_CHANNEL_WIDTH ), + .A2L_DEPTH ( ADDR_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( ADDR_CHANNEL_WIDTH ), + .L2A_DEPTH ( ADDR_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_AW_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_aw_cr_id ), + .swi_crack_id ( swi_aw_crack_id ), + .swi_ack_id ( swi_aw_ack_id ), + .swi_nack_id ( swi_aw_nack_id ), + .swi_data_id ( swi_aw_data_id ), + .swi_word_count ( AW_PKT_WC ), + .a2l_valid ( aw_a2l_valid ), + .a2l_ready ( aw_a2l_ready ), + .a2l_data ( aw_a2l_data ), + .l2a_valid ( aw_l2a_valid ), + .l2a_accept ( aw_l2a_accept ), + .l2a_data ( aw_l2a_data ), + .tx_fifo_empty ( ), //output - 1 + .rx_fifo_empty ( ), //output - 1 + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( ), //output - 1 + .nack_seen ( ), //output - 1 + .tx_sop ( aw_tx_sop ), + .tx_data_id ( aw_tx_data_id ), + .tx_word_count ( aw_tx_word_count ), + .tx_app_data ( aw_tx_app_data ), + .tx_advance ( aw_tx_advance ), + .rx_sop ( aw_rx_sop ), + .rx_data_id ( aw_rx_data_id ), + .rx_word_count ( aw_rx_word_count ), + .rx_app_data ( aw_rx_app_data ), + .rx_valid ( aw_rx_valid ), + .rx_crc_corrupted ( aw_rx_crc_corrupted )); + + + +//------------------------------------------ +// Write Data Channel +//------------------------------------------ +wire w_tx_sop; +wire [7:0] w_tx_data_id; +wire [15:0] w_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] w_tx_app_data; +wire w_tx_advance; + +wire w_rx_sop; +wire [7:0] w_rx_data_id; +wire [15:0] w_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] w_rx_app_data; +wire w_rx_valid; +wire w_rx_crc_corrupted; + +wire w_a2l_valid; +wire w_a2l_ready; +wire [WDATA_CHANNEL_WIDTH-1:0] w_a2l_data; + +wire w_l2a_valid; +wire w_l2a_accept; +wire [WDATA_CHANNEL_WIDTH-1:0] w_l2a_data; + +assign w_a2l_data = {tgt_wdata, + tgt_wstrb, + tgt_wlast, + tgt_wid}; +assign tgt_wready = aw_a2l_ready; + +assign w_a2l_valid = tgt_wvalid; + +assign ini_wvalid = w_l2a_valid; +assign ini_wdata = w_l2a_data[9+(AXI_DATA_WIDTH/8)+1+AXI_DATA_WIDTH-1 : 9+(AXI_DATA_WIDTH/8)]; +assign ini_wstrb = w_l2a_data[9+(AXI_DATA_WIDTH/8)-1:9]; +assign ini_wlast = w_l2a_data[8]; +assign ini_wid = w_l2a_data[7:0]; + +assign w_l2a_accept = ini_wready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( WDATA_CHANNEL_WIDTH ), + .A2L_DEPTH ( DATA_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( WDATA_CHANNEL_WIDTH ), + .L2A_DEPTH ( DATA_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_W_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_w_cr_id ), + .swi_crack_id ( swi_w_crack_id ), + .swi_ack_id ( swi_w_ack_id ), + .swi_nack_id ( swi_w_nack_id ), + .swi_data_id ( swi_w_data_id ), + .swi_word_count ( W_PKT_WC ), + .a2l_valid ( w_a2l_valid ), + .a2l_ready ( w_a2l_ready ), + .a2l_data ( w_a2l_data ), + .l2a_valid ( w_l2a_valid ), + .l2a_accept ( w_l2a_accept ), + .l2a_data ( w_l2a_data ), + .tx_fifo_empty ( ), //output - 1 + .rx_fifo_empty ( ), //output - 1 + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( ), //output - 1 + .nack_seen ( ), //output - 1 + .tx_sop ( w_tx_sop ), + .tx_data_id ( w_tx_data_id ), + .tx_word_count ( w_tx_word_count ), + .tx_app_data ( w_tx_app_data ), + .tx_advance ( w_tx_advance ), + .rx_sop ( w_rx_sop ), + .rx_data_id ( w_rx_data_id ), + .rx_word_count ( w_rx_word_count ), + .rx_app_data ( w_rx_app_data ), + .rx_valid ( w_rx_valid ), + .rx_crc_corrupted ( w_rx_crc_corrupted )); + + + +//------------------------------------------ +// Write Response Channel +//------------------------------------------ +wire b_tx_sop; +wire [7:0] b_tx_data_id; +wire [15:0] b_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] b_tx_app_data; +wire b_tx_advance; + +wire b_rx_sop; +wire [7:0] b_rx_data_id; +wire [15:0] b_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] b_rx_app_data; +wire b_rx_valid; +wire b_rx_crc_corrupted; + +wire b_a2l_valid; +wire b_a2l_ready; +wire [B_CHANNEL_WIDTH-1:0] b_a2l_data; + +wire b_l2a_valid; +wire b_l2a_accept; +wire [B_CHANNEL_WIDTH-1:0] b_l2a_data; + +assign b_a2l_data = {ini_bresp, + ini_bid}; +assign ini_bready = b_a2l_ready; + +assign b_a2l_valid = ini_bvalid; + + +assign tgt_bvalid = b_l2a_valid; +assign tgt_bresp = b_l2a_data[9:8]; +assign tgt_bid = b_l2a_data[7:0]; + +assign b_l2a_accept = tgt_bready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( B_CHANNEL_WIDTH ), + .A2L_DEPTH ( ADDR_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( B_CHANNEL_WIDTH ), + .L2A_DEPTH ( ADDR_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_B_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_b_cr_id ), + .swi_crack_id ( swi_b_crack_id ), + .swi_ack_id ( swi_b_ack_id ), + .swi_nack_id ( swi_b_nack_id ), + .swi_data_id ( swi_b_data_id ), + .swi_word_count ( B_PKT_WC ), + .a2l_valid ( b_a2l_valid ), + .a2l_ready ( b_a2l_ready ), + .a2l_data ( b_a2l_data ), + .l2a_valid ( b_l2a_valid ), + .l2a_accept ( b_l2a_accept ), + .l2a_data ( b_l2a_data ), + .tx_fifo_empty ( ), //output - 1 + .rx_fifo_empty ( ), //output - 1 + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( ), //output - 1 + .nack_seen ( ), //output - 1 + .tx_sop ( b_tx_sop ), + .tx_data_id ( b_tx_data_id ), + .tx_word_count ( b_tx_word_count ), + .tx_app_data ( b_tx_app_data ), + .tx_advance ( b_tx_advance ), + .rx_sop ( b_rx_sop ), + .rx_data_id ( b_rx_data_id ), + .rx_word_count ( b_rx_word_count ), + .rx_app_data ( b_rx_app_data ), + .rx_valid ( b_rx_valid ), + .rx_crc_corrupted ( b_rx_crc_corrupted )); + + + + +//------------------------------------------ +// ADDR Read Channel +//------------------------------------------ +wire ar_tx_sop; +wire [7:0] ar_tx_data_id; +wire [15:0] ar_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] ar_tx_app_data; +wire ar_tx_advance; + +wire ar_rx_sop; +wire [7:0] ar_rx_data_id; +wire [15:0] ar_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] ar_rx_app_data; +wire ar_rx_valid; +wire ar_rx_crc_corrupted; + +wire ar_a2l_valid; +wire ar_a2l_ready; +wire [ADDR_CHANNEL_WIDTH-1:0] ar_a2l_data; + +wire ar_l2a_valid; +wire ar_l2a_accept; +wire [ADDR_CHANNEL_WIDTH-1:0] ar_l2a_data; + +assign ar_a2l_data = {tgt_araddr, + tgt_arregion, + tgt_arqos, + tgt_arprot, + tgt_arcache, + tgt_arlock, + tgt_arburst, + tgt_arsize, + tgt_arlen, + tgt_arid}; +assign tgt_arready = ar_a2l_ready; + +assign ar_a2l_valid = tgt_arvalid; + + +assign ini_arvalid = ar_l2a_valid; +assign ini_araddr = ar_l2a_data[38+AXI_ADDR_WIDTH-1:38]; +assign ini_arregion = ar_l2a_data[37:34]; +assign ini_arqos = ar_l2a_data[33:30]; +assign ini_arprot = ar_l2a_data[29:27]; +assign ini_arcache = ar_l2a_data[26:23]; +assign ini_arlock = ar_l2a_data[22:21]; +assign ini_arburst = ar_l2a_data[20:19]; +assign ini_arsize = ar_l2a_data[18:16]; +assign ini_arlen = ar_l2a_data[15: 8]; +assign ini_arid = ar_l2a_data[ 7: 0]; + +assign ar_l2a_accept= ini_arready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( ADDR_CHANNEL_WIDTH ), + .A2L_DEPTH ( ADDR_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( ADDR_CHANNEL_WIDTH ), + .L2A_DEPTH ( ADDR_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_AR_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_ar_cr_id ), + .swi_crack_id ( swi_ar_crack_id ), + .swi_ack_id ( swi_ar_ack_id ), + .swi_nack_id ( swi_ar_nack_id ), + .swi_data_id ( swi_ar_data_id ), + .swi_word_count ( AR_PKT_WC ), + .a2l_valid ( ar_a2l_valid ), + .a2l_ready ( ar_a2l_ready ), + .a2l_data ( ar_a2l_data ), + .l2a_valid ( ar_l2a_valid ), + .l2a_accept ( ar_l2a_accept ), + .l2a_data ( ar_l2a_data ), + .tx_fifo_empty ( ), //output - 1 + .rx_fifo_empty ( ), //output - 1 + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( ), //output - 1 + .nack_seen ( ), //output - 1 + .tx_sop ( ar_tx_sop ), + .tx_data_id ( ar_tx_data_id ), + .tx_word_count ( ar_tx_word_count ), + .tx_app_data ( ar_tx_app_data ), + .tx_advance ( ar_tx_advance ), + .rx_sop ( ar_rx_sop ), + .rx_data_id ( ar_rx_data_id ), + .rx_word_count ( ar_rx_word_count ), + .rx_app_data ( ar_rx_app_data ), + .rx_valid ( ar_rx_valid ), + .rx_crc_corrupted ( ar_rx_crc_corrupted )); + + + +//------------------------------------------ +// READ Data Channel +//------------------------------------------ +wire r_tx_sop; +wire [7:0] r_tx_data_id; +wire [15:0] r_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] r_tx_app_data; +wire r_tx_advance; + +wire r_rx_sop; +wire [7:0] r_rx_data_id; +wire [15:0] r_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] r_rx_app_data; +wire r_rx_valid; +wire r_rx_crc_corrupted; + +wire r_a2l_valid; +wire r_a2l_ready; +wire [RDATA_CHANNEL_WIDTH-1:0] r_a2l_data; + +wire r_l2a_valid; +wire r_l2a_accept; +wire [RDATA_CHANNEL_WIDTH-1:0] r_l2a_data; + + +assign r_a2l_data = {ini_rdata, + ini_rlast, + ini_rresp, + ini_rid}; +assign ini_rready = r_a2l_ready; + +assign r_a2l_valid = ini_rvalid; + +assign tgt_rvalid = r_l2a_valid; +assign tgt_rdata = r_l2a_data[RDATA_CHANNEL_WIDTH-1:10]; +assign tgt_rlast = r_l2a_data[10]; +assign tgt_rresp = r_l2a_data[ 9: 8]; +assign tgt_rid = r_l2a_data[ 7: 0]; + +assign r_l2a_accept = tgt_rready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( RDATA_CHANNEL_WIDTH ), + .A2L_DEPTH ( DATA_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( RDATA_CHANNEL_WIDTH ), + .L2A_DEPTH ( DATA_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_R_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_r_cr_id ), + .swi_crack_id ( swi_r_crack_id ), + .swi_ack_id ( swi_r_ack_id ), + .swi_nack_id ( swi_r_nack_id ), + .swi_data_id ( swi_r_data_id ), + .swi_word_count ( R_PKT_WC ), + .a2l_valid ( r_a2l_valid ), + .a2l_ready ( r_a2l_ready ), + .a2l_data ( r_a2l_data ), + .l2a_valid ( r_l2a_valid ), + .l2a_accept ( r_l2a_accept ), + .l2a_data ( r_l2a_data ), + .tx_fifo_empty ( ), //output - 1 + .rx_fifo_empty ( ), //output - 1 + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( ), //output - 1 + .nack_seen ( ), //output - 1 + .tx_sop ( r_tx_sop ), + .tx_data_id ( r_tx_data_id ), + .tx_word_count ( r_tx_word_count ), + .tx_app_data ( r_tx_app_data ), + .tx_advance ( r_tx_advance ), + .rx_sop ( r_rx_sop ), + .rx_data_id ( r_rx_data_id ), + .rx_word_count ( r_rx_word_count ), + .rx_app_data ( r_rx_app_data ), + .rx_valid ( r_rx_valid ), + .rx_crc_corrupted ( r_rx_crc_corrupted )); + + + +endmodule diff --git a/rtl/app/amba/slink_axi_top.v b/rtl/app/amba/slink_axi_top.v new file mode 100644 index 0000000..834878c --- /dev/null +++ b/rtl/app/amba/slink_axi_top.v @@ -0,0 +1,755 @@ +module slink_axi_top #( + parameter AXI_ADDR_WIDTH = 32, //8/16/24/32/40/48/56/64 (I hope to be retired by the time we need 128) + parameter AXI_DATA_WIDTH = 64, //32/64/128/256/512/1024 + parameter DATA_CH_APP_DEPTH = 16, + parameter ADDR_CH_APP_DEPTH = 4, + + parameter TX_APP_DATA_WIDTH = 32, + parameter RX_APP_DATA_WIDTH = 32 +)( + input wire axi_clk, + input wire axi_reset, + + //-------------------------------------- + // AXI Target + //-------------------------------------- + input wire [7:0] tgt_awid, + input wire [AXI_ADDR_WIDTH-1:0] tgt_awaddr, + input wire [7:0] tgt_awlen, + input wire [2:0] tgt_awsize, + input wire [1:0] tgt_awburst, + input wire [1:0] tgt_awlock, + input wire [3:0] tgt_awcache, + input wire [2:0] tgt_awprot, + input wire [3:0] tgt_awqos, + input wire [3:0] tgt_awregion, + input wire tgt_awvalid, + output wire tgt_awready, + + input wire [7:0] tgt_wid, + input wire [AXI_DATA_WIDTH-1:0] tgt_wdata, + input wire [(AXI_DATA_WIDTH/8)-1:0] tgt_wstrb, + input wire tgt_wlast, + input wire tgt_wvalid, + output wire tgt_wready, + + output wire [7:0] tgt_bid, + output wire [1:0] tgt_bresp, + output wire tgt_bvalid, + input wire tgt_bready, + + input wire [7:0] tgt_arid, + input wire [AXI_ADDR_WIDTH-1:0] tgt_araddr, + input wire [7:0] tgt_arlen, + input wire [2:0] tgt_arsize, + input wire [1:0] tgt_arburst, + input wire [1:0] tgt_arlock, + input wire [3:0] tgt_arcache, + input wire [2:0] tgt_arprot, + input wire [3:0] tgt_arqos, + input wire [3:0] tgt_arregion, + input wire tgt_arvalid, + output wire tgt_arready, + + output wire [7:0] tgt_rid, + output wire [AXI_DATA_WIDTH-1:0] tgt_rdata, + output wire [1:0] tgt_rresp, + output wire tgt_rlast, + output wire tgt_rvalid, + input wire tgt_rready, + + //-------------------------------------- + // AXI Initiator + //-------------------------------------- + output wire [7:0] ini_awid, + output wire [AXI_ADDR_WIDTH-1:0] ini_awaddr, + output wire [7:0] ini_awlen, + output wire [2:0] ini_awsize, + output wire [1:0] ini_awburst, + output wire [1:0] ini_awlock, + output wire [3:0] ini_awcache, + output wire [2:0] ini_awprot, + output wire [3:0] ini_awqos, + output wire [3:0] ini_awregion, + output wire ini_awvalid, + input wire ini_awready, + + output wire [7:0] ini_wid, + output wire [AXI_DATA_WIDTH-1:0] ini_wdata, + output wire [(AXI_DATA_WIDTH/8)-1:0] ini_wstrb, + output wire ini_wlast, + output wire ini_wvalid, + input wire ini_wready, + + input wire [7:0] ini_bid, + input wire [1:0] ini_bresp, + input wire ini_bvalid, + output wire ini_bready, + + output wire [7:0] ini_arid, + output wire [AXI_ADDR_WIDTH-1:0] ini_araddr, + output wire [7:0] ini_arlen, + output wire [2:0] ini_arsize, + output wire [1:0] ini_arburst, + output wire [1:0] ini_arlock, + output wire [3:0] ini_arcache, + output wire [2:0] ini_arprot, + output wire [3:0] ini_arqos, + output wire [3:0] ini_arregion, + output wire ini_arvalid, + input wire ini_arready, + + input wire [7:0] ini_rid, + input wire [AXI_DATA_WIDTH-1:0] ini_rdata, + input wire [1:0] ini_rresp, + input wire ini_rlast, + input wire ini_rvalid, + output wire ini_rready, + + + //-------------------------------------- + // Controls / Status + //-------------------------------------- + input wire enable, + + input wire [7:0] swi_aw_cr_id, + input wire [7:0] swi_aw_crack_id, + input wire [7:0] swi_aw_ack_id, + input wire [7:0] swi_aw_nack_id, + input wire [7:0] swi_aw_data_id, + + input wire [7:0] swi_w_cr_id, + input wire [7:0] swi_w_crack_id, + input wire [7:0] swi_w_ack_id, + input wire [7:0] swi_w_nack_id, + input wire [7:0] swi_w_data_id, + + input wire [7:0] swi_b_cr_id, + input wire [7:0] swi_b_crack_id, + input wire [7:0] swi_b_ack_id, + input wire [7:0] swi_b_nack_id, + input wire [7:0] swi_b_data_id, + + input wire [7:0] swi_ar_cr_id, + input wire [7:0] swi_ar_crack_id, + input wire [7:0] swi_ar_ack_id, + input wire [7:0] swi_ar_nack_id, + input wire [7:0] swi_ar_data_id, + + input wire [7:0] swi_r_cr_id, + input wire [7:0] swi_r_crack_id, + input wire [7:0] swi_r_ack_id, + input wire [7:0] swi_r_nack_id, + input wire [7:0] swi_r_data_id, + + output wire [4:0] nack_sent, + output wire [4:0] nack_seen, + output wire [4:0] tx_fifo_empty, + output wire [4:0] rx_fifo_empty, + + //-------------------------------------- + // Link Layer + //-------------------------------------- + input wire link_clk, + input wire link_reset, + + output wire tx_sop, + output wire [7:0] tx_data_id, + output wire [15:0] tx_word_count, + output wire [TX_APP_DATA_WIDTH-1:0] tx_app_data, + input wire tx_advance, + + input wire rx_sop, + input wire [7:0] rx_data_id, + input wire [15:0] rx_word_count, + input wire [RX_APP_DATA_WIDTH-1:0] rx_app_data, + input wire rx_valid, + input wire rx_crc_corrupted + + +); + + + +localparam WDATA_CHANNEL_WIDTH = 1 + 8 + AXI_DATA_WIDTH + (AXI_DATA_WIDTH/8); //W channel is always larger than R/B due to WSTRB's +localparam RDATA_CHANNEL_WIDTH = 1 + 8 + AXI_DATA_WIDTH + 2; +localparam ADDR_CHANNEL_WIDTH = 38 + AXI_ADDR_WIDTH; //AW/AR are same size +localparam B_CHANNEL_WIDTH = 10; + +localparam [15:0] AW_PKT_WC = 5 + (AXI_ADDR_WIDTH/8); +localparam [15:0] WSTRB_WC = AXI_DATA_WIDTH == 8 ? 1 : + AXI_DATA_WIDTH == 16 ? 1 : + AXI_DATA_WIDTH == 32 ? 1 : + AXI_DATA_WIDTH == 64 ? 1 : + AXI_DATA_WIDTH == 128 ? 2 : + AXI_DATA_WIDTH == 256 ? 4 : + AXI_DATA_WIDTH == 512 ? 8 : 16; +localparam [15:0] W_PKT_WC = 2 + (AXI_DATA_WIDTH/8) + WSTRB_WC; +localparam [15:0] B_PKT_WC = 2; +localparam [15:0] AR_PKT_WC = 5 + (AXI_ADDR_WIDTH/8); +localparam [15:0] R_PKT_WC = 2 + (AXI_DATA_WIDTH/8); + + + + +//------------------------------------------ +// ADDR Write Channel +//------------------------------------------ +wire aw_tx_sop; +wire [7:0] aw_tx_data_id; +wire [15:0] aw_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] aw_tx_app_data; +wire aw_tx_advance; + +wire aw_rx_sop; +wire [7:0] aw_rx_data_id; +wire [15:0] aw_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] aw_rx_app_data; +wire aw_rx_valid; +wire aw_rx_crc_corrupted; + +wire aw_a2l_valid; +wire aw_a2l_ready; +wire [ADDR_CHANNEL_WIDTH-1:0] aw_a2l_data; + +wire aw_l2a_valid; +wire aw_l2a_accept; +wire [ADDR_CHANNEL_WIDTH-1:0] aw_l2a_data; + +assign aw_a2l_data = {tgt_awaddr, + tgt_awregion, + tgt_awqos, + tgt_awprot, + tgt_awcache, + tgt_awlock, + tgt_awburst, + tgt_awsize, + tgt_awlen, + tgt_awid}; +assign tgt_awready = aw_a2l_ready; + +assign aw_a2l_valid = tgt_awvalid; + + +assign ini_awvalid = aw_l2a_valid; +assign ini_awaddr = aw_l2a_data[38+AXI_ADDR_WIDTH-1:38]; +assign ini_awregion = aw_l2a_data[37:34]; +assign ini_awqos = aw_l2a_data[33:30]; +assign ini_awprot = aw_l2a_data[29:27]; +assign ini_awcache = aw_l2a_data[26:23]; +assign ini_awlock = aw_l2a_data[22:21]; +assign ini_awburst = aw_l2a_data[20:19]; +assign ini_awsize = aw_l2a_data[18:16]; +assign ini_awlen = aw_l2a_data[15: 8]; +assign ini_awid = aw_l2a_data[ 7: 0]; + +assign aw_l2a_accept= ini_awready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( ADDR_CHANNEL_WIDTH ), + .A2L_DEPTH ( ADDR_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( ADDR_CHANNEL_WIDTH ), + .L2A_DEPTH ( ADDR_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_AW_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_aw_cr_id ), + .swi_crack_id ( swi_aw_crack_id ), + .swi_ack_id ( swi_aw_ack_id ), + .swi_nack_id ( swi_aw_nack_id ), + .swi_data_id ( swi_aw_data_id ), + .swi_word_count ( AW_PKT_WC ), + .a2l_valid ( aw_a2l_valid ), + .a2l_ready ( aw_a2l_ready ), + .a2l_data ( aw_a2l_data ), + .l2a_valid ( aw_l2a_valid ), + .l2a_accept ( aw_l2a_accept ), + .l2a_data ( aw_l2a_data ), + .tx_fifo_empty ( tx_fifo_empty[0] ), + .rx_fifo_empty ( rx_fifo_empty[0] ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( nack_sent[0] ), + .nack_seen ( nack_seen[0] ), + .tx_sop ( aw_tx_sop ), + .tx_data_id ( aw_tx_data_id ), + .tx_word_count ( aw_tx_word_count ), + .tx_app_data ( aw_tx_app_data ), + .tx_advance ( aw_tx_advance ), + .rx_sop ( aw_rx_sop ), + .rx_data_id ( aw_rx_data_id ), + .rx_word_count ( aw_rx_word_count ), + .rx_app_data ( aw_rx_app_data ), + .rx_valid ( aw_rx_valid ), + .rx_crc_corrupted ( aw_rx_crc_corrupted )); + + + +//------------------------------------------ +// Write Data Channel +//------------------------------------------ +wire w_tx_sop; +wire [7:0] w_tx_data_id; +wire [15:0] w_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] w_tx_app_data; +wire w_tx_advance; + +wire w_rx_sop; +wire [7:0] w_rx_data_id; +wire [15:0] w_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] w_rx_app_data; +wire w_rx_valid; +wire w_rx_crc_corrupted; + +wire w_a2l_valid; +wire w_a2l_ready; +wire [WDATA_CHANNEL_WIDTH-1:0] w_a2l_data; + +wire w_l2a_valid; +wire w_l2a_accept; +wire [WDATA_CHANNEL_WIDTH-1:0] w_l2a_data; + +assign w_a2l_data = {tgt_wdata, + tgt_wstrb, + tgt_wlast, + tgt_wid}; +assign tgt_wready = w_a2l_ready; + +assign w_a2l_valid = tgt_wvalid; + +assign ini_wvalid = w_l2a_valid; +//assign ini_wdata = w_l2a_data[9+(AXI_DATA_WIDTH/8)+1+AXI_DATA_WIDTH-1 : 9+(AXI_DATA_WIDTH/8)]; +assign ini_wdata = w_l2a_data[80 : 17]; +assign ini_wstrb = w_l2a_data[9+(AXI_DATA_WIDTH/8)-1:9]; +assign ini_wlast = w_l2a_data[8]; +assign ini_wid = w_l2a_data[7:0]; + +assign w_l2a_accept = ini_wready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( WDATA_CHANNEL_WIDTH ), + .A2L_DEPTH ( DATA_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( WDATA_CHANNEL_WIDTH ), + .L2A_DEPTH ( DATA_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_W_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_w_cr_id ), + .swi_crack_id ( swi_w_crack_id ), + .swi_ack_id ( swi_w_ack_id ), + .swi_nack_id ( swi_w_nack_id ), + .swi_data_id ( swi_w_data_id ), + .swi_word_count ( W_PKT_WC ), + .a2l_valid ( w_a2l_valid ), + .a2l_ready ( w_a2l_ready ), + .a2l_data ( w_a2l_data ), + .l2a_valid ( w_l2a_valid ), + .l2a_accept ( w_l2a_accept ), + .l2a_data ( w_l2a_data ), + .tx_fifo_empty ( tx_fifo_empty[1] ), + .rx_fifo_empty ( rx_fifo_empty[1] ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( nack_sent[1] ), + .nack_seen ( nack_seen[1] ), + .tx_sop ( w_tx_sop ), + .tx_data_id ( w_tx_data_id ), + .tx_word_count ( w_tx_word_count ), + .tx_app_data ( w_tx_app_data ), + .tx_advance ( w_tx_advance ), + .rx_sop ( w_rx_sop ), + .rx_data_id ( w_rx_data_id ), + .rx_word_count ( w_rx_word_count ), + .rx_app_data ( w_rx_app_data ), + .rx_valid ( w_rx_valid ), + .rx_crc_corrupted ( w_rx_crc_corrupted )); + + + +//------------------------------------------ +// Write Response Channel +//------------------------------------------ +wire b_tx_sop; +wire [7:0] b_tx_data_id; +wire [15:0] b_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] b_tx_app_data; +wire b_tx_advance; + +wire b_rx_sop; +wire [7:0] b_rx_data_id; +wire [15:0] b_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] b_rx_app_data; +wire b_rx_valid; +wire b_rx_crc_corrupted; + +wire b_a2l_valid; +wire b_a2l_ready; +wire [B_CHANNEL_WIDTH-1:0] b_a2l_data; + +wire b_l2a_valid; +wire b_l2a_accept; +wire [B_CHANNEL_WIDTH-1:0] b_l2a_data; + +assign b_a2l_data = {ini_bresp, + ini_bid}; +assign ini_bready = b_a2l_ready; + +assign b_a2l_valid = ini_bvalid; + + +assign tgt_bvalid = b_l2a_valid; +assign tgt_bresp = b_l2a_data[9:8]; +assign tgt_bid = b_l2a_data[7:0]; + +assign b_l2a_accept = tgt_bready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( B_CHANNEL_WIDTH ), + .A2L_DEPTH ( ADDR_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( B_CHANNEL_WIDTH ), + .L2A_DEPTH ( ADDR_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_B_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_b_cr_id ), + .swi_crack_id ( swi_b_crack_id ), + .swi_ack_id ( swi_b_ack_id ), + .swi_nack_id ( swi_b_nack_id ), + .swi_data_id ( swi_b_data_id ), + .swi_word_count ( B_PKT_WC ), + .a2l_valid ( b_a2l_valid ), + .a2l_ready ( b_a2l_ready ), + .a2l_data ( b_a2l_data ), + .l2a_valid ( b_l2a_valid ), + .l2a_accept ( b_l2a_accept ), + .l2a_data ( b_l2a_data ), + .tx_fifo_empty ( tx_fifo_empty[2] ), + .rx_fifo_empty ( rx_fifo_empty[2] ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( nack_sent[2] ), + .nack_seen ( nack_seen[2] ), + .tx_sop ( b_tx_sop ), + .tx_data_id ( b_tx_data_id ), + .tx_word_count ( b_tx_word_count ), + .tx_app_data ( b_tx_app_data ), + .tx_advance ( b_tx_advance ), + .rx_sop ( b_rx_sop ), + .rx_data_id ( b_rx_data_id ), + .rx_word_count ( b_rx_word_count ), + .rx_app_data ( b_rx_app_data ), + .rx_valid ( b_rx_valid ), + .rx_crc_corrupted ( b_rx_crc_corrupted )); + + + + +//------------------------------------------ +// ADDR Read Channel +//------------------------------------------ +wire ar_tx_sop; +wire [7:0] ar_tx_data_id; +wire [15:0] ar_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] ar_tx_app_data; +wire ar_tx_advance; + +wire ar_rx_sop; +wire [7:0] ar_rx_data_id; +wire [15:0] ar_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] ar_rx_app_data; +wire ar_rx_valid; +wire ar_rx_crc_corrupted; + +wire ar_a2l_valid; +wire ar_a2l_ready; +wire [ADDR_CHANNEL_WIDTH-1:0] ar_a2l_data; + +wire ar_l2a_valid; +wire ar_l2a_accept; +wire [ADDR_CHANNEL_WIDTH-1:0] ar_l2a_data; + +assign ar_a2l_data = {tgt_araddr, + tgt_arregion, + tgt_arqos, + tgt_arprot, + tgt_arcache, + tgt_arlock, + tgt_arburst, + tgt_arsize, + tgt_arlen, + tgt_arid}; +assign tgt_arready = ar_a2l_ready; + +assign ar_a2l_valid = tgt_arvalid; + + +assign ini_arvalid = ar_l2a_valid; +assign ini_araddr = ar_l2a_data[38+AXI_ADDR_WIDTH-1:38]; +assign ini_arregion = ar_l2a_data[37:34]; +assign ini_arqos = ar_l2a_data[33:30]; +assign ini_arprot = ar_l2a_data[29:27]; +assign ini_arcache = ar_l2a_data[26:23]; +assign ini_arlock = ar_l2a_data[22:21]; +assign ini_arburst = ar_l2a_data[20:19]; +assign ini_arsize = ar_l2a_data[18:16]; +assign ini_arlen = ar_l2a_data[15: 8]; +assign ini_arid = ar_l2a_data[ 7: 0]; + +assign ar_l2a_accept= ini_arready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( ADDR_CHANNEL_WIDTH ), + .A2L_DEPTH ( ADDR_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( ADDR_CHANNEL_WIDTH ), + .L2A_DEPTH ( ADDR_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_AR_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_ar_cr_id ), + .swi_crack_id ( swi_ar_crack_id ), + .swi_ack_id ( swi_ar_ack_id ), + .swi_nack_id ( swi_ar_nack_id ), + .swi_data_id ( swi_ar_data_id ), + .swi_word_count ( AR_PKT_WC ), + .a2l_valid ( ar_a2l_valid ), + .a2l_ready ( ar_a2l_ready ), + .a2l_data ( ar_a2l_data ), + .l2a_valid ( ar_l2a_valid ), + .l2a_accept ( ar_l2a_accept ), + .l2a_data ( ar_l2a_data ), + .tx_fifo_empty ( tx_fifo_empty[3] ), + .rx_fifo_empty ( rx_fifo_empty[3] ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( nack_sent[3] ), + .nack_seen ( nack_seen[3] ), + .tx_sop ( ar_tx_sop ), + .tx_data_id ( ar_tx_data_id ), + .tx_word_count ( ar_tx_word_count ), + .tx_app_data ( ar_tx_app_data ), + .tx_advance ( ar_tx_advance ), + .rx_sop ( ar_rx_sop ), + .rx_data_id ( ar_rx_data_id ), + .rx_word_count ( ar_rx_word_count ), + .rx_app_data ( ar_rx_app_data ), + .rx_valid ( ar_rx_valid ), + .rx_crc_corrupted ( ar_rx_crc_corrupted )); + + + +//------------------------------------------ +// READ Data Channel +//------------------------------------------ +wire r_tx_sop; +wire [7:0] r_tx_data_id; +wire [15:0] r_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] r_tx_app_data; +wire r_tx_advance; + +wire r_rx_sop; +wire [7:0] r_rx_data_id; +wire [15:0] r_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] r_rx_app_data; +wire r_rx_valid; +wire r_rx_crc_corrupted; + +wire r_a2l_valid; +wire r_a2l_ready; +wire [RDATA_CHANNEL_WIDTH-1:0] r_a2l_data; + +wire r_l2a_valid; +wire r_l2a_accept; +wire [RDATA_CHANNEL_WIDTH-1:0] r_l2a_data; + + +assign r_a2l_data = {ini_rdata, + ini_rlast, + ini_rresp, + ini_rid}; +assign ini_rready = r_a2l_ready; + +assign r_a2l_valid = ini_rvalid; + +assign tgt_rvalid = r_l2a_valid; +assign tgt_rdata = r_l2a_data[RDATA_CHANNEL_WIDTH-1:11]; +assign tgt_rlast = r_l2a_data[10]; +assign tgt_rresp = r_l2a_data[ 9: 8]; +assign tgt_rid = r_l2a_data[ 7: 0]; + +assign r_l2a_accept = tgt_rready; + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( RDATA_CHANNEL_WIDTH ), + .A2L_DEPTH ( DATA_CH_APP_DEPTH ), + .L2A_DATA_WIDTH ( RDATA_CHANNEL_WIDTH ), + .L2A_DEPTH ( DATA_CH_APP_DEPTH ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm_R_CHANNEL ( + .app_clk ( axi_clk ), + .app_reset ( axi_reset ), + .enable ( enable ), + .swi_cr_id ( swi_r_cr_id ), + .swi_crack_id ( swi_r_crack_id ), + .swi_ack_id ( swi_r_ack_id ), + .swi_nack_id ( swi_r_nack_id ), + .swi_data_id ( swi_r_data_id ), + .swi_word_count ( R_PKT_WC ), + .a2l_valid ( r_a2l_valid ), + .a2l_ready ( r_a2l_ready ), + .a2l_data ( r_a2l_data ), + .l2a_valid ( r_l2a_valid ), + .l2a_accept ( r_l2a_accept ), + .l2a_data ( r_l2a_data ), + .tx_fifo_empty ( tx_fifo_empty[4] ), + .rx_fifo_empty ( rx_fifo_empty[4] ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( nack_sent[4] ), + .nack_seen ( nack_seen[4] ), + .tx_sop ( r_tx_sop ), + .tx_data_id ( r_tx_data_id ), + .tx_word_count ( r_tx_word_count ), + .tx_app_data ( r_tx_app_data ), + .tx_advance ( r_tx_advance ), + .rx_sop ( r_rx_sop ), + .rx_data_id ( r_rx_data_id ), + .rx_word_count ( r_rx_word_count ), + .rx_app_data ( r_rx_app_data ), + .rx_valid ( r_rx_valid ), + .rx_crc_corrupted ( r_rx_crc_corrupted )); + + + + + +//------------------------------------------ +// Routing +//------------------------------------------ +slink_generic_tx_router #( + //parameters + .NUM_CHANNELS ( 5 ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ) +) u_slink_generic_tx_router ( + .clk ( link_clk ), + .reset ( link_reset ), + .enable ( enable ), + .tx_sop_ch ( {r_tx_sop, + ar_tx_sop, + b_tx_sop, + w_tx_sop, + aw_tx_sop} ), + .tx_data_id_ch ( {r_tx_data_id, + ar_tx_data_id, + b_tx_data_id, + w_tx_data_id, + aw_tx_data_id} ), + .tx_word_count_ch ( {r_tx_word_count, + ar_tx_word_count, + b_tx_word_count, + w_tx_word_count, + aw_tx_word_count} ), + .tx_app_data_ch ( {r_tx_app_data, + ar_tx_app_data, + b_tx_app_data, + w_tx_app_data, + aw_tx_app_data} ), + .tx_advance_ch ( {r_tx_advance, + ar_tx_advance, + b_tx_advance, + w_tx_advance, + aw_tx_advance} ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance )); + +//I need to fix this +slink_generic_rx_router #( + //parameters + .NUM_CHANNELS ( 5 ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ) +) u_slink_generic_rx_router ( + .clk ( link_clk ), + .reset ( link_reset ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted ), + .swi_ch_sp_min ( {swi_r_cr_id, + swi_ar_cr_id, + swi_b_cr_id, + swi_w_cr_id, + swi_aw_cr_id} ), //input - [(NUM_CHANNELS*8)-1:0] + .swi_ch_sp_max ( {swi_r_nack_id, + swi_ar_nack_id, + swi_b_nack_id, + swi_w_nack_id, + swi_aw_nack_id} ), //input - [(NUM_CHANNELS*8)-1:0] + .swi_ch_lp_min ( {swi_r_data_id, + swi_ar_data_id, + swi_b_data_id, + swi_w_data_id, + swi_aw_data_id} ), //input - [(NUM_CHANNELS*8)-1:0] + .swi_ch_lp_max ( {swi_r_data_id, + swi_ar_data_id, + swi_b_data_id, + swi_w_data_id, + swi_aw_data_id} ), //input - [(NUM_CHANNELS*8)-1:0] + .rx_sop_ch ( {r_rx_sop, + ar_rx_sop, + b_rx_sop, + w_rx_sop, + aw_rx_sop} ), + .rx_data_id_ch ( {r_rx_data_id, + ar_rx_data_id, + b_rx_data_id, + w_rx_data_id, + aw_rx_data_id} ), + .rx_word_count_ch ( {r_rx_word_count, + ar_rx_word_count, + b_rx_word_count, + w_rx_word_count, + aw_rx_word_count} ), + .rx_app_data_ch ( {r_rx_app_data, + ar_rx_app_data, + b_rx_app_data, + w_rx_app_data, + aw_rx_app_data} ), + .rx_valid_ch ( {r_rx_valid, + ar_rx_valid, + b_rx_valid, + w_rx_valid, + aw_rx_valid} ), + .rx_crc_corrupted_ch ( {r_rx_crc_corrupted, + ar_rx_crc_corrupted, + b_rx_crc_corrupted, + w_rx_crc_corrupted, + aw_rx_crc_corrupted})); + +endmodule diff --git a/rtl/app/int_gpio/slink_int_gpio_top.v b/rtl/app/int_gpio/slink_int_gpio_top.v new file mode 100644 index 0000000..b3f58c2 --- /dev/null +++ b/rtl/app/int_gpio/slink_int_gpio_top.v @@ -0,0 +1,174 @@ +module slink_int_gpio_top #( + parameter TX_APP_DATA_WIDTH = 128, + parameter RX_APP_DATA_WIDTH = 128, + + //Look, to keep this simple, just make this a factor of 8 please + //I mean really, I'm giving you all these components. Now, would you kindly + //just keep it a factor of 8? + parameter NUM_INTS = 16, + parameter NUM_GPIOS = 8 +)( + input wire app_clk, + input wire app_reset, + + //------------------------------- + // Configs + //------------------------------- + input wire enable, + + input wire [7:0] swi_cr_id, + input wire [7:0] swi_crack_id, + input wire [7:0] swi_ack_id, + input wire [7:0] swi_nack_id, + input wire [7:0] swi_data_id, + input wire [15:0] swi_word_count, + + output wire nack_sent, + output wire nack_seen, + + + //------------------------------- + // Interrupts / GPIOs + //------------------------------- + input wire [NUM_INTS-1:0] i_interrupt, + output wire [NUM_INTS-1:0] o_interrupt, + input wire [NUM_GPIOS-1:0] i_gpio, + output wire [NUM_GPIOS-1:0] o_gpio, + + //------------------------------- + // Link Layer + //------------------------------- + input wire link_clk, + input wire link_reset, + + output wire tx_sop, + output wire [7:0] tx_data_id, + output wire [15:0] tx_word_count, + output wire [TX_APP_DATA_WIDTH-1:0] tx_app_data, + input wire tx_advance, + + input wire rx_sop, + input wire [7:0] rx_data_id, + input wire [15:0] rx_word_count, + input wire [RX_APP_DATA_WIDTH-1:0] rx_app_data, + input wire rx_valid, + input wire rx_crc_corrupted +); + + +localparam A2L_DATA_WIDTH = NUM_INTS+NUM_GPIOS; +localparam L2A_DATA_WIDTH = NUM_INTS+NUM_GPIOS; + +wire [A2L_DATA_WIDTH-1:0] a2l_data; +reg a2l_valid; +wire a2l_valid_in; +wire a2l_ready; + +wire [L2A_DATA_WIDTH-1:0] l2a_data; +reg [L2A_DATA_WIDTH-1:0] l2a_data_reg; +wire l2a_valid; +wire l2a_ready; + + +wire enable_app_clk; + +wire [NUM_INTS+NUM_GPIOS-1:0] ig_ff2; +reg [NUM_INTS+NUM_GPIOS-1:0] ig_ff3; +wire [NUM_INTS+NUM_GPIOS-1:0] ig_diff; +wire diff_seen; + +slink_demet_reset u_slink_demet_reset_enable ( + .clk ( app_clk ), + .reset ( app_reset ), + .sig_in ( enable ), + .sig_out ( enable_app_clk )); + +//------------------------ +// Input side +//------------------------ +slink_demet_reset u_slink_demet_reset_ints_gpios[NUM_INTS+NUM_GPIOS-1:0] ( + .clk ( app_clk ), + .reset ( app_reset ), + .sig_in ( {i_gpio, + i_interrupt} ), + .sig_out ( ig_ff2 )); + +always @(posedge app_clk or posedge app_reset) begin + if(app_reset) begin + ig_ff3 <= {NUM_INTS+NUM_GPIOS{1'b0}}; + a2l_valid <= 1'b1; //Force a send on the first one + end else begin + ig_ff3 <= ig_ff2; + a2l_valid <= a2l_valid_in; + end +end + +assign ig_diff = ig_ff2 ^ ig_ff3; +assign diff_seen = |ig_diff; + +//diff_seen check should protect against missing a transition +//when we also see the acceptance in the link layer +assign a2l_valid_in = a2l_ready && ~diff_seen ? 1'b0 : (diff_seen ? 1'b1 : a2l_valid); +assign a2l_data = ig_ff2; + +//------------------------ +// Output Side +//------------------------ +always @(posedge app_clk or posedge app_reset) begin + if(app_reset) begin + l2a_data_reg <= {L2A_DATA_WIDTH{1'b0}}; + end else begin + l2a_data_reg <= l2a_valid ? l2a_data : l2a_data_reg; + end +end + +assign l2a_accept = enable_app_clk; + +assign {o_gpio, o_interrupt} = l2a_data_reg; + + +slink_generic_fc_sm #( + //parameters + .A2L_DATA_WIDTH ( A2L_DATA_WIDTH ), + .A2L_DEPTH ( 2 ), + .L2A_DATA_WIDTH ( L2A_DATA_WIDTH ), + .L2A_DEPTH ( 2 ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ), + .USE_HARDCODED_DTWC ( 1 ) +) u_slink_generic_fc_sm ( + .app_clk ( app_clk ), + .app_reset ( app_reset ), + .enable ( enable_app_clk ), + .swi_cr_id ( swi_cr_id ), + .swi_crack_id ( swi_crack_id ), + .swi_ack_id ( swi_ack_id ), + .swi_nack_id ( swi_nack_id ), + .swi_data_id ( swi_data_id ), + .swi_word_count ( swi_word_count ), + .a2l_valid ( a2l_valid ), + .a2l_ready ( a2l_ready ), + .a2l_data ( a2l_data ), + .l2a_valid ( l2a_valid ), + .l2a_accept ( l2a_accept ), + .l2a_data ( l2a_data ), + .tx_fifo_empty ( tx_fifo_empty ), + .rx_fifo_empty ( rx_fifo_empty ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .nack_sent ( nack_sent ), + .nack_seen ( nack_seen ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted )); + + +endmodule diff --git a/rtl/app/slink_generic_fc_replay.v b/rtl/app/slink_generic_fc_replay.v new file mode 100644 index 0000000..e8401f9 --- /dev/null +++ b/rtl/app/slink_generic_fc_replay.v @@ -0,0 +1,228 @@ +module slink_generic_fc_replay #( + // Application Side + parameter A2L_DATA_WIDTH = 32, + parameter A2L_DEPTH = 8, //up to 128 + parameter A2L_ADDR_WDITH = $clog2(A2L_DEPTH) +)( + input wire app_clk, + input wire app_reset, + + input wire link_clk, + input wire link_reset, + + input wire enable, + + //-------------------------- + // Application Side + //-------------------------- + input wire a2l_valid, + output wire a2l_ready, + input wire [A2L_DATA_WIDTH-1:0] a2l_data, + + output wire empty, + + //-------------------------- + // Link Side + //-------------------------- + input wire link_ack_update, + input wire [A2L_ADDR_WDITH:0] link_ack_addr, + + input wire link_revert, + input wire [A2L_ADDR_WDITH:0] link_revert_addr, + + output wire [A2L_ADDR_WDITH:0] link_cur_addr, + output wire [A2L_DATA_WIDTH-1:0] link_data, + output wire link_valid, + input wire link_advance + + + +); + +wire enable_app_clk; +reg [A2L_ADDR_WDITH:0] a2l_app_addr; +wire [A2L_ADDR_WDITH:0] a2l_app_addr_in; +wire a2l_write; + +wire [A2L_ADDR_WDITH:0] a2l_link_addr_app_clk; +wire a2l_link_addr_app_clk_ready; +wire a2l_full; + +wire [A2L_ADDR_WDITH:0] a2l_app_addr_link_clk; +wire a2l_app_addr_link_clk_ready; + + + +wire enable_link_clk; +reg [A2L_ADDR_WDITH:0] a2l_link_addr; +wire [A2L_ADDR_WDITH:0] a2l_link_addr_in; +wire a2l_read; +wire a2l_empty; +reg [A2L_ADDR_WDITH:0] a2l_link_addr_real; +wire [A2L_ADDR_WDITH:0] a2l_link_addr_real_in; + + +//--------------------------- +// App Side A2L +//--------------------------- + +slink_demet_reset u_slink_demet_reset_enable_app_clk ( + .clk ( app_clk ), + .reset ( app_reset ), + .sig_in ( enable ), + .sig_out ( enable_app_clk )); + +always @(posedge app_clk or posedge app_reset) begin + if(app_reset) begin + a2l_app_addr <= {A2L_ADDR_WDITH+1{1'b0}}; + end else begin + a2l_app_addr <= a2l_app_addr_in; + end +end + + + + +assign a2l_full = (a2l_app_addr[A2L_ADDR_WDITH] != a2l_link_addr_app_clk[A2L_ADDR_WDITH]) && + (a2l_app_addr[A2L_ADDR_WDITH-1:0] == a2l_link_addr_app_clk[A2L_ADDR_WDITH-1:0]); +assign a2l_ready = ~a2l_full && enable_app_clk; +assign a2l_write = a2l_ready && a2l_valid; +assign a2l_app_addr_in = enable_app_clk ? (a2l_write ? a2l_app_addr + 'd1 : a2l_app_addr) : {A2L_ADDR_WDITH+1{1'b0}}; + + +//------------------------------- +// Moving the addr pointers between the clock domains +//------------------------------- + +slink_fc_replay_addr_sync #( + //parameters + .ADDR_WIDTH ( A2L_ADDR_WDITH+1 ) +) u_slink_fc_replay_addr_sync_app_addr_to_link_clk ( + .wclk ( app_clk ), + .wreset ( app_reset ), + .waddr ( a2l_app_addr ), + .rclk ( link_clk ), + .rreset ( link_reset ), + .raddr ( a2l_app_addr_link_clk )); + + +slink_fc_replay_addr_sync #( + //parameters + .ADDR_WIDTH ( A2L_ADDR_WDITH+1 ) +) u_slink_fc_replay_addr_sync_link_addr_to_app_clk ( + .wclk ( link_clk ), + .wreset ( link_reset ), + .waddr ( a2l_link_addr ), + .rclk ( app_clk ), + .rreset ( app_reset ), + .raddr ( a2l_link_addr_app_clk )); + + +//--------------------------- +// Link Side A2L +//--------------------------- + +slink_demet_reset u_slink_demet_reset_enable_link_clk ( + .clk ( link_clk ), + .reset ( link_reset ), + .sig_in ( enable ), + .sig_out ( enable_link_clk)); + +always @(posedge link_clk or posedge link_reset) begin + if(link_reset) begin + a2l_link_addr_real <= {A2L_ADDR_WDITH+1{1'b0}}; + a2l_link_addr <= {A2L_ADDR_WDITH+1{1'b0}}; + end else begin + a2l_link_addr_real <= a2l_link_addr_real_in; + a2l_link_addr <= a2l_link_addr_in; + end +end + + +//This is on the link_clk_domain +assign a2l_empty = (a2l_link_addr_real[A2L_ADDR_WDITH] == a2l_app_addr_link_clk[A2L_ADDR_WDITH]) && + (a2l_link_addr_real[A2L_ADDR_WDITH-1:0] == a2l_app_addr_link_clk[A2L_ADDR_WDITH-1:0]); +assign empty = a2l_empty; +//The "REAL" link address is what we are actually reading from in the FIFO +//BUT we send the last known good packet address back to the APP layer, this way +//if we need to do a replay, we can and the app hasn't overwritten the packet + +//The revert will take precedence over the link_advance (since we are going to re-transmit anyways) +assign a2l_link_addr_real_in = enable_link_clk ? link_revert ? link_revert_addr : (link_advance && link_valid ? a2l_link_addr_real + 'd1 : a2l_link_addr_real) : {A2L_ADDR_WDITH+1{1'b0}}; +assign a2l_link_addr_in = link_ack_update ? link_ack_addr : a2l_link_addr; +assign link_valid = enable_link_clk ? ~a2l_empty : 1'b0; + +assign a2l_read = link_valid; + + +assign link_cur_addr = a2l_link_addr_real; +slink_dp_ram #( + //parameters + .SIZE ( A2L_DEPTH ), + .DWIDTH ( A2L_DATA_WIDTH ) +) u_a2l_dp_ram ( + .clk_0 ( app_clk ), + .addr_0 ( a2l_app_addr[A2L_ADDR_WDITH-1:0] ), + .en_0 ( a2l_write ), + .we_0 ( a2l_write ), + .wdata_0 ( a2l_data ), + .rdata_0 ( ), + + .clk_1 ( link_clk ), + .addr_1 ( a2l_link_addr_real[A2L_ADDR_WDITH-1:0] ), + .en_1 ( a2l_read ), + .we_1 ( 1'b0 ), + .wdata_1 ( {A2L_DATA_WIDTH{1'b0}} ), + .rdata_1 ( link_data )); + + +endmodule + + +/** + * This will handle the update in each direction. We will essentially + * always write/read and only update the output when the rready is set + */ +module slink_fc_replay_addr_sync #( + parameter ADDR_WIDTH = 4 +)( + input wire wclk, + input wire wreset, + input wire [ADDR_WIDTH-1:0] waddr, + + input wire rclk, + input wire rreset, + output wire [ADDR_WIDTH-1:0] raddr +); + +wire wready; +wire rready; + +wire [ADDR_WIDTH-1:0] raddr_fifo; +reg [ADDR_WIDTH-1:0] raddr_reg; + + +always @(posedge rclk or posedge rreset) begin + if(rreset) begin + raddr_reg <= {ADDR_WIDTH{1'b0}}; + end else begin + raddr_reg <= rready ? raddr_fifo : raddr_reg; + end +end + +assign raddr = rready ? raddr_fifo : raddr_reg; + +slink_multibit_sync #(.DATA_SIZE(ADDR_WIDTH)) u_slink_multibit_sync ( + .wclk ( wclk ), + .wreset ( wreset ), + .winc ( 1'b1 ), + .wready ( ), + .wdata ( waddr ), + + .rclk ( rclk ), + .rreset ( rreset ), + .rinc ( 1'b1 ), + .rready ( rready ), + .rdata ( raddr_fifo )); + +endmodule diff --git a/rtl/app/slink_generic_fc_sm.v b/rtl/app/slink_generic_fc_sm.v new file mode 100644 index 0000000..4c4bf1f --- /dev/null +++ b/rtl/app/slink_generic_fc_sm.v @@ -0,0 +1,628 @@ +/* +.rst_start +slink_generic_fc_sm +------------------- +This block, known also as "FC block", handles several flow control related items when communicating across S-Link. It houses a +"generic" flow control mechanism that should serve well for the majority of applications. While there +may be some improvements that can be acheived by spinning your own flow control block, this provides +a component for creating larger systems. Several of these can be placed for an application, with the idea +being that you would use a ref:`slink_generic_tx_router` and ref:`slink_generic_rx_router` to route traffic +appropriately. + + +The block has two conceptual directions, Application-to-Link Layer (A2L) and Link Layer-to-Application (L2A). The +data width and FIFO depth are parameters which can be chosen based on the needs of the protocol/data supported. +``A2L_DEPTH`` and ``L2A_DEPTH`` represent the number of FIFO entries for the respective directions. + +.. note :: + + The ``A2L_DEPTH`` and ``L2A_DEPTH`` values should be a power of 2 and should not exceed 256. + + +Flow Control Training +++++++++++++++++++++++ +Upon enabling the FC block, the FC will communicate with the far-end FC, exchanging information regarding +the available credits for each side. Each side of the link will advertise it's maximum TX (A2L) and RX (L2A) +credits. These credits are essentially the number of available entries in each FIFO. + +The link begins by sending a ``GENERIC_SCRD`` packet which is a two byte count Slink long packet with Byte1 +representing the Near-End TX credits and Byte2 representing the Near-End RX credits. + +After recieving a ``GENERIC_SCRD`` packet, the FC block will beging to send a ``GENERIC_CR_ACK`` packet +which indicates to the other side that it has received the credit advertisement. + +After sending `and` recieving a ``GENERIC_CR_ACK`` packet, the FC block will transition to the LINK_IDLE +state and wait for valid data to be transmitted. + +Replay Buffer ++++++++++++++++++ +The A2L direction of the FC block includes replayability features to compensate for any link degradation +resulting in loss of packets. Any time data is sent to the far end, a packet number is prefixed. This packet +number is used to ensure the receiving side did not miss a packet, and the receiving side can inform the +transmitting side that a packet has been missed, resulting in a replay. + +During FC Training, the packet number initializes to zero and increments by one for each packet sent. When +a packet is received an ``ACK`` FC packet is scheduled to be sent. To indicate to the transmitter that the +packet was received in order, and without error. In the event a packet was either received out of order or +with an error in the packet, a ``NACK`` FC packet is scheduled with the last good packet number. Upon reception +by the transmitter of the ``NACK`` with the last good packet number, the TX will start replaying packets starting +after the last good packet number. + + +.rst_end +*/ +module slink_generic_fc_sm #( + //----------------------------- + // App -> Link layer + //----------------------------- + parameter A2L_DATA_WIDTH = 32, //Width of the data entry (includes WC+DT) + parameter A2L_DEPTH = 8, //Number of FIFO entires (MAX 256 ?) + parameter A2L_ADDR_WDITH = $clog2(A2L_DEPTH), + parameter L2A_DATA_WIDTH = 32, //Width of the data entry (includes WC+DT) + parameter L2A_DEPTH = 8, //Number of FIFO entires (MAX 128) + parameter L2A_ADDR_WDITH = $clog2(L2A_DEPTH), + + //When hardcoded, we don't send the DT/WC through the replay. Generally + //used for multi-channel systems. Saves area in the REPLAY buffer + parameter USE_HARDCODED_DTWC = 0, + //parameter HARDCODED_DT = 8'h20, + //parameter HARDCODED_WC = 16'h8, + + parameter TX_APP_DATA_WIDTH = 64, + parameter RX_APP_DATA_WIDTH = 64 +)( + input wire app_clk, + input wire app_reset, + + input wire enable, + + input wire [7:0] swi_cr_id, + input wire [7:0] swi_crack_id, + input wire [7:0] swi_ack_id, + input wire [7:0] swi_nack_id, + + input wire [7:0] swi_data_id, + input wire [15:0] swi_word_count, + + input wire a2l_valid, + output wire a2l_ready, + input wire [A2L_DATA_WIDTH-1:0] a2l_data, + + output wire l2a_valid, + input wire l2a_accept, + output wire [L2A_DATA_WIDTH-1:0] l2a_data, + + output wire tx_fifo_empty, + output wire rx_fifo_empty, + + input wire link_clk, + input wire link_reset, + + output wire nack_sent, //on link_clk + output wire nack_seen, //on link_clk + + output reg tx_sop, + output reg [7:0] tx_data_id, + output reg [15:0] tx_word_count, + output reg [TX_APP_DATA_WIDTH-1:0] tx_app_data, + input wire tx_advance, + + input wire rx_sop, + input wire [7:0] rx_data_id, + input wire [15:0] rx_word_count, + input wire [RX_APP_DATA_WIDTH-1:0] rx_app_data, + input wire rx_valid, + input wire rx_crc_corrupted +); + +localparam IDLE = 'd0, + SEND_CREDITS1 = 'd1, + SEND_CREDITS2 = 'd2, + LINK_IDLE = 'd3, + LINK_DATA = 'd4, + SEND_ACK = 'd5, + SEND_NACK = 'd6; + + +wire [7:0] GENERIC_ACK = swi_ack_id; +wire [7:0] GENERIC_NACK = swi_nack_id; +wire [7:0] GENERIC_SCRD = swi_cr_id; +wire [7:0] GENERIC_CR_ACK= swi_crack_id; + +reg [2:0] state, nstate; +wire enable_link_clk; +reg recv_credits, recv_credits_in; +reg recv_resp_credits, recv_resp_credits_in; +reg [7:0] fe_tx_credit_max, fe_tx_credit_max_in; +reg [7:0] fe_rx_credit_max, fe_rx_credit_max_in; +reg fe_rx_is_full; +reg [2:0] fe_rx_ptr_msb; +wire [7:0] ne_tx_credit_max; +wire [7:0] ne_rx_credit_max; +reg [7:0] exp_pkt_num; +wire [7:0] exp_pkt_num_in; +wire exp_pkt_seen; +wire exp_pkt_not_seen; +reg [7:0] last_good_pkt; +wire [7:0] last_good_pkt_in; +reg [7:0] last_ack_pkt_sent; +reg [7:0] last_ack_pkt_sent_in; +reg send_ack_req; +reg send_ack_req_in; +reg send_nack_req; +reg send_nack_req_in; +//reg [7:0] nack_pkt_num; +//wire [7:0] nack_pkt_num_in; + +wire credit_pkt_recv; +wire resp_credit_pkt_recv; +wire valid_rx_pkt; +wire valid_rx_pkt_crc_err; + +reg ack_seen_before; +wire ack_seen_before_in; + +reg [7:0] fe_rx_ptr; +wire [7:0] fe_rx_ptr_in; +reg [7:0] ne_rx_ptr; +reg [7:0] ne_rx_ptr_in; +wire [7:0] ne_rx_ptr_next; + + +wire link_ack_update; +wire [A2L_ADDR_WDITH:0] link_ack_addr; +wire [A2L_ADDR_WDITH:0] link_cur_addr; +wire [7:0] link_cur_addr_8bit; +wire [A2L_DATA_WIDTH-1:0] link_data_replay; +wire link_valid_replay; +reg link_advance_replay; + + +wire rempty; +wire wfull; +wire [L2A_DATA_WIDTH-1:0] fifo_wdata; +wire [L2A_ADDR_WDITH:0] fifo_rbin_ptr; +reg [L2A_ADDR_WDITH:0] fifo_rbin_ptr_prev; +wire fifo_rbin_ptr_update; +wire [L2A_ADDR_WDITH:0] fifo_rbin_ptr_link_clk; + +wire link_revert; +wire [A2L_ADDR_WDITH:0] link_revert_addr; + + +reg tx_sop_in; +reg [7:0] tx_data_id_in; +reg [15:0] tx_word_count_in; +reg [TX_APP_DATA_WIDTH-1:0] tx_app_data_in; + +wire [7:0] tx_data_id_sel; +wire [15:0] tx_word_count_sel; +wire [TX_APP_DATA_WIDTH-1:0] tx_app_data_sel; + + + +slink_demet_reset u_slink_demet_reset_enable_link_clk ( + .clk ( link_clk ), + .reset ( link_reset ), + .sig_in ( enable ), + .sig_out ( enable_link_clk)); + + +always @(posedge link_clk or posedge link_reset) begin + if(link_reset) begin + state <= IDLE; + recv_credits <= 1'b0; + fe_tx_credit_max <= 8'd0; + fe_rx_credit_max <= 8'd0; + fe_rx_ptr <= 8'd0; + ne_rx_ptr <= 8'd0; + recv_resp_credits <= 1'b0; + exp_pkt_num <= 8'd0; + last_good_pkt <= 8'd0; + last_ack_pkt_sent <= 8'd0; + send_ack_req <= 1'b0; + send_nack_req <= 1'b0; + tx_sop <= 1'b0; + tx_data_id <= 8'd0; + tx_word_count <= 16'd0; + tx_app_data <= {TX_APP_DATA_WIDTH{1'b0}}; + fifo_rbin_ptr_prev <= {L2A_ADDR_WDITH+1{1'b0}}; + ack_seen_before <= 1'b0; + end else begin + state <= nstate; + recv_credits <= recv_credits_in; + fe_tx_credit_max <= fe_tx_credit_max_in; + fe_rx_credit_max <= fe_rx_credit_max_in; + fe_rx_ptr <= fe_rx_ptr_in; + //ne_rx_ptr <= ne_rx_ptr_in; + //On a link revert, we need to refresh the current ne_rx_ptr + ne_rx_ptr <= link_revert ? rx_word_count[15:8] : ne_rx_ptr_in; + recv_resp_credits <= recv_resp_credits_in; + exp_pkt_num <= (state == IDLE) ? 8'd0 : exp_pkt_num_in; + last_good_pkt <= (state == IDLE) ? 8'd0 : last_good_pkt_in; + last_ack_pkt_sent <= (state == IDLE) ? 8'd0 : last_ack_pkt_sent_in; + send_ack_req <= (state == IDLE) ? 1'b0 : send_ack_req_in; + send_nack_req <= (state == IDLE) ? 1'b0 : send_nack_req_in; + + tx_sop <= tx_sop_in; + tx_data_id <= tx_data_id_in; + tx_word_count <= tx_word_count_in; + tx_app_data <= tx_app_data_in; + fifo_rbin_ptr_prev <= fifo_rbin_ptr_link_clk; + ack_seen_before <= ack_seen_before_in; + end +end + + + + +slink_generic_fc_replay #( + //parameters + .A2L_DATA_WIDTH ( A2L_DATA_WIDTH ), + .A2L_DEPTH ( A2L_DEPTH ) +) u_slink_generic_fc_replay ( + .app_clk ( app_clk ), + .app_reset ( app_reset ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .enable ( enable ), + .a2l_valid ( a2l_valid ), + .a2l_ready ( a2l_ready ), + .a2l_data ( a2l_data ), + .empty ( tx_fifo_empty ), + .link_ack_update ( link_ack_update ), + .link_ack_addr ( link_ack_addr ), + .link_revert ( link_revert ), + .link_revert_addr ( link_revert_addr ), + .link_cur_addr ( link_cur_addr ), + .link_data ( link_data_replay ), + .link_valid ( link_valid_replay ), + .link_advance ( link_advance_replay )); + + +assign nack_sent = (state == SEND_NACK) && (nstate != SEND_NACK); +assign nack_seen = link_revert; + + +assign link_ack_update = valid_rx_pkt && (rx_data_id == GENERIC_ACK); +assign link_ack_addr = rx_word_count[A2L_ADDR_WDITH:0]; +assign link_revert = valid_rx_pkt && (rx_data_id == GENERIC_NACK); + +//We will get back the last good packet, so we need to do the last good +1 +//There is an issue however where if you get an error on the first packet and the far end sends +//back a NACK, pkt number 0 is really what you need to replay, not 1. So ensure that we +//know the far end has received at least one packet sucessfully to ensure we don't mess up the sequence +assign link_revert_addr = ack_seen_before ? ((rx_word_count[A2L_ADDR_WDITH:0] == ne_tx_credit_max) ? 'd0 : rx_word_count[A2L_ADDR_WDITH:0] + 'd1) : 'd0; + +assign link_cur_addr_8bit = {{(7-A2L_ADDR_WDITH){1'b0}}, link_cur_addr}; + +assign ne_tx_credit_max = {{(7-A2L_ADDR_WDITH){1'b0}}, {A2L_ADDR_WDITH+1{1'b1}}}; +assign ne_rx_credit_max = {{(7-L2A_ADDR_WDITH){1'b0}}, {L2A_ADDR_WDITH+1{1'b1}}}; + +assign valid_rx_pkt = rx_sop && rx_valid && ~rx_crc_corrupted; + +//We want to block crc errors during credits as we don't have a packet sequence yet +//Stop reverts if the ACK/NACK has a CRC error. We should let the far side just resend. +// +assign valid_rx_pkt_crc_err = rx_sop && rx_valid && rx_crc_corrupted; + +assign credit_pkt_recv = valid_rx_pkt && (rx_data_id == GENERIC_SCRD); +assign resp_credit_pkt_recv = valid_rx_pkt && (rx_data_id == GENERIC_CR_ACK); + + +assign fe_rx_ptr_in = (state == IDLE) ? 8'd0 : (link_ack_update || link_revert) ? rx_word_count[15:8] : fe_rx_ptr; +assign ne_rx_ptr_next = (ne_rx_ptr == fe_rx_credit_max) ? 8'd0 : ne_rx_ptr + 8'd1; + +assign fifo_rbin_ptr_update = fifo_rbin_ptr_link_clk != fifo_rbin_ptr_prev; + + +assign ack_seen_before_in = (state == IDLE) ? 1'b0 : (link_ack_update ? 1'b1 : ack_seen_before); + + +integer i; +always @(*) begin + fe_rx_ptr_msb = 3'd0; + for(i=0; i < 8; i = i + 1) begin + if(fe_rx_credit_max[i]) begin + fe_rx_ptr_msb = i; + end + end + + + //Default to FULL and check for conditions that aren't full + // msb's should be != and all lower bits == for full + //See about optimizing this? I think we can get one more entry + fe_rx_is_full = 1'b1; + for(i=0; i < fe_rx_ptr_msb; i = i + 1) begin + //if(ne_rx_ptr[i] != fe_rx_ptr[i]) begin + if(ne_rx_ptr_next[i] != fe_rx_ptr[i]) begin + fe_rx_is_full = 1'b0; + end + end + //if(ne_rx_ptr[fe_rx_ptr_msb] == fe_rx_ptr[fe_rx_ptr_msb]) begin + if(ne_rx_ptr_next[fe_rx_ptr_msb] == fe_rx_ptr[fe_rx_ptr_msb]) begin + fe_rx_is_full = 1'b0; + end + +end + + +//Picks between the hardcorded and passed through method +generate + if(USE_HARDCODED_DTWC == 1) begin : gen_hardcoded_dtwc + assign tx_data_id_sel = swi_data_id; + assign tx_word_count_sel = swi_word_count + 16'h1; //note the +1 for the packet num + assign tx_app_data_sel = {{TX_APP_DATA_WIDTH-A2L_DATA_WIDTH-8{1'b0}}, link_data_replay[A2L_DATA_WIDTH-1:0], link_cur_addr_8bit}; + end else begin : gen_app_dtwc + assign tx_data_id_sel = link_data_replay[ 7: 0]; + assign tx_word_count_sel = link_data_replay[23: 8] + 16'h1; + assign tx_app_data_sel = {{TX_APP_DATA_WIDTH-A2L_DATA_WIDTH-32{1'b0}}, link_data_replay[A2L_DATA_WIDTH-1:24], link_cur_addr_8bit}; + end +endgenerate + + + +always @(*) begin + nstate = state; + recv_credits_in = recv_credits; + recv_resp_credits_in = recv_resp_credits; + fe_tx_credit_max_in = fe_tx_credit_max; + fe_rx_credit_max_in = fe_rx_credit_max; + ne_rx_ptr_in = ne_rx_ptr; + tx_sop_in = tx_sop; + tx_data_id_in = tx_data_id; + tx_word_count_in = tx_word_count; + tx_app_data_in = tx_app_data; + link_advance_replay = 1'b0; + last_ack_pkt_sent_in = last_ack_pkt_sent; + send_ack_req_in = send_ack_req ? 1'b1 : (exp_pkt_seen | fifo_rbin_ptr_update); + send_nack_req_in = send_nack_req ? 1'b1 : (valid_rx_pkt_crc_err | exp_pkt_not_seen); + + + case(state) + //-------------------------------------------- + IDLE : begin + recv_credits_in = 1'b0; + fe_tx_credit_max_in = 8'd0; + fe_rx_credit_max_in = 8'd0; + ne_rx_ptr_in = 8'd0; + recv_resp_credits_in = 1'b0; + if(enable_link_clk) begin + nstate = SEND_CREDITS1; + end + end + + //-------------------------------------------- + // We will send the number of credits we have and wait for + // a packet that describes the number of credits on the other side + //-------------------------------------------- + SEND_CREDITS1 : begin + tx_sop_in = 1'b1; + tx_data_id_in = GENERIC_SCRD; + //tx_word_count_in = 16'd2; + //tx_app_data_in = {{TX_APP_DATA_WIDTH-16{1'b0}}, ne_rx_credit_max, ne_tx_credit_max}; + tx_word_count_in = {ne_rx_credit_max, ne_tx_credit_max}; + tx_app_data_in = {TX_APP_DATA_WIDTH{1'b0}}; + + if(resp_credit_pkt_recv) begin + recv_resp_credits_in= 1'b1; + end + + if(credit_pkt_recv) begin + recv_credits_in = 1'b1; + fe_tx_credit_max_in = rx_word_count[7:0]; + fe_rx_credit_max_in = rx_word_count[15:8]; + end + + if(tx_advance) begin + if(recv_credits_in) begin + tx_sop_in = 1'b1; + tx_data_id_in = GENERIC_CR_ACK; + //tx_word_count_in = 16'd2; + //tx_app_data_in = {{TX_APP_DATA_WIDTH-16{1'b0}}, ne_rx_credit_max, ne_tx_credit_max}; + tx_word_count_in = {ne_rx_credit_max, ne_tx_credit_max}; + tx_app_data_in = {TX_APP_DATA_WIDTH{1'b0}}; + nstate = SEND_CREDITS2; + end + end + end + + //-------------------------------------------- + SEND_CREDITS2 : begin + tx_sop_in = 1'b1; + tx_data_id_in = GENERIC_CR_ACK; + //tx_word_count_in = 16'd2; + //tx_app_data_in = {{TX_APP_DATA_WIDTH-16{1'b0}}, ne_rx_credit_max, ne_tx_credit_max}; + tx_word_count_in = {ne_rx_credit_max, ne_tx_credit_max}; + tx_app_data_in = {TX_APP_DATA_WIDTH{1'b0}}; + + if(resp_credit_pkt_recv) begin + recv_resp_credits_in= 1'b1; + end + + if(tx_advance) begin + if(recv_resp_credits_in) begin + tx_sop_in = 1'b0; + tx_data_id_in = 8'd0; + tx_word_count_in = 16'd0; + tx_app_data_in = {TX_APP_DATA_WIDTH{1'b0}}; + nstate = LINK_IDLE; + end + end + end + + //-------------------------------------------- + // Priority is NACK -> ACK -> DATA + // + LINK_IDLE : begin + if(send_nack_req) begin + //Capture the most recent good packet and the current RX pointer and send that as part of the NACK + tx_sop_in = 1'b1; + tx_data_id_in = GENERIC_NACK; + //tx_word_count_in = 16'd2; + //tx_app_data_in = {{TX_APP_DATA_WIDTH-16{1'b0}}, fifo_rbin_ptr_link_clk, last_ack_pkt_sent}; + tx_word_count_in = {fifo_rbin_ptr_link_clk, last_ack_pkt_sent}; + tx_app_data_in = {TX_APP_DATA_WIDTH{1'b0}}; + send_nack_req_in = 1'b0; //Clear this now to protect against missing another NACK request + nstate = SEND_NACK; + end else if(send_ack_req) begin + //Capture the most recent good packet and the current RX pointer and send that as part of the ACK + last_ack_pkt_sent_in = last_good_pkt_in; + tx_sop_in = 1'b1; + tx_data_id_in = GENERIC_ACK; + //tx_word_count_in = 16'd2; + //tx_app_data_in = {{TX_APP_DATA_WIDTH-16{1'b0}}, fifo_rbin_ptr_link_clk, last_ack_pkt_sent}; + tx_word_count_in = {fifo_rbin_ptr_link_clk, last_ack_pkt_sent}; + tx_app_data_in = {TX_APP_DATA_WIDTH{1'b0}}; + send_ack_req_in = 1'b0; //Clear this now to protect against missing another ACK request + nstate = SEND_ACK; + end else if(link_valid_replay && ~fe_rx_is_full) begin + tx_sop_in = 1'b1; + tx_data_id_in = tx_data_id_sel; + tx_word_count_in = tx_word_count_sel; + tx_app_data_in = tx_app_data_sel; + link_advance_replay = 1'b1; //go ahead and clear this one + ne_rx_ptr_in = ne_rx_ptr_next; + nstate = LINK_DATA; + end + end + + //-------------------------------------------- + // + LINK_DATA : begin + if(tx_advance) begin + if(send_nack_req) begin + tx_sop_in = 1'b1; + tx_data_id_in = GENERIC_NACK; + //tx_word_count_in = 16'd2; + //tx_app_data_in = {{TX_APP_DATA_WIDTH-16{1'b0}}, fifo_rbin_ptr_link_clk, last_ack_pkt_sent}; + tx_word_count_in = {fifo_rbin_ptr_link_clk, last_ack_pkt_sent}; + tx_app_data_in = {TX_APP_DATA_WIDTH{1'b0}}; + send_nack_req_in = 1'b0; + nstate = SEND_NACK; + end else if(~send_ack_req && link_valid_replay && ~fe_rx_is_full) begin + tx_sop_in = 1'b1; + tx_data_id_in = tx_data_id_sel; + tx_word_count_in = tx_word_count_sel; + tx_app_data_in = tx_app_data_sel; + link_advance_replay = 1'b1; + ne_rx_ptr_in = ne_rx_ptr_next; + end else begin + tx_sop_in = 1'b0; + nstate = LINK_IDLE; + end + end + end + + //-------------------------------------------- + // Add check for valid data or NACK + SEND_ACK : begin + if(tx_advance) begin + tx_sop_in = 1'b0; + nstate = LINK_IDLE; + end + end + + //-------------------------------------------- + SEND_NACK : begin + if(tx_advance) begin + tx_sop_in = 1'b0; + nstate = LINK_IDLE; + end + end + + + default : begin + nstate = IDLE; + end + endcase + + if(~enable_link_clk) begin + nstate = IDLE; + end +end + + +//you want to ignore credits and ACKs/nacks +assign exp_pkt_not_seen = valid_rx_pkt && ~(credit_pkt_recv || resp_credit_pkt_recv || link_ack_update || link_revert) && (rx_app_data[7:0] != exp_pkt_num); +assign exp_pkt_seen = valid_rx_pkt && ~(credit_pkt_recv || resp_credit_pkt_recv || link_ack_update || link_revert) && (rx_app_data[7:0] == exp_pkt_num); +assign exp_pkt_num_in = exp_pkt_seen ? (exp_pkt_num == fe_tx_credit_max) ? 8'd0 : exp_pkt_num + 'd1 : exp_pkt_num; + +//assign last_good_pkt_in = exp_pkt_seen ? exp_pkt_num_in : last_good_pkt; +assign last_good_pkt_in = exp_pkt_seen ? exp_pkt_num : last_good_pkt; + + + + + +generate + if(USE_HARDCODED_DTWC == 1) begin : gen_hardcoded_rxdata + assign fifo_wdata = rx_app_data[L2A_DATA_WIDTH+7:8]; + end else begin : gen_app_rxdata + assign fifo_wdata = {rx_app_data[L2A_DATA_WIDTH-15:8], rx_word_count, rx_data_id}; + end +endgenerate + +slink_fc_replay_addr_sync #( + //parameters + .ADDR_WIDTH ( L2A_ADDR_WDITH+1 ) +) u_slink_fc_replay_addr_sync ( + .wclk ( app_clk ), + .wreset ( app_reset ), + .waddr ( fifo_rbin_ptr ), + .rclk ( link_clk ), + .rreset ( link_reset ), + .raddr ( fifo_rbin_ptr_link_clk )); + + + +// Using this backwards for now +// app is the link +// link is the app +wire [L2A_ADDR_WDITH:0] receive_dp_addr; +slink_generic_fc_replay #( + //parameters + .A2L_DEPTH ( L2A_DEPTH ), + .A2L_DATA_WIDTH ( L2A_DATA_WIDTH ) +) u_receive_dpram ( + .app_clk ( link_clk ), + .app_reset ( link_reset ), + .link_clk ( app_clk ), + .link_reset ( app_reset ), + .enable ( enable ), + .a2l_valid ( exp_pkt_seen ), + .a2l_ready ( ), //need to check this + .a2l_data ( fifo_wdata ), + .empty ( rx_fifo_empty ), + .link_ack_update ( 1'b1 ), + .link_ack_addr ( fifo_rbin_ptr ), + .link_cur_addr ( fifo_rbin_ptr ), + .link_revert ( 1'b0 ), + .link_revert_addr ( {L2A_ADDR_WDITH+1{1'b0}} ), + .link_data ( l2a_data ), + .link_valid ( l2a_valid ), + .link_advance ( l2a_accept )); + + + +//assign l2a_valid = ~rx_fifo_empty; + + +`ifdef SIMULATION +reg [8*40:1] state_name; +always @(*) begin + case(state) + IDLE : state_name = "IDLE"; + SEND_CREDITS1 : state_name = "SEND_CREDITS1"; + SEND_CREDITS2 : state_name = "SEND_CREDITS2"; + LINK_IDLE : state_name = "LINK_IDLE"; + LINK_DATA : state_name = "LINK_DATA"; + SEND_ACK : state_name = "SEND_ACK"; + SEND_NACK : state_name = "SEND_NACK"; + endcase +end + +`endif + +endmodule + diff --git a/rtl/app/slink_generic_pstate_ctrl.v b/rtl/app/slink_generic_pstate_ctrl.v new file mode 100644 index 0000000..ac2758a --- /dev/null +++ b/rtl/app/slink_generic_pstate_ctrl.v @@ -0,0 +1,109 @@ +/* +.rst_start +slink_generic_pstate_ctrl +------------------------- +Implements a simple timer-based Pstate controller. Link activity resets the timer. If +timer expires then the link goes into the lowest selected PState. + +.rst_end +*/ + + +module slink_generic_pstate_ctrl( + input wire refclk, + input wire refclk_reset, + input wire enable, + + input wire link_clk, + input wire link_clk_reset, + input wire link_active, + input wire in_px_state, + + input wire [7:0] swi_1us_tick_count, + input wire [7:0] swi_inactivity_count, + input wire [2:0] swi_pstate_req, + + output reg p1_req, + output reg p2_req, + output reg p3_req +); + +wire enable_ff2; +wire in_px_state_ff2; +reg in_px_state_ff3; +wire px_state_exit; +reg [7:0] count_1us; +wire [7:0] count_1us_in; +wire count_1us_tick; +reg [7:0] inactivity_count; +wire [7:0] inactivity_count_in; +wire inactivity_time_reached; +wire p1_req_in; +wire p2_req_in; +wire p3_req_in; + + +slink_demet_reset u_slink_demet_reset ( + .clk ( refclk ), + .reset ( refclk_reset ), + .sig_in ( enable ), + .sig_out ( enable_ff2 )); + +slink_demet_reset u_slink_demet_reset_in_px_state ( + .clk ( refclk ), + .reset ( refclk_reset ), + .sig_in ( in_px_state ), + .sig_out ( in_px_state_ff2 )); + + +wire link_acitve_sync; +wire link_acitve_valid; +wire link_acitve_refclk; + +slink_multibit_sync #(.DATA_SIZE(1)) u_slink_multibit_sync ( + .wclk ( link_clk ), + .wreset ( link_clk_reset ), + .winc ( link_active ), + .wready ( ), + .wdata ( link_active ), + + .rclk ( refclk ), + .rreset ( refclk_reset ), + .rinc ( 1'b1 ), + .rready ( link_acitve_valid), + .rdata ( link_acitve_sync )); + +assign link_acitve_refclk = (link_acitve_valid && link_acitve_sync) || px_state_exit; + + +always @(posedge refclk or posedge refclk_reset) begin + if(refclk_reset) begin + count_1us <= 8'd0; + inactivity_count <= 8'd0; + p1_req <= 1'b0; + p2_req <= 1'b0; + p3_req <= 1'b0; + in_px_state_ff3 <= 1'b0; + end else begin + count_1us <= count_1us_in; + inactivity_count <= inactivity_count_in; + p1_req <= p1_req_in; + p2_req <= p2_req_in; + p3_req <= p3_req_in; + in_px_state_ff3 <= in_px_state_ff2; + end +end + +assign px_state_exit = ~in_px_state_ff2 & in_px_state_ff3; + +assign count_1us_tick = count_1us == swi_1us_tick_count; +assign count_1us_in = ~enable_ff2 ? 8'd0 : count_1us_tick ? 8'd0 : count_1us + 8'd1; +assign inactivity_time_reached = (inactivity_count == swi_inactivity_count); +assign inactivity_count_in = ~enable_ff2 || link_acitve_refclk ? 8'd0 : count_1us_tick ? (inactivity_time_reached ? inactivity_count : inactivity_count + 8'd1) : inactivity_count; + + +assign p3_req_in = inactivity_time_reached && swi_pstate_req[2]; +assign p2_req_in = inactivity_time_reached && swi_pstate_req[1] && ~p3_req_in; +assign p1_req_in = inactivity_time_reached && swi_pstate_req[0] && ~p2_req_in; + +endmodule diff --git a/rtl/app/slink_generic_rx_router.v b/rtl/app/slink_generic_rx_router.v new file mode 100644 index 0000000..78946db --- /dev/null +++ b/rtl/app/slink_generic_rx_router.v @@ -0,0 +1,80 @@ +/* +.rst_start +slink_generic_rx_router +----------------------- + +This "generic" router will send RX data to the repsective channel based on +``rx_data_id`` windows. A user would set ``SP_CH_MIN``, ``SP_CH_MAX``, ``LP_CH_MIN``, +and ``LP_CH_MAX`` for each channel and the start of a packet would enable that channel until the start +of the next received packet. The channel windows are exclusive, meaning +separate channels cannot share the same data IDs. + +.rst_end +*/ + +module slink_generic_rx_router #( + parameter NUM_CHANNELS = 8, + parameter RX_APP_DATA_WIDTH = 64 +)( + input wire clk, + input wire reset, + + input wire rx_sop, + input wire [7:0] rx_data_id, + input wire [15:0] rx_word_count, + input wire [RX_APP_DATA_WIDTH-1:0] rx_app_data, + input wire rx_valid, + input wire rx_crc_corrupted, + + input wire [(NUM_CHANNELS*8)-1:0] swi_ch_sp_min, + input wire [(NUM_CHANNELS*8)-1:0] swi_ch_sp_max, + input wire [(NUM_CHANNELS*8)-1:0] swi_ch_lp_min, + input wire [(NUM_CHANNELS*8)-1:0] swi_ch_lp_max, + + output wire [NUM_CHANNELS-1:0] rx_sop_ch, + output wire [(NUM_CHANNELS*8)-1:0] rx_data_id_ch, + output wire [(NUM_CHANNELS*16)-1:0] rx_word_count_ch, + output wire [(NUM_CHANNELS* + RX_APP_DATA_WIDTH)-1:0] rx_app_data_ch, + output wire [NUM_CHANNELS-1:0] rx_valid_ch, + output wire [NUM_CHANNELS-1:0] rx_crc_corrupted_ch +); + +localparam NUM_CHANNELS_CLOG2 = $clog2(NUM_CHANNELS); + +reg [NUM_CHANNELS-1:0] ch_sel; +wire [NUM_CHANNELS-1:0] ch_sel_in; +wire ch_update; +wire enable_ff2; + + +always @(posedge clk or posedge reset) begin + if(reset) begin + ch_sel <= {NUM_CHANNELS_CLOG2{1'b0}}; + end else begin + ch_sel <= ch_sel_in; + end +end + + +assign ch_update = rx_sop && rx_valid; + +genvar index; +generate + for(index = 0; index < NUM_CHANNELS; index = index + 1) begin : gen_indexes + assign ch_sel_in[index] = ch_update ? ((rx_data_id >= swi_ch_sp_min[((index+1)*8)-1:(index*8)]) && + (rx_data_id <= swi_ch_sp_max[((index+1)*8)-1:(index*8)])) || + ((rx_data_id >= swi_ch_lp_min[((index+1)*8)-1:(index*8)]) && + (rx_data_id <= swi_ch_lp_max[((index+1)*8)-1:(index*8)])) : ch_sel[index]; + + assign rx_sop_ch[index] = rx_sop && ch_sel_in[index]; + assign rx_valid_ch[index] = rx_valid && ch_sel_in[index]; + assign rx_crc_corrupted_ch[index] = rx_crc_corrupted && ch_sel_in[index]; + assign rx_data_id_ch[((index+1)*8)-1:(index*8)] = rx_data_id; + assign rx_word_count_ch[((index+1)*16)-1:(index*16)] = rx_word_count; + assign rx_app_data_ch[((index+1)*RX_APP_DATA_WIDTH)-1:(index*RX_APP_DATA_WIDTH)] = rx_app_data; + end +endgenerate + +endmodule + diff --git a/rtl/app/slink_generic_tx_router.v b/rtl/app/slink_generic_tx_router.v new file mode 100644 index 0000000..b4a48ae --- /dev/null +++ b/rtl/app/slink_generic_tx_router.v @@ -0,0 +1,144 @@ +/* +.rst_start +slink_generic_tx_router +----------------------- + +This "generic" router will arbitrate between N channels for TX data. Priority is given to the lowest +channel number, however a lower channel will not preempt a higher channel if the higher channel started +it's transaction first. In addition, a lower channel must wait until all of the higher channels have +completed, similar to most round robin arbitration schemes. Here is an example: + + **Example 1:** + Channels 0, 1, and 4 all assert ``tx_sop`` on the same cycle. Channel 0 will have priority, then Channel 1, + then Channel 4. If Channel 0 wants to start another packet on the following cycle, it will be blocked until *after* + Channel 4 has sent. + + **Example 2:** + Channels 1 and 2 all assert ``tx_sop`` on the same cycle. Channel 1 will have priority and start sending data. Channel 0 + then wants to send another packet (1+ cycles after Channel 1 and 2 started), Channel 1 and 2 will both complete before + Channel 0 is allowed through. + +The selected channel defaults to 0 when not active. If a Channel other than 0 starts a transmission, there is no +cycle delay to swtich to that channel. + +.rst_end +*/ + +module slink_generic_tx_router #( + parameter NUM_CHANNELS = 8, + parameter TX_APP_DATA_WIDTH = 64 +)( + input wire clk, + input wire reset, + input wire enable, + + input wire [NUM_CHANNELS-1:0] tx_sop_ch, + input wire [(NUM_CHANNELS*8)-1:0] tx_data_id_ch, + input wire [(NUM_CHANNELS*16)-1:0] tx_word_count_ch, + input wire [(NUM_CHANNELS* + TX_APP_DATA_WIDTH)-1:0] tx_app_data_ch, + output wire [NUM_CHANNELS-1:0] tx_advance_ch, + + output wire tx_sop, + output wire [7:0] tx_data_id, + output wire [15:0] tx_word_count, + output wire [TX_APP_DATA_WIDTH-1:0] tx_app_data, + input wire tx_advance +); + +localparam NUM_CHANNELS_CLOG2 = $clog2(NUM_CHANNELS); + +reg [NUM_CHANNELS_CLOG2-1:0] curr_ch; +reg [NUM_CHANNELS_CLOG2-1:0] curr_ch_reg; +reg [NUM_CHANNELS_CLOG2-1:0] curr_ch_reg_in; +wire [NUM_CHANNELS_CLOG2-1:0] curr_ch_next; +wire enable_ff2; + +wire [NUM_CHANNELS-1:0] higher_index_sel; +reg [NUM_CHANNELS_CLOG2-1:0] higher_index_pri; +wire [NUM_CHANNELS-1:0] lower_index_sel; +reg [NUM_CHANNELS_CLOG2-1:0] lower_index_pri; + +wire tx_sop_sel [NUM_CHANNELS-1:0]; +wire [7:0] tx_data_id_sel [NUM_CHANNELS-1:0]; +wire [15:0] tx_word_count_sel [NUM_CHANNELS-1:0]; +wire [TX_APP_DATA_WIDTH-1:0] tx_app_data_sel [NUM_CHANNELS-1:0]; + +slink_demet_reset u_slink_demet_reset_enable ( + .clk ( clk ), + .reset ( reset ), + .sig_in ( enable ), + .sig_out ( enable_ff2 )); + + +always @(posedge clk or posedge reset) begin + if(reset) begin + curr_ch_reg <= {NUM_CHANNELS_CLOG2{1'b0}}; + end else begin + curr_ch_reg <= enable_ff2 ? curr_ch_reg_in : {NUM_CHANNELS_CLOG2{1'b0}}; + end +end + + +genvar index; +generate + for(index = 0; index < NUM_CHANNELS; index = index + 1) begin : gen_indexes + assign higher_index_sel[index] = (index > curr_ch_reg) && tx_sop_ch[index]; + assign lower_index_sel[index] = (index <= curr_ch_reg) && tx_sop_ch[index]; + + assign tx_advance_ch[index] = tx_advance && (curr_ch == index); + + assign tx_sop_sel[index] = tx_sop_ch[index]; + assign tx_data_id_sel[index] = tx_data_id_ch[((index+1)*8)-1:(index*8)]; + assign tx_word_count_sel[index] = tx_word_count_ch[((index+1)*16)-1:(index*16)]; + assign tx_app_data_sel[index] = tx_app_data_ch[((index+1)*TX_APP_DATA_WIDTH)-1:(index*TX_APP_DATA_WIDTH)]; + end +endgenerate + + +integer i; +always @(*) begin + higher_index_pri = {NUM_CHANNELS_CLOG2{1'b0}}; + for(i = (NUM_CHANNELS-1); i >= 0; i = i - 1) begin + if((i > curr_ch_reg) && tx_sop_ch[i]) begin + higher_index_pri = i; + end + end +end + +integer j; +always @(*) begin + lower_index_pri = {NUM_CHANNELS_CLOG2{1'b0}}; + for(j = (NUM_CHANNELS-1); j >= 0; j = j - 1) begin + //if((j <= curr_ch_reg) && tx_sop_ch[j]) begin + if((j < curr_ch_reg) && tx_sop_ch[j]) begin + lower_index_pri = j; + end + end +end + + + +always @(*) begin + curr_ch_reg_in = curr_ch_reg; + curr_ch = curr_ch_reg; + + if((curr_ch_reg != higher_index_pri) && ~(|lower_index_sel)) begin + curr_ch_reg_in = higher_index_pri; + curr_ch = higher_index_pri; + end else begin + if(tx_advance) begin + curr_ch_reg_in = |higher_index_sel ? higher_index_pri : + |lower_index_sel ? lower_index_pri : {NUM_CHANNELS_CLOG2{1'b0}}; + end + end + +end + +assign tx_sop = tx_sop_sel [curr_ch]; +assign tx_data_id = tx_data_id_sel [curr_ch]; +assign tx_word_count = tx_word_count_sel[curr_ch]; +assign tx_app_data = tx_app_data_sel [curr_ch]; + + +endmodule diff --git a/rtl/bist/regs/create_regs.csh b/rtl/bist/regs/create_regs.csh new file mode 100755 index 0000000..bc47331 --- /dev/null +++ b/rtl/bist/regs/create_regs.csh @@ -0,0 +1,9 @@ +#!/bin/bash + +gen_regs_py -i slink_bist_regs.txt -p slink -b bist -cm slink_clock_mux -dm slink_demet_reset +gen_regs_py -i slink_bist_regs.txt -p slink -b bist -sphinx > ../../../docs/source/bist_regs.rst +gen_regs_py -i slink_bist_regs.txt -p slink -b bist -dv +##mv slink_bist_addr_defines.vh ../../../verif/slink/tests/ +##rm slink_bist_dv.txt + +gen_inst -t slink_bist_regs_top -of ../slink_bist.v -gen_wires -wire_only diff --git a/rtl/bist/regs/slink_bist_addr_defines.vh b/rtl/bist/regs/slink_bist_addr_defines.vh new file mode 100644 index 0000000..4e2f3ef --- /dev/null +++ b/rtl/bist/regs/slink_bist_addr_defines.vh @@ -0,0 +1,53 @@ +//=================================================================== +// +// Created by sbridges on December/22/2020 at 13:54:41 +// +// slink_bist_addr_defines.vh +// +//=================================================================== + + + +`define SLINK_BIST_SWRESET 'h00000000 +`define SLINK_BIST_SWRESET__SWRESET 0 +`define SLINK_BIST_SWRESET___POR 32'h00000001 + +`define SLINK_BIST_BIST_MAIN_CONTROL 'h00000004 +`define SLINK_BIST_BIST_MAIN_CONTROL__DISABLE_CLKGATE 4 +`define SLINK_BIST_BIST_MAIN_CONTROL__BIST_ACTIVE 3 +`define SLINK_BIST_BIST_MAIN_CONTROL__BIST_RESET 2 +`define SLINK_BIST_BIST_MAIN_CONTROL__BIST_RX_EN 1 +`define SLINK_BIST_BIST_MAIN_CONTROL__BIST_TX_EN 0 +`define SLINK_BIST_BIST_MAIN_CONTROL___POR 32'h00000000 + +`define SLINK_BIST_BIST_MODE 'h00000008 +`define SLINK_BIST_BIST_MODE__BIST_MODE_DI 5 +`define SLINK_BIST_BIST_MODE__BIST_MODE_WC 4 +`define SLINK_BIST_BIST_MODE__BIST_MODE_PAYLOAD 3:0 +`define SLINK_BIST_BIST_MODE___POR 32'h00000000 + +`define SLINK_BIST_BIST_WORD_COUNT_VALUES 'h0000000C +`define SLINK_BIST_BIST_WORD_COUNT_VALUES__BIST_WC_MAX 31:16 +`define SLINK_BIST_BIST_WORD_COUNT_VALUES__BIST_WC_MIN 15:0 +`define SLINK_BIST_BIST_WORD_COUNT_VALUES___POR 32'h0064000A + +`define SLINK_BIST_BIST_DATA_ID_VALUES 'h00000010 +`define SLINK_BIST_BIST_DATA_ID_VALUES__BIST_DI_MAX 15:8 +`define SLINK_BIST_BIST_DATA_ID_VALUES__BIST_DI_MIN 7:0 +`define SLINK_BIST_BIST_DATA_ID_VALUES___POR 32'h0000F020 + +`define SLINK_BIST_BIST_STATUS 'h00000014 +`define SLINK_BIST_BIST_STATUS__BIST_ERRORS 31:16 +`define SLINK_BIST_BIST_STATUS__RESERVED0 15:2 +`define SLINK_BIST_BIST_STATUS__BIST_UNRECOVER 1 +`define SLINK_BIST_BIST_STATUS__BIST_LOCKED 0 +`define SLINK_BIST_BIST_STATUS___POR 32'h00000000 + +`define SLINK_BIST_DEBUG_BUS_CTRL 'h00000018 +`define SLINK_BIST_DEBUG_BUS_CTRL__DEBUG_BUS_CTRL_SEL 0 +`define SLINK_BIST_DEBUG_BUS_CTRL___POR 32'h00000000 + +`define SLINK_BIST_DEBUG_BUS_STATUS 'h0000001C +`define SLINK_BIST_DEBUG_BUS_STATUS__DEBUG_BUS_CTRL_STATUS 31:0 +`define SLINK_BIST_DEBUG_BUS_STATUS___POR 32'h00000000 + diff --git a/rtl/bist/regs/slink_bist_dv.txt b/rtl/bist/regs/slink_bist_dv.txt new file mode 100644 index 0000000..fb428f1 --- /dev/null +++ b/rtl/bist/regs/slink_bist_dv.txt @@ -0,0 +1,37 @@ +# +# +SLINK_BIST_SWRESET RW 'h0 <\DESC> +SWRESET 1 0 1'h1 RW Main software reset for BIST logic<\DESC> + +SLINK_BIST_BIST_MAIN_CONTROL RW 'h4 <\DESC> +DISABLE_CLKGATE 1 4 1'h0 RW <\DESC> +BIST_ACTIVE 1 3 1'h0 RW Signal exits the BIST block and can be used to control an external mux for data path.<\DESC> +BIST_RESET 1 2 1'h0 RW Reset for clearing BIST error counters<\DESC> +BIST_RX_EN 1 1 1'h0 RW Main Enable for RX. Controls clock gate for BIST logic<\DESC> +BIST_TX_EN 1 0 1'h0 RW Main Enable for TX. Controls clock gate for BIST logic<\DESC> + +SLINK_BIST_BIST_MODE RW 'h8 <\DESC> +BIST_MODE_DI 1 5 1'h0 RW 0 - Always use fixed data id (di_min). 1 - Cycle through data id (min -> max back to min)<\DESC> +BIST_MODE_WC 1 4 1'h0 RW 0 - Always use fixed word count (wc_min). 1 - Cycle through word counts (min -> max back to min)<\DESC> +BIST_MODE_PAYLOAD 4 0 4'h0 RW Denotes long data payload type. 0 - 1010, 1 - 1100, 2 - 1111_0000, 8 - counter, 9 - PRBS9<\DESC> + +SLINK_BIST_BIST_WORD_COUNT_VALUES RW 'hc <\DESC> +BIST_WC_MAX 16 16 16'h64 RW Maximum number of bytes in payload<\DESC> +BIST_WC_MIN 16 0 16'ha RW Minimum number of bytes in payload<\DESC> + +SLINK_BIST_BIST_DATA_ID_VALUES RW 'h10 <\DESC> +BIST_DI_MAX 8 8 8'hf0 RW Maximum Data ID Value<\DESC> +BIST_DI_MIN 8 0 8'h20 RW Minimum Data ID Value<\DESC> + +SLINK_BIST_BIST_STATUS RO 'h14 <\DESC> +BIST_ERRORS 16 16 16'h0 RO Number of errors seen during this run. Saturates at all ones.<\DESC> +RESERVED0 14 2 14'h0 RO <\DESC> +BIST_UNRECOVER 1 1 1'h0 RO 1 - BIST RX has received data in such a way that the remaining data stream is not likely to be observable.<\DESC> +BIST_LOCKED 1 0 1'h0 RO 1 - BIST RX has seen at least one start of packet and word count has not had an issue<\DESC> + +SLINK_BIST_DEBUG_BUS_CTRL RW 'h18 Debug observation bus selection for signals that have a mux override<\DESC> +DEBUG_BUS_CTRL_SEL 1 0 1'h0 RW Select signal for DEBUG_BUS_CTRL<\DESC> + +SLINK_BIST_DEBUG_BUS_STATUS RO 'h1c Debug observation bus for signals that have a mux override<\DESC> +DEBUG_BUS_CTRL_STATUS 32 0 32'h0 RO Status output for DEBUG_BUS_STATUS<\DESC> + diff --git a/rtl/bist/regs/slink_bist_regs.txt b/rtl/bist/regs/slink_bist_regs.txt new file mode 100644 index 0000000..d739417 --- /dev/null +++ b/rtl/bist/regs/slink_bist_regs.txt @@ -0,0 +1,28 @@ +SWRESET RW + swreset 1'b1 Main software reset for BIST logic + +BIST_MAIN_CONTROL RW + bist_tx_en 1'b0 Main Enable for TX. Controls clock gate for BIST logic + bist_rx_en 1'b0 Main Enable for RX. Controls clock gate for BIST logic + bist_reset 1'b0 Reset for clearing BIST error counters + bist_active 1'b0 Signal exits the BIST block and can be used to control an external mux for data path. + disable_clkgate 1'b0 + +BIST_MODE RW + bist_mode_payload 4'h0 Denotes long data payload type. 0 - 1010, 1 - 1100, 2 - 1111_0000, 8 - counter, 9 - PRBS9 + bist_mode_wc 1'b0 0 - Always use fixed word count (wc_min). 1 - Cycle through word counts (min -> max back to min) + bist_mode_di 1'b0 0 - Always use fixed data id (di_min). 1 - Cycle through data id (min -> max back to min) + +BIST_WORD_COUNT_VALUES RW + bist_wc_min 16'd10 Minimum number of bytes in payload + bist_wc_max 16'd100 Maximum number of bytes in payload + +BIST_DATA_ID_VALUES RW + bist_di_min 8'h20 Minimum Data ID Value + bist_di_max 8'hf0 Maximum Data ID Value + +BIST_STATUS RO + bist_locked 1'b0 1 - BIST RX has seen at least one start of packet and word count has not had an issue + bist_unrecover 1'b0 1 - BIST RX has received data in such a way that the remaining data stream is not likely to be observable. + reserved 14'd0 + bist_errors 16'd0 Number of errors seen during this run. Saturates at all ones. diff --git a/rtl/bist/regs/slink_bist_regs_top.v b/rtl/bist/regs/slink_bist_regs_top.v new file mode 100644 index 0000000..387f5c6 --- /dev/null +++ b/rtl/bist/regs/slink_bist_regs_top.v @@ -0,0 +1,433 @@ +//=================================================================== +// +// Created by sbridges on December/22/2020 at 13:54:40 +// +// slink_bist_regs_top.v +// +//=================================================================== + + + +module slink_bist_regs_top #( + parameter ADDR_WIDTH = 8 +)( + //SWRESET + output wire swi_swreset, + //BIST_MAIN_CONTROL + output wire swi_bist_tx_en, + output wire swi_bist_rx_en, + output wire swi_bist_reset, + output wire swi_bist_active, + output wire swi_disable_clkgate, + //BIST_MODE + output wire [3:0] swi_bist_mode_payload, + output wire swi_bist_mode_wc, + output wire swi_bist_mode_di, + //BIST_WORD_COUNT_VALUES + output wire [15:0] swi_bist_wc_min, + output wire [15:0] swi_bist_wc_max, + //BIST_DATA_ID_VALUES + output wire [7:0] swi_bist_di_min, + output wire [7:0] swi_bist_di_max, + //BIST_STATUS + input wire bist_locked, + input wire bist_unrecover, + input wire [15:0] bist_errors, + //DEBUG_BUS_STATUS + output reg [31:0] debug_bus_ctrl_status, + + //DFT Ports (if used) + + // APB Interface + input wire RegReset, + input wire RegClk, + input wire PSEL, + input wire PENABLE, + input wire PWRITE, + output wire PSLVERR, + output wire PREADY, + input wire [(ADDR_WIDTH-1):0] PADDR, + input wire [31:0] PWDATA, + output wire [31:0] PRDATA +); + + //DFT Tieoffs (if not used) + wire dft_core_scan_mode = 1'b0; + wire dft_iddq_mode = 1'b0; + wire dft_hiz_mode = 1'b0; + wire dft_bscan_mode = 1'b0; + + //APB Setup/Access + wire [(ADDR_WIDTH-1):0] RegAddr_in; + reg [(ADDR_WIDTH-1):0] RegAddr; + wire [31:0] RegWrData_in; + reg [31:0] RegWrData; + wire RegWrEn_in; + reg RegWrEn_pq; + wire RegWrEn; + + assign RegAddr_in = PSEL ? PADDR : RegAddr; + + always @(posedge RegClk or posedge RegReset) begin + if (RegReset) begin + RegAddr <= {(ADDR_WIDTH){1'b0}}; + end else begin + RegAddr <= RegAddr_in; + end + end + + assign RegWrData_in = PSEL ? PWDATA : RegWrData; + + always @(posedge RegClk or posedge RegReset) begin + if (RegReset) begin + RegWrData <= 32'h00000000; + end else begin + RegWrData <= RegWrData_in; + end + end + + assign RegWrEn_in = PSEL & PWRITE; + + always @(posedge RegClk or posedge RegReset) begin + if (RegReset) begin + RegWrEn_pq <= 1'b0; + end else begin + RegWrEn_pq <= RegWrEn_in; + end + end + + assign RegWrEn = RegWrEn_pq & PENABLE; + + //assign PSLVERR = 1'b0; + assign PREADY = 1'b1; + + + + //Regs for Mux Override sel + + + + //--------------------------- + // SWRESET + // swreset - Main software reset for BIST logic + //--------------------------- + wire [31:0] SWRESET_reg_read; + reg reg_swreset; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_swreset <= 1'h1; + end else if(RegAddr == 'h0 && RegWrEn) begin + reg_swreset <= RegWrData[0]; + end else begin + reg_swreset <= reg_swreset; + end + end + + assign SWRESET_reg_read = {31'h0, + reg_swreset}; + + //----------------------- + assign swi_swreset = reg_swreset; + + + + + + //--------------------------- + // BIST_MAIN_CONTROL + // bist_tx_en - Main Enable for TX. Controls clock gate for BIST logic + // bist_rx_en - Main Enable for RX. Controls clock gate for BIST logic + // bist_reset - Reset for clearing BIST error counters + // bist_active - Signal exits the BIST block and can be used to control an external mux for data path. + // disable_clkgate - + //--------------------------- + wire [31:0] BIST_MAIN_CONTROL_reg_read; + reg reg_bist_tx_en; + reg reg_bist_rx_en; + reg reg_bist_reset; + reg reg_bist_active; + reg reg_disable_clkgate; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_bist_tx_en <= 1'h0; + reg_bist_rx_en <= 1'h0; + reg_bist_reset <= 1'h0; + reg_bist_active <= 1'h0; + reg_disable_clkgate <= 1'h0; + end else if(RegAddr == 'h4 && RegWrEn) begin + reg_bist_tx_en <= RegWrData[0]; + reg_bist_rx_en <= RegWrData[1]; + reg_bist_reset <= RegWrData[2]; + reg_bist_active <= RegWrData[3]; + reg_disable_clkgate <= RegWrData[4]; + end else begin + reg_bist_tx_en <= reg_bist_tx_en; + reg_bist_rx_en <= reg_bist_rx_en; + reg_bist_reset <= reg_bist_reset; + reg_bist_active <= reg_bist_active; + reg_disable_clkgate <= reg_disable_clkgate; + end + end + + assign BIST_MAIN_CONTROL_reg_read = {27'h0, + reg_disable_clkgate, + reg_bist_active, + reg_bist_reset, + reg_bist_rx_en, + reg_bist_tx_en}; + + //----------------------- + assign swi_bist_tx_en = reg_bist_tx_en; + + //----------------------- + assign swi_bist_rx_en = reg_bist_rx_en; + + //----------------------- + assign swi_bist_reset = reg_bist_reset; + + //----------------------- + assign swi_bist_active = reg_bist_active; + + //----------------------- + assign swi_disable_clkgate = reg_disable_clkgate; + + + + + + //--------------------------- + // BIST_MODE + // bist_mode_payload - Denotes long data payload type. 0 - 1010, 1 - 1100, 2 - 1111_0000, 8 - counter, 9 - PRBS9 + // bist_mode_wc - 0 - Always use fixed word count (wc_min). 1 - Cycle through word counts (min -> max back to min) + // bist_mode_di - 0 - Always use fixed data id (di_min). 1 - Cycle through data id (min -> max back to min) + //--------------------------- + wire [31:0] BIST_MODE_reg_read; + reg [3:0] reg_bist_mode_payload; + reg reg_bist_mode_wc; + reg reg_bist_mode_di; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_bist_mode_payload <= 4'h0; + reg_bist_mode_wc <= 1'h0; + reg_bist_mode_di <= 1'h0; + end else if(RegAddr == 'h8 && RegWrEn) begin + reg_bist_mode_payload <= RegWrData[3:0]; + reg_bist_mode_wc <= RegWrData[4]; + reg_bist_mode_di <= RegWrData[5]; + end else begin + reg_bist_mode_payload <= reg_bist_mode_payload; + reg_bist_mode_wc <= reg_bist_mode_wc; + reg_bist_mode_di <= reg_bist_mode_di; + end + end + + assign BIST_MODE_reg_read = {26'h0, + reg_bist_mode_di, + reg_bist_mode_wc, + reg_bist_mode_payload}; + + //----------------------- + assign swi_bist_mode_payload = reg_bist_mode_payload; + + //----------------------- + assign swi_bist_mode_wc = reg_bist_mode_wc; + + //----------------------- + assign swi_bist_mode_di = reg_bist_mode_di; + + + + + + //--------------------------- + // BIST_WORD_COUNT_VALUES + // bist_wc_min - Minimum number of bytes in payload + // bist_wc_max - Maximum number of bytes in payload + //--------------------------- + wire [31:0] BIST_WORD_COUNT_VALUES_reg_read; + reg [15:0] reg_bist_wc_min; + reg [15:0] reg_bist_wc_max; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_bist_wc_min <= 16'ha; + reg_bist_wc_max <= 16'h64; + end else if(RegAddr == 'hc && RegWrEn) begin + reg_bist_wc_min <= RegWrData[15:0]; + reg_bist_wc_max <= RegWrData[31:16]; + end else begin + reg_bist_wc_min <= reg_bist_wc_min; + reg_bist_wc_max <= reg_bist_wc_max; + end + end + + assign BIST_WORD_COUNT_VALUES_reg_read = { reg_bist_wc_max, + reg_bist_wc_min}; + + //----------------------- + assign swi_bist_wc_min = reg_bist_wc_min; + + //----------------------- + assign swi_bist_wc_max = reg_bist_wc_max; + + + + + + //--------------------------- + // BIST_DATA_ID_VALUES + // bist_di_min - Minimum Data ID Value + // bist_di_max - Maximum Data ID Value + //--------------------------- + wire [31:0] BIST_DATA_ID_VALUES_reg_read; + reg [7:0] reg_bist_di_min; + reg [7:0] reg_bist_di_max; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_bist_di_min <= 8'h20; + reg_bist_di_max <= 8'hf0; + end else if(RegAddr == 'h10 && RegWrEn) begin + reg_bist_di_min <= RegWrData[7:0]; + reg_bist_di_max <= RegWrData[15:8]; + end else begin + reg_bist_di_min <= reg_bist_di_min; + reg_bist_di_max <= reg_bist_di_max; + end + end + + assign BIST_DATA_ID_VALUES_reg_read = {16'h0, + reg_bist_di_max, + reg_bist_di_min}; + + //----------------------- + assign swi_bist_di_min = reg_bist_di_min; + + //----------------------- + assign swi_bist_di_max = reg_bist_di_max; + + + + + + //--------------------------- + // BIST_STATUS + // bist_locked - 1 - BIST RX has seen at least one start of packet and word count has not had an issue + // bist_unrecover - 1 - BIST RX has received data in such a way that the remaining data stream is not likely to be observable. + // reserved0 - + // bist_errors - Number of errors seen during this run. Saturates at all ones. + //--------------------------- + wire [31:0] BIST_STATUS_reg_read; + assign BIST_STATUS_reg_read = { bist_errors, + 14'd0, //Reserved + bist_unrecover, + bist_locked}; + + //----------------------- + //----------------------- + //----------------------- + //----------------------- + + + + + //--------------------------- + // DEBUG_BUS_CTRL + // DEBUG_BUS_CTRL_SEL - Select signal for DEBUG_BUS_CTRL + //--------------------------- + wire [31:0] DEBUG_BUS_CTRL_reg_read; + reg reg_debug_bus_ctrl_sel; + wire swi_debug_bus_ctrl_sel; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_debug_bus_ctrl_sel <= 1'h0; + end else if(RegAddr == 'h18 && RegWrEn) begin + reg_debug_bus_ctrl_sel <= RegWrData[0]; + end else begin + reg_debug_bus_ctrl_sel <= reg_debug_bus_ctrl_sel; + end + end + + assign DEBUG_BUS_CTRL_reg_read = {31'h0, + reg_debug_bus_ctrl_sel}; + + //----------------------- + assign swi_debug_bus_ctrl_sel = reg_debug_bus_ctrl_sel; + + + + + + //--------------------------- + // DEBUG_BUS_STATUS + // DEBUG_BUS_CTRL_STATUS - Status output for DEBUG_BUS_STATUS + //--------------------------- + wire [31:0] DEBUG_BUS_STATUS_reg_read; + + //Debug bus control logic + always @(*) begin + case(swi_debug_bus_ctrl_sel) + 'd0 : debug_bus_ctrl_status = {bist_errors, 14'd0, bist_unrecover, bist_locked}; + default : debug_bus_ctrl_status = 32'd0; + endcase + end + + assign DEBUG_BUS_STATUS_reg_read = { debug_bus_ctrl_status}; + + //----------------------- + + + + + //--------------------------- + // PRDATA Selection + //--------------------------- + reg [31:0] prdata_sel; + + always @(*) begin + case(RegAddr) + 'h0 : prdata_sel = SWRESET_reg_read; + 'h4 : prdata_sel = BIST_MAIN_CONTROL_reg_read; + 'h8 : prdata_sel = BIST_MODE_reg_read; + 'hc : prdata_sel = BIST_WORD_COUNT_VALUES_reg_read; + 'h10 : prdata_sel = BIST_DATA_ID_VALUES_reg_read; + 'h14 : prdata_sel = BIST_STATUS_reg_read; + 'h18 : prdata_sel = DEBUG_BUS_CTRL_reg_read; + 'h1c : prdata_sel = DEBUG_BUS_STATUS_reg_read; + + default : prdata_sel = 32'd0; + endcase + end + + assign PRDATA = prdata_sel; + + + + + //--------------------------- + // PSLVERR Detection + //--------------------------- + reg pslverr_pre; + + always @(*) begin + case(RegAddr) + 'h0 : pslverr_pre = 1'b0; + 'h4 : pslverr_pre = 1'b0; + 'h8 : pslverr_pre = 1'b0; + 'hc : pslverr_pre = 1'b0; + 'h10 : pslverr_pre = 1'b0; + 'h14 : pslverr_pre = 1'b0; + 'h18 : pslverr_pre = 1'b0; + 'h1c : pslverr_pre = 1'b0; + + default : pslverr_pre = 1'b1; + endcase + end + + assign PSLVERR = pslverr_pre; + +endmodule diff --git a/rtl/bist/slink_bist_rx.v b/rtl/bist/slink_bist_rx.v index 7268b95..dffb8b3 100644 --- a/rtl/bist/slink_bist_rx.v +++ b/rtl/bist/slink_bist_rx.v @@ -189,27 +189,28 @@ always @(*) begin case(swi_bist_mode_payload) BIST_PAYLOAD_1010 : begin - for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count_save); i = i + 1) begin + for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count/*word_count_save*/); i = i + 1) begin app_data_xor[(i*8) +: 8] = 8'haa ^ app_data[(i*8) +: 8]; end end BIST_PAYLOAD_1100 : begin - for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count_save); i = i + 1) begin + for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count/*word_count_save*/); i = i + 1) begin app_data_xor[(i*8) +: 8] = 8'hcc ^ app_data[(i*8) +: 8]; end end BIST_PAYLOAD_1111_0000 : begin - for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count_save); i = i + 1) begin + for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count/*word_count_save*/); i = i + 1) begin app_data_xor[(i*8) +: 8] = 8'hf0 ^ app_data[(i*8) +: 8]; end end BIST_PAYLOAD_COUNT : begin - for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count_save); i = i + 1) begin - app_data_xor[(i*8) +: 8] = (byte_count + i) ^ app_data[(i*8) +: 8]; + for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count/*word_count_save*/); i = i + 1) begin + //app_data_xor[(i*8) +: 8] = (byte_count + i) ^ app_data[(i*8) +: 8]; + app_data_xor[(i*8) +: 8] = i ^ app_data[(i*8) +: 8]; end end default : begin - for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count_save); i = i + 1) begin + for(int i = 0; (i < APP_DATA_BYTES) && ((i + byte_count) < word_count/*word_count_save*/); i = i + 1) begin app_data_xor[(i*8) +: 8] = 8'hd0 ^ app_data[(i*8) +: 8]; end end @@ -243,6 +244,10 @@ always @(*) begin nstate = IDLE; end endcase + + if(~bist_en_ff2 || bist_reset_ff2) begin + nstate = IDLE; + end end endmodule diff --git a/rtl/bist/slink_bist_tx.v b/rtl/bist/slink_bist_tx.v index 7b9e4a6..f9a008d 100644 --- a/rtl/bist/slink_bist_tx.v +++ b/rtl/bist/slink_bist_tx.v @@ -56,7 +56,12 @@ slink_demet_reset u_slink_demet_reset_bist_en ( .sig_in ( swi_bist_en ), .sig_out ( bist_en_ff2 )); - +wire bist_reset_ff2; +slink_demet_reset u_slink_demet_reset_bist_reset ( + .clk ( clk ), + .reset ( reset ), + .sig_in ( swi_bist_reset ), + .sig_out ( bist_reset_ff2 )); always @(posedge clk or posedge reset) begin if(reset) begin @@ -69,9 +74,9 @@ always @(posedge clk or posedge reset) begin end else begin state <= nstate; byte_count <= byte_count_in; - sop <= sop_in; - data_id <= data_id_in; - word_count <= word_count_in; + sop <= bist_reset_ff2 ? 1'b0 : sop_in; + data_id <= bist_reset_ff2 ? 8'd0 : data_id_in; + word_count <= bist_reset_ff2 ? 16'd0 : word_count_in; app_data <= app_data_in; end end @@ -214,6 +219,10 @@ always @(*) begin end endcase + + if(~bist_en_ff2 || bist_reset_ff2) begin + nstate = IDLE; + end end diff --git a/rtl/gen_slink_attr.py b/rtl/gen_slink_attr.py index 8ae791e..1fe231e 100644 --- a/rtl/gen_slink_attr.py +++ b/rtl/gen_slink_attr.py @@ -101,7 +101,24 @@ def print_header(attrs): module slink_attributes #( parameter NUM_TX_LANES_CLOG2 = 2, - parameter NUM_RX_LANES_CLOG2 = 2 + parameter NUM_RX_LANES_CLOG2 = 2, + parameter P1_TS1_TX_RESET = 16, + parameter P1_TS1_RX_RESET = 16, + parameter P1_TS2_TX_RESET = 4, + parameter P1_TS2_RX_RESET = 4, + + parameter P2_TS1_TX_RESET = 32, + parameter P2_TS1_RX_RESET = 32, + parameter P2_TS2_TX_RESET = 8, + parameter P2_TS2_RX_RESET = 8, + + parameter P3R_TS1_TX_RESET = 32, + parameter P3R_TS1_RX_RESET = 32, + parameter P3R_TS2_TX_RESET = 8, + parameter P3R_TS2_RX_RESET = 8, + parameter PX_CLK_TRAIL_RESET = 32, + + parameter SYNC_FREQ_RESET = 15 )( //Attributes """ @@ -263,20 +280,20 @@ def __init__(self, name, width, rst, ro=0, desc=""): 0x2 : SlinkAttr(name='active_txs', width=3, rst='NUM_TX_LANES_CLOG2', desc='Active TX lanes') , 0x3 : SlinkAttr(name='active_rxs', width=3, rst='NUM_RX_LANES_CLOG2', desc='Active RX lanes') , 0x8 : SlinkAttr(name='hard_reset_us',width=10, rst=100, desc='Time (in us) at which a Hard Reset Condition is detected.') , - 0x10 : SlinkAttr(name='px_clk_trail', width=8, rst=32, desc='Number of clock cycles to run the bitclk when going to a P state that doesn\'t supply the bitclk') , - 0x20 : SlinkAttr(name='p1_ts1_tx', width=16, rst=32, desc='TS1s to send if exiting from P1' ) , - 0x21 : SlinkAttr(name='p1_ts1_rx', width=16, rst=32, desc='TS1s to receive if exiting from P1') , - 0x22 : SlinkAttr(name='p1_ts2_tx', width=16, rst=4, desc='TS2s to send if exiting from P1' ) , - 0x23 : SlinkAttr(name='p1_ts2_rx', width=16, rst=4, desc='TS2s to receive if exiting from P1') , - 0x24 : SlinkAttr(name='p2_ts1_tx', width=16, rst=64, desc='TS1s to send if exiting from P2' ) , - 0x25 : SlinkAttr(name='p2_ts1_rx', width=16, rst=64, desc='TS1s to receive if exiting from P2') , - 0x26 : SlinkAttr(name='p2_ts2_tx', width=16, rst=8, desc='TS2s to send if exiting from P2' ) , - 0x27 : SlinkAttr(name='p2_ts2_rx', width=16, rst=8, desc='TS2s to receive if exiting from P2') , - 0x28 : SlinkAttr(name='p3r_ts1_tx', width=16, rst=128, desc='TS1s to send if exiting from P3 or when coming out of reset' ) , - 0x29 : SlinkAttr(name='p3r_ts1_rx', width=16, rst=128, desc='TS1s to receive if exiting from P3 or when coming out of reset') , - 0x2a : SlinkAttr(name='p3r_ts2_tx', width=16, rst=16, desc='TS2s to send if exiting from P3 or when coming out of reset' ) , - 0x2b : SlinkAttr(name='p3r_ts2_rx', width=16, rst=16, desc='TS2s to receive if exiting from P3 or when coming out of reset') , - 0x30 : SlinkAttr(name='sync_freq', width=8, rst=15, desc='How often SYNC Ordered Sets are sent during training') , + 0x10 : SlinkAttr(name='px_clk_trail', width=8, rst='PX_CLK_TRAIL_RESET', desc='Number of clock cycles to run the bitclk when going to a P state that doesn\'t supply the bitclk') , + 0x20 : SlinkAttr(name='p1_ts1_tx', width=16, rst='P1_TS1_TX_RESET', desc='TS1s to send if exiting from P1' ) , + 0x21 : SlinkAttr(name='p1_ts1_rx', width=16, rst='P1_TS1_RX_RESET', desc='TS1s to receive if exiting from P1') , + 0x22 : SlinkAttr(name='p1_ts2_tx', width=16, rst='P1_TS2_TX_RESET', desc='TS2s to send if exiting from P1' ) , + 0x23 : SlinkAttr(name='p1_ts2_rx', width=16, rst='P1_TS2_RX_RESET', desc='TS2s to receive if exiting from P1') , + 0x24 : SlinkAttr(name='p2_ts1_tx', width=16, rst='P2_TS1_TX_RESET', desc='TS1s to send if exiting from P2' ) , + 0x25 : SlinkAttr(name='p2_ts1_rx', width=16, rst='P2_TS1_RX_RESET', desc='TS1s to receive if exiting from P2') , + 0x26 : SlinkAttr(name='p2_ts2_tx', width=16, rst='P2_TS2_TX_RESET', desc='TS2s to send if exiting from P2' ) , + 0x27 : SlinkAttr(name='p2_ts2_rx', width=16, rst='P2_TS2_RX_RESET', desc='TS2s to receive if exiting from P2') , + 0x28 : SlinkAttr(name='p3r_ts1_tx', width=16, rst='P3R_TS1_TX_RESET', desc='TS1s to send if exiting from P3 or when coming out of reset' ) , + 0x29 : SlinkAttr(name='p3r_ts1_rx', width=16, rst='P3R_TS1_RX_RESET', desc='TS1s to receive if exiting from P3 or when coming out of reset') , + 0x2a : SlinkAttr(name='p3r_ts2_tx', width=16, rst='P3R_TS2_TX_RESET', desc='TS2s to send if exiting from P3 or when coming out of reset' ) , + 0x2b : SlinkAttr(name='p3r_ts2_rx', width=16, rst='P3R_TS2_RX_RESET', desc='TS2s to receive if exiting from P3 or when coming out of reset') , + 0x30 : SlinkAttr(name='sync_freq', width=8, rst='SYNC_FREQ_RESET', desc='How often SYNC Ordered Sets are sent during training') , } # Print it diff --git a/rtl/gpio/slink_gpio_serdes.v b/rtl/gpio/slink_gpio_serdes.v new file mode 100644 index 0000000..15305c9 --- /dev/null +++ b/rtl/gpio/slink_gpio_serdes.v @@ -0,0 +1,157 @@ +/** + * A generic "serdes" that uses a simple GPIO to convert the parallel data + * to a lower width (must be a power of two) + */ +module slink_gpio_serdes #( + parameter PAR_DATA_WIDTH = 8, + parameter IO_DATA_WIDTH = 1 +)( + input wire core_scan_mode, + input wire core_scan_clk, + + input wire serial_clk, //from pll/clk source in master, from pad in slave + input wire serial_reset, + + input wire clk_en, + input wire clk_idle, + output wire clk_ready, + + output wire phy_clk, + + input wire tx_en, + output wire tx_ready, + input wire [PAR_DATA_WIDTH-1:0] tx_par_data, + + input wire rx_en, + output wire rx_ready, + output reg [PAR_DATA_WIDTH-1:0] rx_par_data, + + output wire tx_ser_clk, + output wire [IO_DATA_WIDTH-1:0] tx_ser_data, + input wire [IO_DATA_WIDTH-1:0] rx_ser_data +); + + +localparam DIV_RATIO = PAR_DATA_WIDTH / IO_DATA_WIDTH; //You want this to be a power of 2 +localparam COUNT_CLOG2 = $clog2(DIV_RATIO); + +wire clk_en_ff2; +wire clk_idle_ff2; +wire serial_clk_gated; + + +wire clk_active; +reg [COUNT_CLOG2-1:0] count; +wire [COUNT_CLOG2-1:0] count_in; +wire tx_en_ff2; +wire [IO_DATA_WIDTH-1:0] tx_ser_data_array [DIV_RATIO-1:0]; + +wire rx_en_ff2; +reg [IO_DATA_WIDTH-1:0] rx_ser_data_samp; + +reg [IO_DATA_WIDTH-1:0] rx_par_data_reg [DIV_RATIO-1:0]; +wire [PAR_DATA_WIDTH-1:0] rx_par_data_in; + +slink_demet_reset u_slink_demet_reset[3:0] ( + .clk ( serial_clk ), + .reset ( serial_reset ), + .sig_in ( {tx_en, + rx_en, + clk_en, + clk_idle} ), + .sig_out ( {tx_en_ff2, + rx_en_ff2, + clk_en_ff2, + clk_idle_ff2} )); + +assign clk_ready = clk_en_ff2; + +assign clk_active = (clk_en_ff2 && ~clk_idle_ff2); + + +slink_clock_gate u_slink_clock_gate ( + .clk_in ( serial_clk ), + .reset ( serial_reset ), + .core_scan_mode ( core_scan_mode ), + .enable ( clk_active ), + .disable_clkgate ( 1'b0 ), + .clk_out ( serial_clk_gated )); + +assign tx_ser_clk = serial_clk_gated; + + +//thanks ARM! +//The clock gate latch seems to just let X prop +//when you default the clock high. This is probably +//better anyways, but I don't see where it really matters + +always @(posedge serial_clk_gated or posedge serial_reset) begin + if(serial_reset) begin + //count <= {COUNT_CLOG2{1'b0}}; + count <= {COUNT_CLOG2{1'b1}}; + end else begin + count <= count_in; + end +end + +assign phy_clk_pre = ~count[COUNT_CLOG2-1]; +//assign phy_clk_pre = count[COUNT_CLOG2-1]; + + + + +slink_clock_mux u_slink_clock_mux_phy_clk ( + .clk0 ( phy_clk_pre ), + .clk1 ( core_scan_clk ), + .sel ( core_scan_mode ), + .clk_out ( phy_clk )); + + +//assign count_in = clk_active ? count + 'd1 : 'd0; +assign count_in = clk_active ? count + 'd1 : {COUNT_CLOG2{1'b1}}; +assign tx_ready = tx_en_ff2; +assign tx_ser_data = tx_ser_data_array[count]; + +genvar index; +generate + for(index = 0; index < DIV_RATIO; index = index + 1) begin + assign tx_ser_data_array[index] = tx_par_data[((index+1)*IO_DATA_WIDTH)-1 : (index*IO_DATA_WIDTH)]; + end +endgenerate + +assign rx_ready = rx_en_ff2; + +always @(negedge serial_clk_gated or posedge serial_reset) begin + if(serial_reset) begin + rx_ser_data_samp <= {PAR_DATA_WIDTH{1'b0}}; + end else begin + rx_ser_data_samp <= ~rx_en_ff2 ? {PAR_DATA_WIDTH{1'b0}} : rx_ser_data; + end +end + +genvar rxindex; +generate + for(rxindex = 0; rxindex < DIV_RATIO; rxindex = rxindex + 1) begin + always @(posedge serial_clk_gated or posedge serial_reset) begin + if(serial_reset) begin + rx_par_data_reg[rxindex] <= {IO_DATA_WIDTH{1'b0}}; + end else begin + if(~rx_en_ff2) begin + rx_par_data_reg[rxindex] <= {IO_DATA_WIDTH{1'b0}}; + end else if(count == rxindex) begin + rx_par_data_reg[rxindex] <= rx_ser_data_samp; + end else begin + rx_par_data_reg[rxindex] <= rx_par_data_reg[rxindex]; + end + end + end + + assign rx_par_data_in[((rxindex+1)*IO_DATA_WIDTH)-1 : (rxindex*IO_DATA_WIDTH)] = rx_par_data_reg[rxindex]; + end +endgenerate + +always @(posedge phy_clk) begin + rx_par_data <= ~rx_en_ff2 ? {PAR_DATA_WIDTH{1'b0}} : rx_par_data_in; +end + +endmodule diff --git a/rtl/regs/create_regs.sh b/rtl/regs/create_regs.sh new file mode 100755 index 0000000..3faad1e --- /dev/null +++ b/rtl/regs/create_regs.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +gen_regs_py -i slink_ctrl_regs.txt -p slink -b ctrl -cm slink_clock_mux -dm slink_demet_reset +gen_regs_py -i slink_ctrl_regs.txt -p slink -b ctrl -sphinx > ../../docs/source/regs.rst +gen_regs_py -i slink_ctrl_regs.txt -p slink -b ctrl -dv +mv slink_ctrl_addr_defines.vh ../../verif/slink/tests/ +rm slink_ctrl_dv.txt + +gen_inst -t slink_ctrl_regs_top -of ../slink.v -gen_wires -wire_only diff --git a/rtl/regs/slink_ctrl_regs.txt b/rtl/regs/slink_ctrl_regs.txt new file mode 100644 index 0000000..79a8c23 --- /dev/null +++ b/rtl/regs/slink_ctrl_regs.txt @@ -0,0 +1,97 @@ +######################################## +# S-Link Registers +######################################## + +SWRESET RW + swreset 1'b1 Main reset. Must be cleared prior to operation. + swreset_mux 1'b0 0 - Use logic, 1 - Use register + +ENABLE RW + enable 1'b0 Main enable. Must be set prior to operation. Any configurations should be performed prior to enabling. + enable_mux 1'b0 0 - Use logic, 1 - Use register + +INTERRUPT_STATUS RO + ecc_corrupted 1'b0 W1C Indicates that a packet header was received with the ECC corrupted. + ecc_corrected 1'b0 W1C Indicates that a packet header was received with the ECC corrected. + crc_corrupted 1'b0 W1C Indicates that a long packet was received and the received CRC did not match the calculated CRC based on the payload. + reset_seen 1'b0 W1C Indicates a reset condition was seen + wake_seen 1'b0 W1C Indicates a wake condition was seen + in_pstate 1'b0 W1C Indicates the link has entered into a P state (only asserts on entry) + +INTERRUPT_ENABLE RW + ecc_corrupted_int_en 1'b1 Enables the ecc_corrupted interrupt + ecc_corrected_int_en 1'b1 Enables the ecc_corrected interrupt + crc_corrupted_int_en 1'b1 Enables the crc_corrupted interrupt + reset_seen_int_en 1'b1 Enables the reset_seen interrupt + wake_seen_int_en 1'b0 Enables the wake_seen interrupt + in_pstate_int_en 1'b0 Enables the in_pstate interrupt + + +PSTATE_CONTROL RW + p1_state_enter 1'b0 Set to enter P1 power state + p2_state_enter 1'b0 Set to enter P2 power state + p3_state_enter 1'b0 Set to enter P3 power state + reserved 27'd0 + link_reset 1'b0 Forces the link to the reset state for both sides of the link + link_wake 1'b0 Forces the link to wake up to P0 without a packet being available + + +ERROR_CONTROL RW + allow_ecc_corrected 1'b1 1 - ECC Corrected conditions will not block the Packet Header from going to the application layer + ecc_corrected_causes_reset 1'b0 1 - ECC Corrected will cause S-Link to reset. This should not be set if allow_ecc_corrected is set + ecc_corrupted_causes_reset 1'b1 1 - ECC Corrupted condition will cause S-Link to reset. + crc_corrupted_causes_reset 1'b0 1 - CRC Corrupted condition will cause S-Link to reset. + +COUNT_VAL_1US RW + count_val_1us 10'd38 Number of REFCLK cycles that equal 1us. + + +SHORT_PACKET_MAX RW + short_packet_max 8'h2f This setting allows you to change the window for short/long packets + +###################### +# Attribute Override +# +# Attribute overrides are meant to be used to configure S-Link prior to initial start. +# +# A user would go through updating the shadow values then forcing a +# +# It is possible that a user could update attributes during a low power mode, but this +# should be done on **both** sides of the link. i.e. you use some other side band channel +# to communicate the changes. Do this at your own risk. +###################### +SW_ATTR_ADDR_DATA RW + sw_attr_addr 16'd0 Address for software based attribute updates + sw_attr_wdata 16'd0 Data for software based attribute updates + +SW_ATTR_CONTROLS RW + sw_attr_write 1'b1 0 - Perform a read command. 1 - Perform a write command + sw_attr_local 1'b1 0 - Write/Read to far end SLink. 1 - Write/Read to local SLink + +SW_ATTR_DATA_READ RO + sw_attr_rdata 16'd0 RFIFO Shadow attribute data based on the sw_attr_addr value. *The sw_attr_data_read is actually only the link_clk, so it is advised to set the sw_attr_addr for several cycles prior to reading* + +SW_ATTR_FIFO_STATUS RO + sw_attr_send_fifo_full 1'b0 + sw_attr_send_fifo_empty 1'b0 + sw_attr_recv_fifo_full 1'b0 + sw_attr_recv_fifo_empty 1'b0 + +SW_ATTR_SHADOW_UPDATE RW + sw_attr_shadow_update 1'b0 WFIFO Write a 1 to update the current sw_attr_addr with the current sw_attr_data. If set to local, this will handle a local write, else will create a transation to the other side + +SW_ATTR_EFFECTIVE_UPDATE RW + sw_attr_effective_update 1'b0 WFIFO Write a 1 to set the shadow attribute values to the effective values. This should only be used prior to removing swreset for initial config. + + + +###################### +# S-Link Debug Status +###################### +STATE_STATUS RO + ltssm_state 5'd0 LTSSM State + reserved 3'd0 + ll_tx_state 4'd0 LL TX State + ll_rx_state 4'd0 LL RX State + deskew_state 2'd0 Deskew State + diff --git a/rtl/serdes/slink_serdes_front_end.v b/rtl/serdes/slink_serdes_front_end.v index dde96a0..79a9a6b 100644 --- a/rtl/serdes/slink_serdes_front_end.v +++ b/rtl/serdes/slink_serdes_front_end.v @@ -6,8 +6,10 @@ module slink_serdes_front_end #( parameter LTSSM_REGISTER_TXDATA = 1, parameter DESKEW_FIFO_DEPTH = 4, + parameter RETIME_FIFO_DEPTH = 0, //Attribute + parameter START_IN_ONE_LANE = 0, parameter P1_TS1_TX_RESET = 16, parameter P1_TS1_RX_RESET = 8, parameter P1_TS2_TX_RESET = 8, @@ -23,6 +25,7 @@ module slink_serdes_front_end #( parameter P3R_TS2_TX_RESET = 8, parameter P3R_TS2_RX_RESET = 8, + parameter PX_CLK_TRAIL_RESET = 32, parameter SYNC_FREQ_RESET = 15 )( @@ -83,6 +86,8 @@ module slink_serdes_front_end #( PHY_DATA_WIDTH)-1:0] ll_rx_data, output wire ll_rx_sds_recv, + output wire [4:0] ltssm_state, + // PHY output wire phy_clk_en, @@ -237,7 +242,8 @@ slink_rx_align_deskew #( //parameters .FIFO_DEPTH ( DESKEW_FIFO_DEPTH ), .NUM_LANES ( NUM_RX_LANES ), - .DATA_WIDTH ( PHY_DATA_WIDTH ) + .DATA_WIDTH ( PHY_DATA_WIDTH ), + .RETIME_FIFO_DEPTH ( RETIME_FIFO_DEPTH ) ) u_slink_rx_align_deskew ( .clk ( link_clk ), .reset ( link_clk_reset ), @@ -265,7 +271,7 @@ slink_rx_align_deskew #( .attr_update ( link_attr_shadow_update ), .attr_rd_req ( ), - .deskew_state ( deskew_state )); + .deskew_state ( )); wire [15:0] sw_attr_rdata_fe_fifo; @@ -331,8 +337,24 @@ slink_attr_ctrl #( assign sw_attr_data_read = sw_attr_local ? sw_attr_rdata_local : sw_attr_rdata_fe_fifo; slink_attributes #( - .NUM_TX_LANES_CLOG2 ( $clog2(NUM_TX_LANES) ), - .NUM_RX_LANES_CLOG2 ( $clog2(NUM_RX_LANES) ) + .NUM_TX_LANES_CLOG2 ( START_IN_ONE_LANE ? 0 : $clog2(NUM_TX_LANES) ), + .NUM_RX_LANES_CLOG2 ( START_IN_ONE_LANE ? 0 : $clog2(NUM_RX_LANES) ), + .P1_TS1_TX_RESET ( P1_TS1_TX_RESET ), + .P1_TS1_RX_RESET ( P1_TS1_RX_RESET ), + .P1_TS2_TX_RESET ( P1_TS2_TX_RESET ), + .P1_TS2_RX_RESET ( P1_TS2_RX_RESET ), + + .P2_TS1_TX_RESET ( P2_TS1_TX_RESET ), + .P2_TS1_RX_RESET ( P2_TS1_RX_RESET ), + .P2_TS2_TX_RESET ( P2_TS2_TX_RESET ), + .P2_TS2_RX_RESET ( P2_TS2_RX_RESET ), + + .P3R_TS1_TX_RESET ( P3R_TS1_TX_RESET ), + .P3R_TS1_RX_RESET ( P3R_TS1_RX_RESET ), + .P3R_TS2_TX_RESET ( P3R_TS2_TX_RESET ), + .P3R_TS2_RX_RESET ( P3R_TS2_RX_RESET ), + .PX_CLK_TRAIL_RESET ( PX_CLK_TRAIL_RESET ), + .SYNC_FREQ_RESET ( SYNC_FREQ_RESET ) ) u_slink_attributes ( .attr_max_txs ( ), .attr_max_rxs ( ), diff --git a/rtl/slink.v b/rtl/slink.v index ea060f5..c1f1625 100644 --- a/rtl/slink.v +++ b/rtl/slink.v @@ -1,13 +1,35 @@ module slink #( - parameter TRADITIONAL_SERDES_MODE = 1, parameter NUM_TX_LANES = 4, parameter NUM_RX_LANES = 4, parameter PHY_DATA_WIDTH = 8, parameter TX_APP_DATA_WIDTH = (NUM_TX_LANES * PHY_DATA_WIDTH), parameter RX_APP_DATA_WIDTH = (NUM_RX_LANES * PHY_DATA_WIDTH), parameter DESKEW_FIFO_DEPTH = 4, + parameter RETIME_FIFO_DEPTH = 0, parameter LTSSM_REGISTER_TXDATA = 1, - parameter INCLUDE_BIST = 0 + parameter INCLUDE_BIST = 0, + + //------------------------------- + //Attribute Defaults + //------------------------------- + parameter START_IN_ONE_LANE = 0, + parameter P1_TS1_TX_RESET = 16, + parameter P1_TS1_RX_RESET = 16, + parameter P1_TS2_TX_RESET = 4, + parameter P1_TS2_RX_RESET = 4, + + parameter P2_TS1_TX_RESET = 32, + parameter P2_TS1_RX_RESET = 32, + parameter P2_TS2_TX_RESET = 8, + parameter P2_TS2_RX_RESET = 8, + + parameter P3R_TS1_TX_RESET = 32, + parameter P3R_TS1_RX_RESET = 32, + parameter P3R_TS2_TX_RESET = 8, + parameter P3R_TS2_RX_RESET = 8, + parameter PX_CLK_TRAIL_RESET = 32, + + parameter SYNC_FREQ_RESET = 15 )( input wire core_scan_mode, input wire core_scan_clk, @@ -28,6 +50,9 @@ module slink #( output wire link_clk, output wire link_reset, + input wire slink_enable, + input wire por_reset, + // TX Application/Transaction Layer input wire tx_sop, input wire [7:0] tx_data_id, @@ -103,8 +128,8 @@ wire [NUM_RX_LANES-1:0] rx_clk_scan; wire [NUM_RX_LANES-1:0] rx_clk_reset; -wire swi_swreset; -wire swi_enable; +wire swi_swreset_muxed; +wire swi_enable_muxed; wire swi_ecc_corrupted_int_en; wire w1c_in_ecc_corrupted; wire w1c_out_ecc_corrupted; @@ -124,6 +149,8 @@ wire swi_p1_state_enter; wire swi_p2_state_enter; wire swi_p3_state_enter; +wire [7:0] swi_short_packet_max; + wire [2:0] attr_active_txs; wire [2:0] attr_active_rxs; @@ -143,7 +170,6 @@ wire link_hard_reset_cond; wire [4:0] ltssm_state; wire [3:0] ll_tx_state; wire [3:0] ll_rx_state; -wire [1:0] deskew_state; wire swi_allow_ecc_corrected; wire swi_ecc_corrected_causes_reset; wire swi_ecc_corrupted_causes_reset; @@ -179,7 +205,7 @@ slink_clk_control #( .apb_reset_scan ( apb_reset_scan ), .refclk ( refclk ), .phy_clk ( phy_clk ), - .main_reset ( swi_swreset ), + .main_reset ( swi_swreset_muxed ), .use_phy_clk ( use_phy_clk ), .refclk_scan ( refclk_scan ), .refclk_scan_reset ( refclk_scan_reset ), @@ -227,6 +253,7 @@ slink_ll_tx #( .clk ( link_clk ), .reset ( link_clk_reset ), .enable ( ll_enable ), + .swi_short_packet_max ( swi_short_packet_max ), .sop ( ll_tx_sop ), .data_id ( ll_tx_data_id ), .word_count ( ll_tx_word_count ), @@ -257,6 +284,7 @@ slink_ll_rx #( .clk ( link_clk ), .reset ( link_clk_reset ), .enable ( ll_enable ), + .swi_short_packet_max ( swi_short_packet_max ), .sop ( ll_rx_sop ), .data_id ( ll_rx_data_id ), .word_count ( ll_rx_word_count ), @@ -301,7 +329,7 @@ slink_demet_reset u_slink_demet_reset_wake_reset_signals[3:0] ( swi_link_reset_link_clk, slink_gpio_reset_link_clk} )); -assign link_active_req = tx_sop || slink_gpio_wake_link_clk || swi_link_wake_link_clk; +assign link_active_req = ll_tx_sop || slink_gpio_wake_link_clk || swi_link_wake_link_clk; assign link_reset_req_local = ll_rx_link_reset_condition || swi_link_reset_link_clk; assign link_reset_req = link_reset_req_local || slink_gpio_reset_link_clk; @@ -356,92 +384,92 @@ assign interrupt = (w1c_out_ecc_corrupted && swi_ecc_corrupted_int_en) || generate - if(TRADITIONAL_SERDES_MODE==1) begin : gen_traditional_serdes - slink_serdes_front_end #( - .PHY_DATA_WIDTH ( PHY_DATA_WIDTH ), - .NUM_TX_LANES ( NUM_TX_LANES ), - .NUM_RX_LANES ( NUM_RX_LANES ), - .LTSSM_REGISTER_TXDATA ( LTSSM_REGISTER_TXDATA ), - .DESKEW_FIFO_DEPTH ( DESKEW_FIFO_DEPTH ), - - - .P1_TS1_TX_RESET ( 16 ), - .P1_TS1_RX_RESET ( 8 ), - .P1_TS2_TX_RESET ( 8 ), - .P1_TS2_RX_RESET ( 8 ), - - .P2_TS1_TX_RESET ( 32 ), - .P2_TS1_RX_RESET ( 16 ), - .P2_TS2_TX_RESET ( 8 ), - .P2_TS2_RX_RESET ( 8 ), - - .P3R_TS1_TX_RESET ( 32 ), - .P3R_TS1_RX_RESET ( 16 ), - .P3R_TS2_TX_RESET ( 8 ), - .P3R_TS2_RX_RESET ( 8 ), - .SYNC_FREQ_RESET ( 15 ) - ) u_slink_serdes_front_end ( - .link_clk ( link_clk ), - .link_clk_reset ( link_clk_reset ), - .refclk ( refclk_scan ), - .refclk_reset ( refclk_scan_reset ), - .apb_clk ( apb_clk_scan ), - .apb_reset ( apb_reset_scan ), - .enable ( swi_enable ), - .use_phy_clk ( use_phy_clk ), - .link_p1_req ( link_p1_req ), - .link_p2_req ( link_p2_req ), - .link_p3_req ( link_p3_req ), - .in_px_state ( in_px_state ), - .link_active_req ( link_active_req ), - .ltssm_link_wake_n ( ltssm_link_wake_n ), - .link_reset_req ( link_reset_req ), - .link_reset_req_local ( link_reset_req_local ), - .ltssm_link_reset_n ( ltssm_link_reset_n ), - .in_reset_state ( in_reset_state ), - .swi_count_val_1us ( swi_count_val_1us ), - .sw_attr_addr ( swi_sw_attr_addr ), - .sw_attr_wdata ( swi_sw_attr_wdata ), - .sw_attr_write ( swi_sw_attr_write ), - .sw_attr_local ( swi_sw_attr_local ), - .sw_attr_data_read ( rfifo_sw_attr_rdata ), - .sw_attr_data_read_rinc ( rfifo_rinc_sw_attr_rdata ), - .sw_attr_send_fifo_full ( sw_attr_send_fifo_full ), - .sw_attr_send_fifo_empty ( sw_attr_send_fifo_empty ), - .sw_attr_recv_fifo_full ( sw_attr_recv_fifo_full ), - .sw_attr_recv_fifo_empty ( sw_attr_recv_fifo_empty ), - .sw_attr_shadow_update ( wfifo_sw_attr_shadow_update ), - .sw_attr_shadow_update_winc ( wfifo_winc_sw_attr_shadow_update ), - .sw_attr_effective_update ( wfifo_sw_attr_effective_update ), - .sw_attr_effective_update_winc ( wfifo_winc_sw_attr_effective_update ), - .attr_active_txs ( attr_active_txs ), - .attr_active_rxs ( attr_active_rxs ), - .ll_enable ( ll_enable ), - .ll_tx_valid ( ll_tx_valid ), - .ll_tx_idle ( ll_tx_idle ), - .ll_tx_data ( ll_tx_data ), - .ll_tx_sds_sent ( ll_tx_sds_sent ), - .ll_rx_valid ( ll_rx_valid_adv ), - .ll_rx_data ( ll_rx_data ), - .ll_rx_sds_recv ( ll_rx_sds_recv ), - .phy_clk_en ( phy_clk_en ), - .phy_clk_idle ( phy_clk_idle ), - .phy_clk_ready ( phy_clk_ready ), - .phy_tx_en ( phy_tx_en ), - .phy_tx_ready ( phy_tx_ready ), - .phy_tx_dirdy ( phy_tx_dirdy ), - .phy_tx_data ( phy_tx_data ), - .phy_rx_en ( phy_rx_en ), - .phy_rx_clk ( rx_clk_scan ), - .phy_rx_clk_reset ( rx_clk_reset ), - .phy_rx_ready ( phy_rx_ready ), - .phy_rx_valid ( phy_rx_valid ), - .phy_rx_dordy ( phy_rx_dordy ), - .phy_rx_align ( phy_rx_align ), - .phy_rx_data ( phy_rx_data )); - end else begin - - end + slink_serdes_front_end #( + .PHY_DATA_WIDTH ( PHY_DATA_WIDTH ), + .NUM_TX_LANES ( NUM_TX_LANES ), + .NUM_RX_LANES ( NUM_RX_LANES ), + .LTSSM_REGISTER_TXDATA ( LTSSM_REGISTER_TXDATA ), + .DESKEW_FIFO_DEPTH ( DESKEW_FIFO_DEPTH ), + .RETIME_FIFO_DEPTH ( RETIME_FIFO_DEPTH ), + + + .START_IN_ONE_LANE ( START_IN_ONE_LANE ), + .P1_TS1_TX_RESET ( P1_TS1_TX_RESET ), + .P1_TS1_RX_RESET ( P1_TS1_RX_RESET ), + .P1_TS2_TX_RESET ( P1_TS2_TX_RESET ), + .P1_TS2_RX_RESET ( P1_TS2_RX_RESET ), + + .P2_TS1_TX_RESET ( P2_TS1_TX_RESET ), + .P2_TS1_RX_RESET ( P2_TS1_RX_RESET ), + .P2_TS2_TX_RESET ( P2_TS2_TX_RESET ), + .P2_TS2_RX_RESET ( P2_TS2_RX_RESET ), + + .P3R_TS1_TX_RESET ( P3R_TS1_TX_RESET ), + .P3R_TS1_RX_RESET ( P3R_TS1_RX_RESET ), + .P3R_TS2_TX_RESET ( P3R_TS2_TX_RESET ), + .P3R_TS2_RX_RESET ( P3R_TS2_RX_RESET ), + .PX_CLK_TRAIL_RESET ( PX_CLK_TRAIL_RESET ), + .SYNC_FREQ_RESET ( SYNC_FREQ_RESET ) + ) u_slink_serdes_front_end ( + .link_clk ( link_clk ), + .link_clk_reset ( link_clk_reset ), + .refclk ( refclk_scan ), + .refclk_reset ( refclk_scan_reset ), + .apb_clk ( apb_clk_scan ), + .apb_reset ( apb_reset_scan ), + .enable ( swi_enable_muxed ), + .use_phy_clk ( use_phy_clk ), + .link_p1_req ( link_p1_req ), + .link_p2_req ( link_p2_req ), + .link_p3_req ( link_p3_req ), + .in_px_state ( in_px_state ), + .link_active_req ( link_active_req ), + .ltssm_link_wake_n ( ltssm_link_wake_n ), + .link_reset_req ( link_reset_req ), + .link_reset_req_local ( link_reset_req_local ), + .ltssm_link_reset_n ( ltssm_link_reset_n ), + .in_reset_state ( in_reset_state ), + .swi_count_val_1us ( swi_count_val_1us ), + .sw_attr_addr ( swi_sw_attr_addr ), + .sw_attr_wdata ( swi_sw_attr_wdata ), + .sw_attr_write ( swi_sw_attr_write ), + .sw_attr_local ( swi_sw_attr_local ), + .sw_attr_data_read ( rfifo_sw_attr_rdata ), + .sw_attr_data_read_rinc ( rfifo_rinc_sw_attr_rdata ), + .sw_attr_send_fifo_full ( sw_attr_send_fifo_full ), + .sw_attr_send_fifo_empty ( sw_attr_send_fifo_empty ), + .sw_attr_recv_fifo_full ( sw_attr_recv_fifo_full ), + .sw_attr_recv_fifo_empty ( sw_attr_recv_fifo_empty ), + .sw_attr_shadow_update ( wfifo_sw_attr_shadow_update ), + .sw_attr_shadow_update_winc ( wfifo_winc_sw_attr_shadow_update ), + .sw_attr_effective_update ( wfifo_sw_attr_effective_update ), + .sw_attr_effective_update_winc ( wfifo_winc_sw_attr_effective_update ), + .attr_active_txs ( attr_active_txs ), + .attr_active_rxs ( attr_active_rxs ), + .ll_enable ( ll_enable ), + .ll_tx_valid ( ll_tx_valid ), + .ll_tx_idle ( ll_tx_idle ), + .ll_tx_data ( ll_tx_data ), + .ll_tx_sds_sent ( ll_tx_sds_sent ), + .ll_rx_valid ( ll_rx_valid_adv ), + .ll_rx_data ( ll_rx_data ), + .ll_rx_sds_recv ( ll_rx_sds_recv ), + .ltssm_state ( ltssm_state ), + .phy_clk_en ( phy_clk_en ), + .phy_clk_idle ( phy_clk_idle ), + .phy_clk_ready ( phy_clk_ready ), + .phy_tx_en ( phy_tx_en ), + .phy_tx_ready ( phy_tx_ready ), + .phy_tx_dirdy ( phy_tx_dirdy ), + .phy_tx_data ( phy_tx_data ), + .phy_rx_en ( phy_rx_en ), + .phy_rx_clk ( rx_clk_scan ), + .phy_rx_clk_reset ( rx_clk_reset ), + .phy_rx_ready ( phy_rx_ready ), + .phy_rx_valid ( phy_rx_valid ), + .phy_rx_dordy ( phy_rx_dordy ), + .phy_rx_align ( phy_rx_align ), + .phy_rx_data ( phy_rx_data )); endgenerate @@ -485,8 +513,10 @@ assign apb_pready = (apb_paddr[8] == APB_CTRL) ? apb_pready_ctrl : apb_pr assign apb_pslverr = (apb_paddr[8] == APB_CTRL) ? apb_pslverr_ctrl : apb_pslverr_bist; slink_ctrl_regs_top u_slink_ctrl_regs_top ( - .swi_swreset ( swi_swreset ), - .swi_enable ( swi_enable ), + .swreset ( por_reset ), + .swi_swreset_muxed ( swi_swreset_muxed ), + .enable ( slink_enable ), + .swi_enable_muxed ( swi_enable_muxed ), .w1c_in_ecc_corrupted ( w1c_in_ecc_corrupted ), .w1c_out_ecc_corrupted ( w1c_out_ecc_corrupted ), .w1c_in_ecc_corrected ( w1c_in_ecc_corrected ), @@ -515,6 +545,7 @@ slink_ctrl_regs_top u_slink_ctrl_regs_top ( .swi_ecc_corrupted_causes_reset ( swi_ecc_corrupted_causes_reset ), .swi_crc_corrupted_causes_reset ( swi_crc_corrupted_causes_reset ), .swi_count_val_1us ( swi_count_val_1us ), + .swi_short_packet_max ( swi_short_packet_max ), .swi_sw_attr_addr ( swi_sw_attr_addr ), .swi_sw_attr_wdata ( swi_sw_attr_wdata ), .swi_sw_attr_write ( swi_sw_attr_write ), @@ -532,7 +563,7 @@ slink_ctrl_regs_top u_slink_ctrl_regs_top ( .ltssm_state ( ltssm_state ), .ll_tx_state ( ll_tx_state ), .ll_rx_state ( ll_rx_state ), - .deskew_state ( deskew_state ), + .deskew_state ( 2'd0 ), .debug_bus_ctrl_status ( ), .RegReset ( apb_reset_scan ), .RegClk ( apb_clk_scan ), @@ -597,20 +628,20 @@ generate assign ll_tx_word_count = bist_active ? bist_tx_word_count : tx_word_count; assign ll_tx_app_data = bist_active ? bist_tx_app_data : tx_app_data; assign tx_advance = bist_active ? 1'b0 : ll_tx_advance; - assign bist_tx_advance = ll_tx_advance; + assign bist_tx_advance = bist_active ? ll_tx_advance : 1'b0; assign rx_sop = bist_active ? 1'b0 : ll_rx_sop; - assign rx_data_id = ll_rx_data_id; - assign rx_word_count = ll_rx_word_count; - assign rx_app_data = ll_rx_app_data; + assign rx_data_id = bist_active ? 8'd0 : ll_rx_data_id; + assign rx_word_count = bist_active ? 16'd0: ll_rx_word_count; + assign rx_app_data = bist_active ? {RX_APP_DATA_WIDTH{1'b0}} : ll_rx_app_data; assign rx_valid = bist_active ? 1'b0 : ll_rx_valid; assign rx_crc_corrupted = bist_active ? 1'b0 : ll_rx_crc_corrupted; - assign bist_rx_sop = ll_rx_sop; - assign bist_rx_data_id = ll_rx_data_id; - assign bist_rx_word_count = ll_rx_word_count; - assign bist_rx_app_data = ll_rx_app_data; - assign bist_rx_valid = ll_rx_valid; + assign bist_rx_sop = bist_active ? ll_rx_sop : 1'b0; + assign bist_rx_data_id = bist_active ? ll_rx_data_id : 8'd0; + assign bist_rx_word_count = bist_active ? ll_rx_word_count : 16'd0; + assign bist_rx_app_data = bist_active ? ll_rx_app_data : {RX_APP_DATA_WIDTH{1'b0}}; + assign bist_rx_valid = bist_active ? ll_rx_valid : 1'b0; end else begin : bist_tieoff @@ -629,7 +660,7 @@ generate assign apb_prdata_bist = 32'd0; assign apb_pready_bist = 1'b1; - assign apb_pslverr_bist = 1'b1; //force a slave error if you try to read it + assign apb_pslverr_bist = apb_psel_bist && apb_penable_bist; //force an error end endgenerate diff --git a/rtl/slink_attributes.v b/rtl/slink_attributes.v index 978ca18..15498e7 100644 --- a/rtl/slink_attributes.v +++ b/rtl/slink_attributes.v @@ -87,7 +87,24 @@ endmodule module slink_attributes #( parameter NUM_TX_LANES_CLOG2 = 2, - parameter NUM_RX_LANES_CLOG2 = 2 + parameter NUM_RX_LANES_CLOG2 = 2, + parameter P1_TS1_TX_RESET = 16, + parameter P1_TS1_RX_RESET = 16, + parameter P1_TS2_TX_RESET = 4, + parameter P1_TS2_RX_RESET = 4, + + parameter P2_TS1_TX_RESET = 32, + parameter P2_TS1_RX_RESET = 32, + parameter P2_TS2_TX_RESET = 8, + parameter P2_TS2_RX_RESET = 8, + + parameter P3R_TS1_TX_RESET = 32, + parameter P3R_TS1_RX_RESET = 32, + parameter P3R_TS2_TX_RESET = 8, + parameter P3R_TS2_RX_RESET = 8, + parameter PX_CLK_TRAIL_RESET = 32, + + parameter SYNC_FREQ_RESET = 15 )( //Attributes output wire [2:0] attr_max_txs, @@ -289,7 +306,7 @@ slink_attribute_base #( .ADDR ( 'h10 ), .NAME ( "px_clk_trail" ), .WIDTH ( 8 ), - .RESET_VAL ( 32 ), + .RESET_VAL ( PX_CLK_TRAIL_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_px_clk_trail ( .clk ( clk ), @@ -319,7 +336,7 @@ slink_attribute_base #( .ADDR ( 'h20 ), .NAME ( "p1_ts1_tx" ), .WIDTH ( 16 ), - .RESET_VAL ( 32 ), + .RESET_VAL ( P1_TS1_TX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p1_ts1_tx ( .clk ( clk ), @@ -349,7 +366,7 @@ slink_attribute_base #( .ADDR ( 'h21 ), .NAME ( "p1_ts1_rx" ), .WIDTH ( 16 ), - .RESET_VAL ( 32 ), + .RESET_VAL ( P1_TS1_RX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p1_ts1_rx ( .clk ( clk ), @@ -379,7 +396,7 @@ slink_attribute_base #( .ADDR ( 'h22 ), .NAME ( "p1_ts2_tx" ), .WIDTH ( 16 ), - .RESET_VAL ( 4 ), + .RESET_VAL ( P1_TS2_TX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p1_ts2_tx ( .clk ( clk ), @@ -409,7 +426,7 @@ slink_attribute_base #( .ADDR ( 'h23 ), .NAME ( "p1_ts2_rx" ), .WIDTH ( 16 ), - .RESET_VAL ( 4 ), + .RESET_VAL ( P1_TS2_RX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p1_ts2_rx ( .clk ( clk ), @@ -439,7 +456,7 @@ slink_attribute_base #( .ADDR ( 'h24 ), .NAME ( "p2_ts1_tx" ), .WIDTH ( 16 ), - .RESET_VAL ( 64 ), + .RESET_VAL ( P2_TS1_TX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p2_ts1_tx ( .clk ( clk ), @@ -469,7 +486,7 @@ slink_attribute_base #( .ADDR ( 'h25 ), .NAME ( "p2_ts1_rx" ), .WIDTH ( 16 ), - .RESET_VAL ( 64 ), + .RESET_VAL ( P2_TS1_RX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p2_ts1_rx ( .clk ( clk ), @@ -499,7 +516,7 @@ slink_attribute_base #( .ADDR ( 'h26 ), .NAME ( "p2_ts2_tx" ), .WIDTH ( 16 ), - .RESET_VAL ( 8 ), + .RESET_VAL ( P2_TS2_TX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p2_ts2_tx ( .clk ( clk ), @@ -529,7 +546,7 @@ slink_attribute_base #( .ADDR ( 'h27 ), .NAME ( "p2_ts2_rx" ), .WIDTH ( 16 ), - .RESET_VAL ( 8 ), + .RESET_VAL ( P2_TS2_RX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p2_ts2_rx ( .clk ( clk ), @@ -559,7 +576,7 @@ slink_attribute_base #( .ADDR ( 'h28 ), .NAME ( "p3r_ts1_tx" ), .WIDTH ( 16 ), - .RESET_VAL ( 128 ), + .RESET_VAL ( P3R_TS1_TX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p3r_ts1_tx ( .clk ( clk ), @@ -589,7 +606,7 @@ slink_attribute_base #( .ADDR ( 'h29 ), .NAME ( "p3r_ts1_rx" ), .WIDTH ( 16 ), - .RESET_VAL ( 128 ), + .RESET_VAL ( P3R_TS1_RX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p3r_ts1_rx ( .clk ( clk ), @@ -619,7 +636,7 @@ slink_attribute_base #( .ADDR ( 'h2a ), .NAME ( "p3r_ts2_tx" ), .WIDTH ( 16 ), - .RESET_VAL ( 16 ), + .RESET_VAL ( P3R_TS2_TX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p3r_ts2_tx ( .clk ( clk ), @@ -649,7 +666,7 @@ slink_attribute_base #( .ADDR ( 'h2b ), .NAME ( "p3r_ts2_rx" ), .WIDTH ( 16 ), - .RESET_VAL ( 16 ), + .RESET_VAL ( P3R_TS2_RX_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_p3r_ts2_rx ( .clk ( clk ), @@ -679,7 +696,7 @@ slink_attribute_base #( .ADDR ( 'h30 ), .NAME ( "sync_freq" ), .WIDTH ( 8 ), - .RESET_VAL ( 15 ), + .RESET_VAL ( SYNC_FREQ_RESET ), .IS_RO ( 0 ) ) u_slink_attribute_base_sync_freq ( .clk ( clk ), diff --git a/rtl/slink_crc_calc.v b/rtl/slink_crc_calc.v index 92dcc12..16a5733 100644 --- a/rtl/slink_crc_calc.v +++ b/rtl/slink_crc_calc.v @@ -19,17 +19,18 @@ module slink_crc_8_16bit_compute( wire [15:0] crc_in16; wire [15:0] crc_in8; +reg [15:0] crc_in8_xfix; always @(posedge clk or posedge reset) begin if(reset) begin crc <= 16'hffff; end else begin crc <= init ? 16'hffff : - valid ? crc_in8 : crc; + valid ? crc_in8_xfix : crc; end end -assign crc_next = valid ? crc_in8 : 16'hffff; +assign crc_next = valid ? crc_in8_xfix : 16'hffff; //Can this be more optimzed? @@ -51,5 +52,16 @@ assign crc_in8[ 1] = data_in[5] ^ data_in[1] ^ crc_prev[1] ^ crc_prev[5] ^ crc_p assign crc_in8[ 0] = data_in[4] ^ data_in[0] ^ crc_prev[0] ^ crc_prev[4] ^ crc_prev[8]; +always @(*) begin + crc_in8_xfix = crc_in8; + `ifndef SYNTHESIS + for(int jj=0; jj < 16; jj++) begin + if(crc_in8[jj] === 1'bx) begin + crc_in8_xfix[jj] = 1'b0; + end + end + `endif +end + endmodule diff --git a/rtl/slink_ctrl_regs_top.v b/rtl/slink_ctrl_regs_top.v index a77f5d5..65cc1b5 100644 --- a/rtl/slink_ctrl_regs_top.v +++ b/rtl/slink_ctrl_regs_top.v @@ -1,6 +1,6 @@ //=================================================================== // -// Created by steven on August/30/2020 at 11:55:35 +// Created by sbridges on February/02/2021 at 13:47:33 // // slink_ctrl_regs_top.v // @@ -12,9 +12,11 @@ module slink_ctrl_regs_top #( parameter ADDR_WIDTH = 8 )( //SWRESET - output wire swi_swreset, + input wire swreset, + output wire swi_swreset_muxed, //ENABLE - output wire swi_enable, + input wire enable, + output wire swi_enable_muxed, //INTERRUPT_STATUS input wire w1c_in_ecc_corrupted, output wire w1c_out_ecc_corrupted, @@ -48,6 +50,8 @@ module slink_ctrl_regs_top #( output wire swi_crc_corrupted_causes_reset, //COUNT_VAL_1US output wire [9:0] swi_count_val_1us, + //SHORT_PACKET_MAX + output wire [7:0] swi_short_packet_max, //SW_ATTR_ADDR_DATA output wire [15:0] swi_sw_attr_addr, output wire [15:0] swi_sw_attr_wdata, @@ -144,32 +148,48 @@ module slink_ctrl_regs_top #( //Regs for Mux Override sel + reg reg_swreset_mux; + reg reg_enable_mux; //--------------------------- // SWRESET // swreset - Main reset. Must be cleared prior to operation. + // swreset_mux - 0 - Use logic, 1 - Use register //--------------------------- wire [31:0] SWRESET_reg_read; - reg reg_swreset; + reg reg_swreset; always @(posedge RegClk or posedge RegReset) begin if(RegReset) begin reg_swreset <= 1'h1; + reg_swreset_mux <= 1'h0; end else if(RegAddr == 'h0 && RegWrEn) begin reg_swreset <= RegWrData[0]; + reg_swreset_mux <= RegWrData[1]; end else begin reg_swreset <= reg_swreset; + reg_swreset_mux <= reg_swreset_mux; end end - assign SWRESET_reg_read = {31'h0, + assign SWRESET_reg_read = {30'h0, + reg_swreset_mux, reg_swreset}; //----------------------- - assign swi_swreset = reg_swreset; + wire swi_swreset_muxed_pre; + slink_clock_mux u_slink_clock_mux_swreset ( + .clk0 ( swreset ), + .clk1 ( reg_swreset ), + .sel ( reg_swreset_mux ), + .clk_out ( swi_swreset_muxed_pre )); + + assign swi_swreset_muxed = swi_swreset_muxed_pre; + + //----------------------- @@ -177,26 +197,40 @@ module slink_ctrl_regs_top #( //--------------------------- // ENABLE // enable - Main enable. Must be set prior to operation. Any configurations should be performed prior to enabling. + // enable_mux - 0 - Use logic, 1 - Use register //--------------------------- wire [31:0] ENABLE_reg_read; - reg reg_enable; + reg reg_enable; always @(posedge RegClk or posedge RegReset) begin if(RegReset) begin reg_enable <= 1'h0; + reg_enable_mux <= 1'h0; end else if(RegAddr == 'h4 && RegWrEn) begin reg_enable <= RegWrData[0]; + reg_enable_mux <= RegWrData[1]; end else begin reg_enable <= reg_enable; + reg_enable_mux <= reg_enable_mux; end end - assign ENABLE_reg_read = {31'h0, + assign ENABLE_reg_read = {30'h0, + reg_enable_mux, reg_enable}; //----------------------- - assign swi_enable = reg_enable; + wire swi_enable_muxed_pre; + slink_clock_mux u_slink_clock_mux_enable ( + .clk0 ( enable ), + .clk1 ( reg_enable ), + .sel ( reg_enable_mux ), + .clk_out ( swi_enable_muxed_pre )); + + assign swi_enable_muxed = swi_enable_muxed_pre; + + //----------------------- @@ -579,6 +613,33 @@ module slink_ctrl_regs_top #( + //--------------------------- + // SHORT_PACKET_MAX + // short_packet_max - This setting allows you to change the window for short/long packets + //--------------------------- + wire [31:0] SHORT_PACKET_MAX_reg_read; + reg [7:0] reg_short_packet_max; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_short_packet_max <= 8'h2f; + end else if(RegAddr == 'h1c && RegWrEn) begin + reg_short_packet_max <= RegWrData[7:0]; + end else begin + reg_short_packet_max <= reg_short_packet_max; + end + end + + assign SHORT_PACKET_MAX_reg_read = {24'h0, + reg_short_packet_max}; + + //----------------------- + assign swi_short_packet_max = reg_short_packet_max; + + + + + //--------------------------- // SW_ATTR_ADDR_DATA // sw_attr_addr - Address for software based attribute updates @@ -592,7 +653,7 @@ module slink_ctrl_regs_top #( if(RegReset) begin reg_sw_attr_addr <= 16'h0; reg_sw_attr_wdata <= 16'h0; - end else if(RegAddr == 'h1c && RegWrEn) begin + end else if(RegAddr == 'h20 && RegWrEn) begin reg_sw_attr_addr <= RegWrData[15:0]; reg_sw_attr_wdata <= RegWrData[31:16]; end else begin @@ -627,7 +688,7 @@ module slink_ctrl_regs_top #( if(RegReset) begin reg_sw_attr_write <= 1'h1; reg_sw_attr_local <= 1'h1; - end else if(RegAddr == 'h20 && RegWrEn) begin + end else if(RegAddr == 'h24 && RegWrEn) begin reg_sw_attr_write <= RegWrData[0]; reg_sw_attr_local <= RegWrData[1]; end else begin @@ -656,7 +717,7 @@ module slink_ctrl_regs_top #( //--------------------------- wire [31:0] SW_ATTR_DATA_READ_reg_read; - assign rfifo_rinc_sw_attr_rdata = (RegAddr == 'h24 && PENABLE && PSEL && ~(PWRITE || RegWrEn)); + assign rfifo_rinc_sw_attr_rdata = (RegAddr == 'h28 && PENABLE && PSEL && ~(PWRITE || RegWrEn)); assign SW_ATTR_DATA_READ_reg_read = {16'h0, rfifo_sw_attr_rdata}; @@ -693,8 +754,8 @@ module slink_ctrl_regs_top #( //--------------------------- wire [31:0] SW_ATTR_SHADOW_UPDATE_reg_read; - assign wfifo_sw_attr_shadow_update = (RegAddr == 'h2c && RegWrEn) ? RegWrData[0] : 'd0; - assign wfifo_winc_sw_attr_shadow_update = (RegAddr == 'h2c && RegWrEn); + assign wfifo_sw_attr_shadow_update = (RegAddr == 'h30 && RegWrEn) ? RegWrData[0] : 'd0; + assign wfifo_winc_sw_attr_shadow_update = (RegAddr == 'h30 && RegWrEn); assign SW_ATTR_SHADOW_UPDATE_reg_read = {31'h0, 1'd0}; //Reserved @@ -709,8 +770,8 @@ module slink_ctrl_regs_top #( //--------------------------- wire [31:0] SW_ATTR_EFFECTIVE_UPDATE_reg_read; - assign wfifo_sw_attr_effective_update = (RegAddr == 'h30 && RegWrEn) ? RegWrData[0] : 'd0; - assign wfifo_winc_sw_attr_effective_update = (RegAddr == 'h30 && RegWrEn); + assign wfifo_sw_attr_effective_update = (RegAddr == 'h34 && RegWrEn) ? RegWrData[0] : 'd0; + assign wfifo_winc_sw_attr_effective_update = (RegAddr == 'h34 && RegWrEn); assign SW_ATTR_EFFECTIVE_UPDATE_reg_read = {31'h0, 1'd0}; //Reserved @@ -749,20 +810,20 @@ module slink_ctrl_regs_top #( // DEBUG_BUS_CTRL_SEL - Select signal for DEBUG_BUS_CTRL //--------------------------- wire [31:0] DEBUG_BUS_CTRL_reg_read; - reg [1:0] reg_debug_bus_ctrl_sel; - wire [1:0] swi_debug_bus_ctrl_sel; + reg [2:0] reg_debug_bus_ctrl_sel; + wire [2:0] swi_debug_bus_ctrl_sel; always @(posedge RegClk or posedge RegReset) begin if(RegReset) begin - reg_debug_bus_ctrl_sel <= 2'h0; - end else if(RegAddr == 'h38 && RegWrEn) begin - reg_debug_bus_ctrl_sel <= RegWrData[1:0]; + reg_debug_bus_ctrl_sel <= 3'h0; + end else if(RegAddr == 'h3c && RegWrEn) begin + reg_debug_bus_ctrl_sel <= RegWrData[2:0]; end else begin reg_debug_bus_ctrl_sel <= reg_debug_bus_ctrl_sel; end end - assign DEBUG_BUS_CTRL_reg_read = {30'h0, + assign DEBUG_BUS_CTRL_reg_read = {29'h0, reg_debug_bus_ctrl_sel}; //----------------------- @@ -783,6 +844,8 @@ module slink_ctrl_regs_top #( case(swi_debug_bus_ctrl_sel) 'd0 : debug_bus_ctrl_status = {28'd0, sw_attr_recv_fifo_empty, sw_attr_recv_fifo_full, sw_attr_send_fifo_empty, sw_attr_send_fifo_full}; 'd1 : debug_bus_ctrl_status = {14'd0, deskew_state, ll_rx_state, ll_tx_state, 3'd0, ltssm_state}; + 'd2 : debug_bus_ctrl_status = {31'd0, swi_swreset_muxed}; + 'd3 : debug_bus_ctrl_status = {31'd0, swi_enable_muxed}; default : debug_bus_ctrl_status = 32'd0; endcase end @@ -808,15 +871,16 @@ module slink_ctrl_regs_top #( 'h10 : prdata_sel = PSTATE_CONTROL_reg_read; 'h14 : prdata_sel = ERROR_CONTROL_reg_read; 'h18 : prdata_sel = COUNT_VAL_1US_reg_read; - 'h1c : prdata_sel = SW_ATTR_ADDR_DATA_reg_read; - 'h20 : prdata_sel = SW_ATTR_CONTROLS_reg_read; - 'h24 : prdata_sel = SW_ATTR_DATA_READ_reg_read; - 'h28 : prdata_sel = SW_ATTR_FIFO_STATUS_reg_read; - 'h2c : prdata_sel = SW_ATTR_SHADOW_UPDATE_reg_read; - 'h30 : prdata_sel = SW_ATTR_EFFECTIVE_UPDATE_reg_read; - 'h34 : prdata_sel = STATE_STATUS_reg_read; - 'h38 : prdata_sel = DEBUG_BUS_CTRL_reg_read; - 'h3c : prdata_sel = DEBUG_BUS_STATUS_reg_read; + 'h1c : prdata_sel = SHORT_PACKET_MAX_reg_read; + 'h20 : prdata_sel = SW_ATTR_ADDR_DATA_reg_read; + 'h24 : prdata_sel = SW_ATTR_CONTROLS_reg_read; + 'h28 : prdata_sel = SW_ATTR_DATA_READ_reg_read; + 'h2c : prdata_sel = SW_ATTR_FIFO_STATUS_reg_read; + 'h30 : prdata_sel = SW_ATTR_SHADOW_UPDATE_reg_read; + 'h34 : prdata_sel = SW_ATTR_EFFECTIVE_UPDATE_reg_read; + 'h38 : prdata_sel = STATE_STATUS_reg_read; + 'h3c : prdata_sel = DEBUG_BUS_CTRL_reg_read; + 'h40 : prdata_sel = DEBUG_BUS_STATUS_reg_read; default : prdata_sel = 32'd0; endcase @@ -850,6 +914,7 @@ module slink_ctrl_regs_top #( 'h34 : pslverr_pre = 1'b0; 'h38 : pslverr_pre = 1'b0; 'h3c : pslverr_pre = 1'b0; + 'h40 : pslverr_pre = 1'b0; default : pslverr_pre = 1'b1; endcase diff --git a/rtl/slink_ll_rx.v b/rtl/slink_ll_rx.v index 7ee9fc7..f704f7d 100644 --- a/rtl/slink_ll_rx.v +++ b/rtl/slink_ll_rx.v @@ -10,6 +10,8 @@ module slink_ll_rx #( input wire reset, input wire enable, + input wire [7:0] swi_short_packet_max, + //Interface to App output reg sop, output wire [7:0] data_id, @@ -148,8 +150,8 @@ assign delim_adv = delim_count == 'd0;//delim_count_in == delim assign ll_rx_state = state; -assign short_pkt_check = link_data[7:0] <= 'h1f; -assign short_pkt_check_corrected = corrected_ph[7:0] <= 'h1f; +assign short_pkt_check = link_data[7:0] <= swi_short_packet_max; +assign short_pkt_check_corrected = corrected_ph[7:0] <= swi_short_packet_max; assign block_app_for_ecc_error = ecc_corrupted || (ecc_corrected && ~swi_allow_ecc_corrected); assign ecc_corrected_cond = ecc_corrected && swi_allow_ecc_corrected; @@ -876,6 +878,7 @@ always @(*) begin link_data[ 7: 0]}; valid_in = byte_count[APP_DATA_BYTES_CLOG2-1:0] == {{APP_DATA_BYTES_CLOG2-2{1'b1}}, 2'b00}; + //valid_in = (APP_DATA_BYTES - byte_count[APP_DATA_BYTES_CLOG2-1:0]) == 'd4; byte_count_in = byte_count + 'd4; if(byte_count_in >= word_count_reg) begin //valid_in = 1'b1; diff --git a/rtl/slink_ll_tx.v b/rtl/slink_ll_tx.v index 11abaf8..312caac 100644 --- a/rtl/slink_ll_tx.v +++ b/rtl/slink_ll_tx.v @@ -10,6 +10,8 @@ module slink_ll_tx #( input wire reset, input wire enable, + input wire [7:0] swi_short_packet_max, + //Interface to App input wire sop, input wire [7:0] data_id, @@ -61,6 +63,8 @@ reg advance_in; reg [15:0] word_count_reg, word_count_reg_in; reg [7:0] data_id_reg, data_id_reg_in; wire is_short_pkt; +reg is_short_pkt_reg; +reg is_short_pkt_reg_in; reg crc_init; @@ -88,6 +92,7 @@ always @(posedge clk or posedge reset) begin delim_count <= 'd0; app_data_saved <= {APP_DATA_SAVED_SIZE{1'b0}}; advance_prev <= 1'b0; + is_short_pkt_reg <= 1'b0; end else begin state <= nstate; link_data_reg <= link_data_reg_in; @@ -97,12 +102,41 @@ always @(posedge clk or posedge reset) begin delim_count <= delim_count_in; app_data_saved <= app_data_saved_in; advance_prev <= ~ll_tx_valid ? advance_prev : advance; //need to save this if we don't have a valid data cycle + is_short_pkt_reg <= is_short_pkt_reg_in; + end +end + +//Error injection for sims +`ifndef SYNTHESIS +reg ecc_error_injected, ecc_error_injected_in; +reg crc_error_injected, crc_error_injected_in; +int ecc_bit_error1; +int ecc_bit_error2; +int crc_bit_error; +int error_wait_count; +int error_wait_count_pa; +always @(posedge clk or posedge reset) begin + if(reset) begin + ecc_error_injected <= 0; + crc_error_injected <= 0; + end else begin + ecc_error_injected <= ecc_error_injected_in; + crc_error_injected <= crc_error_injected_in; + end +end + +initial begin + if($value$plusargs("SLINK_ERR_WAIT_COUNT=%d", error_wait_count_pa)) begin + end else begin + error_wait_count_pa = 50; //every 50 packets end end +`endif + assign ll_tx_state = state; -assign is_short_pkt = data_id <= 8'h1f; +assign is_short_pkt = data_id <= swi_short_packet_max; //Delimeter is used to force packets to start when each LANE has sent 32bits. //This combats vaious lane widths (8/16/32) without the need to have some complicated scheme. @@ -126,6 +160,13 @@ always @(*) begin app_data_saved_in = app_data_saved; crc_input = {(NUM_LANES * DATA_WIDTH){1'b0}}; link_idle = 1'b0; + is_short_pkt_reg_in = is_short_pkt_reg; + + + `ifndef SYNTHESIS + ecc_error_injected_in = ecc_error_injected; + crc_error_injected_in = crc_error_injected; + `endif case(state) //------------------------------------------- @@ -247,6 +288,7 @@ always @(*) begin word_count_reg_in = word_count; crc_init = 1'b1; packet_header_syn_in = {word_count_reg_in, data_id_reg_in}; + is_short_pkt_reg_in = is_short_pkt; case(active_lanes) ONE_LANE : begin @@ -869,14 +911,14 @@ always @(*) begin if(DATA_WIDTH==8) begin link_data_reg_in = {{(NUM_LANES-1)*(DATA_WIDTH){1'b0}}, word_count[15: 8]}; nstate = HEADER_ECC; - advance_in = is_short_pkt; + advance_in = is_short_pkt_reg; end if(DATA_WIDTH==16) begin link_data_reg_in = {{(NUM_LANES-1)*(DATA_WIDTH){1'b0}}, calculated_ecc, word_count[15: 8]}; - nstate = is_short_pkt ? IDLE : LONG_DATA; - advance_in = is_short_pkt; + nstate = is_short_pkt_reg ? IDLE : LONG_DATA; + advance_in = is_short_pkt_reg; byte_count_in = 'd0; end end @@ -885,8 +927,8 @@ always @(*) begin if(NUM_LANES >= 2) begin if(DATA_WIDTH==8) begin link_data_reg_in = {{(NUM_LANES-2)*(DATA_WIDTH){1'b0}}, calculated_ecc, word_count[15: 8]}; - nstate = is_short_pkt ? IDLE : LONG_DATA; - advance_in = is_short_pkt; + nstate = is_short_pkt_reg ? IDLE : LONG_DATA; + advance_in = is_short_pkt_reg; byte_count_in = 'd0; end end @@ -902,8 +944,9 @@ always @(*) begin if(ll_tx_valid) begin if(DATA_WIDTH==8) begin link_data_reg_in = {{(NUM_LANES-1)*(DATA_WIDTH){1'b0}}, calculated_ecc}; - nstate = is_short_pkt ? IDLE : (~(|word_count_reg) ? CRC0 : LONG_DATA); - advance_in = word_count_reg == 'd0; + nstate = is_short_pkt_reg ? IDLE : (~(|word_count_reg) ? CRC0 : LONG_DATA); + //advance_in = word_count_reg == 'd0; + advance_in = 1'b0; //done in WC1 byte_count_in = 'd0; end end @@ -1714,6 +1757,73 @@ always @(*) begin if(~enable) begin nstate = WAIT_SDS; end + + //If data is X this can cause the CRC to prop X, resulting in CRCs + //failing, so add this to force the X to something + `ifndef SYNTHESIS + for(int jj=0; jj<(NUM_LANES * DATA_WIDTH); jj++) begin + if(crc_input[jj] === 1'bx) begin + crc_input[jj] = 1'b0; + end + if(link_data_reg_in[jj] === 1'bx) begin + link_data_reg_in[jj] = 1'b0; + end + end + + //ECC injection + if($value$plusargs("SLINK_ECC_BIT_ERR1=%d", ecc_bit_error1)) begin + if(~ecc_error_injected) begin + case(ecc_bit_error1) + 0,1,2,3,4,5,6,7 : begin + case(active_lanes) + ONE_LANE : begin + if(state==IDLE && nstate==HEADER_WC0) begin + if(error_wait_count < error_wait_count_pa) begin + error_wait_count++; + end else begin + for(int jj=0; jj<8; jj++) begin + if(jj==ecc_bit_error1) begin + link_data_reg_in[jj] = ~link_data_reg_in[jj]; + ecc_error_injected_in = 1; + error_wait_count = 0; + end + end + end + end + end + endcase + end + endcase + end + end + + //ECC injection + if($value$plusargs("SLINK_CRC_BIT_ERR=%d", crc_bit_error)) begin + if(~crc_error_injected) begin + case(crc_bit_error) + 0,1,2,3,4,5,6,7 : begin + case(active_lanes) + ONE_LANE : begin + if(state==CRC0 && nstate==CRC1) begin + if(error_wait_count < error_wait_count_pa) begin + error_wait_count++; + end else begin + for(int jj=0; jj<8; jj++) begin + if(jj==crc_bit_error) begin + link_data_reg_in[jj] = ~link_data_reg_in[jj]; + crc_error_injected_in = 0; //temp + error_wait_count = 0; + end + end + end + end + end + endcase + end + endcase + end + end + `endif end diff --git a/rtl/slink_ltssm.v b/rtl/slink_ltssm.v index 7c9a998..44add69 100644 --- a/rtl/slink_ltssm.v +++ b/rtl/slink_ltssm.v @@ -37,7 +37,7 @@ module slink_ltssm #( input wire [NUM_RX_LANES-1:0] rx_ts1_seen, input wire [NUM_RX_LANES-1:0] rx_ts2_seen, input wire [NUM_RX_LANES-1:0] rx_sds_seen, - output wire sds_sent, + output reg sds_sent, output reg deskew_enable, @@ -118,33 +118,7 @@ localparam IDLE = 'd0, PX_START_ST = 'd18, ATTR_ST = 'd19; -`ifdef SIMULATION -reg [8*40:1] state_name; -always @(*) begin - case(state) - IDLE : state_name = "IDLE"; - WAIT_CLK : state_name = "WAIT_CLK"; - SWITCH : state_name = "SWITCH"; - P0_TS1 : state_name = "P0_TS1"; - P0_TS2 : state_name = "P0_TS2"; - P0_SDS : state_name = "P0_SDS"; - P0 : state_name = "P0"; - P0_EXIT : state_name = "P0_EXIT"; - P1 : state_name = "P1"; - P1_EXIT : state_name = "P1_EXIT"; - P0_P2_CLK_TRAIL : state_name = "P0_P2_CLK_TRAIL"; - P2 : state_name = "P2"; - P2_EXIT : state_name = "P2_EXIT"; - P0_P3_CLK_TRAIL : state_name = "P0_P3_CLK_TRAIL"; - P3 : state_name = "P3"; - RESET_ENTER : state_name = "RESET_ENTER"; - RESET_ST : state_name = "RESET_ST"; - PX_REQ_ST : state_name = "PX_REQ_ST"; - PX_START_ST : state_name = "PX_START_ST"; - ATTR_ST : state_name = "ATTR_ST"; - endcase -end -`endif + reg [4:0] state, nstate; @@ -198,6 +172,7 @@ reg ll_enable_in; reg link_px_req_recv, link_px_req_recv_in; reg link_px_start_recv, link_px_start_recv_in; +reg [2:0] link_px_req_reg, link_px_req_reg_in; slink_demet_reset u_slink_demet_reset_enable ( @@ -278,6 +253,7 @@ always @(posedge clk or posedge reset) begin ll_enable <= 1'b0; link_px_req_recv <= 1'b0; link_px_start_recv <= 1'b0; + link_px_req_reg <= 3'd0; end else begin state <= nstate; use_phy_clk <= use_phy_clk_in; @@ -305,6 +281,7 @@ always @(posedge clk or posedge reset) begin ll_enable <= ll_enable_in; link_px_req_recv <= link_px_req_recv_in; link_px_start_recv <= link_px_start_recv_in; + link_px_req_reg <= link_px_req_reg_in; end end @@ -392,6 +369,8 @@ always @(*) begin attr_sent = 1'b0; link_px_req_recv_in = 1'b0; link_px_start_recv_in = 1'b0; + sds_sent = 1'b0; + link_px_req_reg_in = link_px_req_reg; case(state) //-------------------------------------- @@ -566,6 +545,7 @@ always @(*) begin end if(byte_count_end) begin + sds_sent = 1'b1; nstate = P0; end end @@ -581,7 +561,8 @@ always @(*) begin if(byte_count_end) begin if(attr_ready && ll_tx_idle) begin nstate = ATTR_ST; - end else if((link_p3_req || link_p2_req || link_p1_req) && ll_tx_idle) begin + end else if(((link_p3_req || link_p2_req || link_p1_req) && ll_tx_idle) && ~link_active_req) begin + link_px_req_reg_in = {link_p3_req, link_p2_req, link_p1_req}; //capture now as it can deassert later nstate = PX_REQ_ST; end end @@ -665,18 +646,18 @@ always @(*) begin case(byte_count) 'd0 : begin if(DATA_WIDTH==8) begin - if(link_p3_req) begin + if(link_px_req_reg[2]) begin ltssm_lane_data = P3_REQ_B0; - end else if(link_p2_req) begin + end else if(link_px_req_reg[1]) begin ltssm_lane_data = P2_REQ_B0; end else begin ltssm_lane_data = P1_REQ_B0; end end if(DATA_WIDTH==16) begin - if(link_p3_req) begin + if(link_px_req_reg[2]) begin ltssm_lane_data = {PX_FILLER, P3_REQ_B0}; - end else if(link_p2_req) begin + end else if(link_px_req_reg[1]) begin ltssm_lane_data = {PX_FILLER, P2_REQ_B0}; end else begin ltssm_lane_data = {PX_FILLER, P1_REQ_B0}; @@ -695,8 +676,8 @@ always @(*) begin endcase if(byte_count_end && link_px_req_recv_in) begin - px_exit_state_in = link_p3_req ? 'd3 : - link_p2_req ? 'd2 : 'd1; + px_exit_state_in = link_px_req_reg[2] ? 'd3 : + link_px_req_reg[1] ? 'd2 : 'd1; nstate = PX_START_ST; end end @@ -768,6 +749,7 @@ always @(*) begin if(all_tx_ready && all_rx_ready) begin rx_sds_seen_reg_in = 1'b0; phy_rx_align_reg_in = 1'b1; + sending_sync_in = 1'b1; //start with SYNC count_in = 'd0; nstate = P0_TS1; end @@ -871,7 +853,7 @@ end assign phy_rx_align = {NUM_RX_LANES{phy_rx_align_reg}}; -assign sds_sent = (state == P0_SDS) && (nstate == P0); +//assign sds_sent = (state == P0_SDS) && (nstate == P0); @@ -988,6 +970,35 @@ end assign link_hard_reset_cond = hard_reset_cond_ff2 && ~hard_reset_cond_ff3; + +`ifdef SIMULATION +reg [8*40:1] state_name; +always @(*) begin + case(state) + IDLE : state_name = "IDLE"; + WAIT_CLK : state_name = "WAIT_CLK"; + SWITCH : state_name = "SWITCH"; + P0_TS1 : state_name = "P0_TS1"; + P0_TS2 : state_name = "P0_TS2"; + P0_SDS : state_name = "P0_SDS"; + P0 : state_name = "P0"; + P0_EXIT : state_name = "P0_EXIT"; + P1 : state_name = "P1"; + P1_EXIT : state_name = "P1_EXIT"; + P0_P2_CLK_TRAIL : state_name = "P0_P2_CLK_TRAIL"; + P2 : state_name = "P2"; + P2_EXIT : state_name = "P2_EXIT"; + P0_P3_CLK_TRAIL : state_name = "P0_P3_CLK_TRAIL"; + P3 : state_name = "P3"; + RESET_ENTER : state_name = "RESET_ENTER"; + RESET_ST : state_name = "RESET_ST"; + PX_REQ_ST : state_name = "PX_REQ_ST"; + PX_START_ST : state_name = "PX_START_ST"; + ATTR_ST : state_name = "ATTR_ST"; + endcase +end +`endif + endmodule diff --git a/rtl/slink_rx_align_deskew.v b/rtl/slink_rx_align_deskew.v index e9bec0d..fd079b3 100644 --- a/rtl/slink_rx_align_deskew.v +++ b/rtl/slink_rx_align_deskew.v @@ -99,7 +99,6 @@ genvar laneindex; generate for(laneindex = 0; laneindex < NUM_LANES; laneindex = laneindex + 1) begin : gen_block_align - wire enable_local; wire blockalign_local; wire lane_is_active; @@ -137,45 +136,54 @@ generate .locked ( locked[laneindex] )); - wire rempty; - - //NEED TO SEE HOW WE CLEAR THIS FIFO AFTER INACTIVE - assign rx_locked_retime[laneindex] = ~rempty; + if(RETIME_FIFO_DEPTH > 0) begin : gen_retime_fifo - slink_fifo_top #( - //parameters - .DATA_SIZE ( DATA_WIDTH + 2 + 1 + 1 ), //DATA_WIDTH + SyncHeader + DataValid + Startblock - .ADDR_SIZE ( RETIME_FIFO_DEPTH ) - ) u_retime_fifo ( - .wclk ( rxclk[laneindex] ), - .wreset ( rxclk_reset[laneindex] ), - .winc ( locked[laneindex] ), //do we need other gates? - - .rclk ( clk ), - .rreset ( reset ), - .rinc ( ~rempty ), //need anything else? - - .wdata ( {rx_datavalid[laneindex], - rx_startblock[laneindex], - rx_syncheader[((laneindex+1)*2)-1:laneindex*2], - rx_data_aligned[((laneindex+1)*DATA_WIDTH)-1:laneindex*DATA_WIDTH]} ), - .rdata ( {rx_datavalid_retime[laneindex], - rx_startblock_retime[laneindex], - rx_syncheader_retime[((laneindex+1)*2)-1:laneindex*2], - rx_data_aligned_retime[((laneindex+1)*DATA_WIDTH)-1:laneindex*DATA_WIDTH]} ), - .wfull ( ), - .rempty ( rempty ), - .rbin_ptr ( ), - .rdiff ( ), - .wbin_ptr ( ), - .wdiff ( ), - .swi_almost_empty ( {{RETIME_FIFO_DEPTH-1{1'b0}}, 1'b1}), - .swi_almost_full ( {{RETIME_FIFO_DEPTH-1{1'b1}}, 1'b0}), - .half_full ( ), - .almost_empty ( ), - .almost_full ( )); + wire rempty; + assign rx_locked_retime[laneindex] = ~rempty; + slink_fifo_top #( + //parameters + .DATA_SIZE ( DATA_WIDTH + 2 + 1 + 1 ), //DATA_WIDTH + SyncHeader + DataValid + Startblock + .ADDR_SIZE ( RETIME_FIFO_DEPTH ) + ) u_retime_fifo ( + .wclk ( rxclk[laneindex] ), + .wreset ( rxclk_reset[laneindex] ), + .winc ( locked[laneindex] ), //do we need other gates? + + .rclk ( clk ), + .rreset ( reset ), + .rinc ( ~rempty ), //need anything else? + + .wdata ( {rx_datavalid[laneindex], + rx_startblock[laneindex], + rx_syncheader[((laneindex+1)*2)-1:laneindex*2], + rx_data_aligned[((laneindex+1)*DATA_WIDTH)-1:laneindex*DATA_WIDTH]} ), + .rdata ( {rx_datavalid_retime[laneindex], + rx_startblock_retime[laneindex], + rx_syncheader_retime[((laneindex+1)*2)-1:laneindex*2], + rx_data_aligned_retime[((laneindex+1)*DATA_WIDTH)-1:laneindex*DATA_WIDTH]} ), + .wfull ( ), + .rempty ( rempty ), + .rbin_ptr ( ), + .rdiff ( ), + .wbin_ptr ( ), + .wdiff ( ), + .swi_almost_empty ( {{RETIME_FIFO_DEPTH-1{1'b0}}, 1'b1}), + .swi_almost_full ( {{RETIME_FIFO_DEPTH-1{1'b1}}, 1'b0}), + .half_full ( ), + .almost_empty ( ), + .almost_full ( )); + + end else begin : gen_no_retime_fifo + + assign rx_locked_retime[laneindex] = locked[laneindex]; + assign rx_datavalid_retime[laneindex] = rx_datavalid[laneindex]; + assign rx_startblock_retime[laneindex] = rx_startblock[laneindex]; + assign rx_syncheader_retime[((laneindex+1)*2)-1:laneindex*2] = rx_syncheader[((laneindex+1)*2)-1:laneindex*2]; + assign rx_data_aligned_retime[((laneindex+1)*DATA_WIDTH)-1:laneindex*DATA_WIDTH] = rx_data_aligned[((laneindex+1)*DATA_WIDTH)-1:laneindex*DATA_WIDTH]; + + end end endgenerate diff --git a/rtl/slink_rx_blockalign_128b13xb.v b/rtl/slink_rx_blockalign_128b13xb.v index 2bc056d..477e95b 100644 --- a/rtl/slink_rx_blockalign_128b13xb.v +++ b/rtl/slink_rx_blockalign_128b13xb.v @@ -256,54 +256,54 @@ always @(*) begin if(DATA_WIDTH == 32) begin aligned_data_index_check_valid = 1'b1; case({enable, aligned_data_index_check}) - 'h0_0000_0000 : begin + 33'h0_0000_0000 : begin aligned_data_index_in = 'd0; aligned_data_index_check_valid = 1'b0; end - 'h1_0000_0000 : begin + 33'h1_0000_0000 : begin aligned_data_index_in = aligned_data_index; aligned_data_index_check_valid = 1'b0; end - 'h1_0000_0001 : aligned_data_index_in = 'd0; - 'h1_0000_0002 : aligned_data_index_in = 'd1; - 'h1_0000_0004 : aligned_data_index_in = 'd2; - 'h1_0000_0008 : aligned_data_index_in = 'd3; - - 'h1_0000_0010 : aligned_data_index_in = 'd4; - 'h1_0000_0020 : aligned_data_index_in = 'd5; - 'h1_0000_0040 : aligned_data_index_in = 'd6; - 'h1_0000_0080 : aligned_data_index_in = 'd7; - - 'h1_0000_0100 : aligned_data_index_in = 'd8; - 'h1_0000_0200 : aligned_data_index_in = 'd9; - 'h1_0000_0400 : aligned_data_index_in = 'd10; - 'h1_0000_0800 : aligned_data_index_in = 'd11; - - 'h1_0000_1000 : aligned_data_index_in = 'd12; - 'h1_0000_2000 : aligned_data_index_in = 'd13; - 'h1_0000_4000 : aligned_data_index_in = 'd14; - 'h1_0000_8000 : aligned_data_index_in = 'd15; - - 'h1_0001_0000 : aligned_data_index_in = 'd16; - 'h1_0002_0000 : aligned_data_index_in = 'd17; - 'h1_0004_0000 : aligned_data_index_in = 'd18; - 'h1_0008_0000 : aligned_data_index_in = 'd19; - - 'h1_0010_0000 : aligned_data_index_in = 'd20; - 'h1_0020_0000 : aligned_data_index_in = 'd21; - 'h1_0040_0000 : aligned_data_index_in = 'd22; - 'h1_0080_0000 : aligned_data_index_in = 'd23; - - 'h1_0100_0000 : aligned_data_index_in = 'd24; - 'h1_0200_0000 : aligned_data_index_in = 'd25; - 'h1_0400_0000 : aligned_data_index_in = 'd26; - 'h1_0800_0000 : aligned_data_index_in = 'd27; - - 'h1_1000_0000 : aligned_data_index_in = 'd28; - 'h1_2000_0000 : aligned_data_index_in = 'd29; - 'h1_4000_0000 : aligned_data_index_in = 'd30; - 'h1_8000_0000 : aligned_data_index_in = 'd31; + 33'h1_0000_0001 : aligned_data_index_in = 'd0; + 33'h1_0000_0002 : aligned_data_index_in = 'd1; + 33'h1_0000_0004 : aligned_data_index_in = 'd2; + 33'h1_0000_0008 : aligned_data_index_in = 'd3; + + 33'h1_0000_0010 : aligned_data_index_in = 'd4; + 33'h1_0000_0020 : aligned_data_index_in = 'd5; + 33'h1_0000_0040 : aligned_data_index_in = 'd6; + 33'h1_0000_0080 : aligned_data_index_in = 'd7; + + 33'h1_0000_0100 : aligned_data_index_in = 'd8; + 33'h1_0000_0200 : aligned_data_index_in = 'd9; + 33'h1_0000_0400 : aligned_data_index_in = 'd10; + 33'h1_0000_0800 : aligned_data_index_in = 'd11; + + 33'h1_0000_1000 : aligned_data_index_in = 'd12; + 33'h1_0000_2000 : aligned_data_index_in = 'd13; + 33'h1_0000_4000 : aligned_data_index_in = 'd14; + 33'h1_0000_8000 : aligned_data_index_in = 'd15; + + 33'h1_0001_0000 : aligned_data_index_in = 'd16; + 33'h1_0002_0000 : aligned_data_index_in = 'd17; + 33'h1_0004_0000 : aligned_data_index_in = 'd18; + 33'h1_0008_0000 : aligned_data_index_in = 'd19; + + 33'h1_0010_0000 : aligned_data_index_in = 'd20; + 33'h1_0020_0000 : aligned_data_index_in = 'd21; + 33'h1_0040_0000 : aligned_data_index_in = 'd22; + 33'h1_0080_0000 : aligned_data_index_in = 'd23; + + 33'h1_0100_0000 : aligned_data_index_in = 'd24; + 33'h1_0200_0000 : aligned_data_index_in = 'd25; + 33'h1_0400_0000 : aligned_data_index_in = 'd26; + 33'h1_0800_0000 : aligned_data_index_in = 'd27; + + 33'h1_1000_0000 : aligned_data_index_in = 'd28; + 33'h1_2000_0000 : aligned_data_index_in = 'd29; + 33'h1_4000_0000 : aligned_data_index_in = 'd30; + 33'h1_8000_0000 : aligned_data_index_in = 'd31; default : begin aligned_data_index_in = 'd0; diff --git a/rtl/slink_rx_deskew.v b/rtl/slink_rx_deskew.v index e7edb13..184e59f 100644 --- a/rtl/slink_rx_deskew.v +++ b/rtl/slink_rx_deskew.v @@ -81,7 +81,7 @@ generate always @(posedge clk or posedge reset) begin if(reset) begin data_fifo[laneindex][fifoindex] <= 'd0; - fifo_ptr[laneindex] <= 'd0; + //fifo_ptr[laneindex] <= 'd0; end else begin if(fifoindex == 0) begin data_fifo[laneindex][fifoindex] <= lane_active[laneindex] && enable && rx_locked[laneindex] ? {rx_data_valid_in[laneindex], @@ -92,13 +92,24 @@ generate data_fifo[laneindex][fifoindex] <= lane_active[laneindex] && enable && rx_locked[laneindex] ? data_fifo[laneindex][fifoindex-1] : 'd0; end - fifo_ptr[laneindex] <= (state == IDLE) ? {FIFO_CLOG2+1{1'b0}} : - (state == TRAIN) ? fifo_ptr_in[laneindex] : fifo_ptr[laneindex]; + //fifo_ptr[laneindex] <= (state == IDLE) ? {FIFO_CLOG2+1{1'b0}} : + // (state == TRAIN) ? fifo_ptr_in[laneindex] : fifo_ptr[laneindex]; end end end + + always @(posedge clk or posedge reset) begin + if(reset) begin + fifo_ptr[laneindex] <= 'd0; + end else begin + fifo_ptr[laneindex] <= (state == IDLE) ? {FIFO_CLOG2+1{1'b0}} : + (state == TRAIN) ? fifo_ptr_in[laneindex] : fifo_ptr[laneindex]; + end + end + + //Make this up to 16 entries? //Figure out a way to incorporate in the generate loop always@(*) begin diff --git a/rtl/stacks/regs/create_regs.sh b/rtl/stacks/regs/create_regs.sh new file mode 100755 index 0000000..0500a6e --- /dev/null +++ b/rtl/stacks/regs/create_regs.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +gen_regs_py -i slink_apb_axi_regs.txt -p slink -b apb_axi -cm slink_clock_mux -dm slink_demet_reset +#gen_regs_py -i slink_ctrl_regs.txt -p slink -b ctrl -sphinx > ../../docs/source/regs.rst +#gen_regs_py -i slink_ctrl_regs.txt -p slink -b ctrl -dv +#mv slink_ctrl_addr_defines.vh ../../verif/slink/tests/ +#rm slink_ctrl_dv.txt + +gen_inst -t slink_apb_axi_regs_top -of ../slink_apb_axi_gpio_top.v -gen_wires -wire_only diff --git a/rtl/stacks/regs/slink_apb_axi_regs.txt b/rtl/stacks/regs/slink_apb_axi_regs.txt new file mode 100644 index 0000000..6d2c51a --- /dev/null +++ b/rtl/stacks/regs/slink_apb_axi_regs.txt @@ -0,0 +1,88 @@ +################################# +# Enables +################################# +APB_APP_ENABLE RW + apb_app_enable 1'b0 Enables the APB Application Layer + apb_app_enable_mux 1'b0 1 - Use regsiter, 0 - use external logic + +AXI_APP_ENABLE RW + axi_app_enable 1'b0 Enables the AXI Application Layer + axi_app_enable_mux 1'b0 1 - Use regsiter, 0 - use external logic + +INT_APP_ENABLE RW + int_app_enable 1'b0 Enables the Interrupt/GPIO Application Layer + int_app_enable_mux 1'b0 1 - Use regsiter, 0 - use external logic + + + +################################# +# Interrupts / Status +################################# +INTERRUPT_STATUS RW + apb_nack_seen 1'b0 W1C APB Nack has been seen on this application layer (far-end saw an issue) + apb_nack_sent 1'b0 W1C APB Nack has been sent from this application layer (near-end saw an issue) + int_nack_seen 1'b0 W1C INT Nack has been seen on this application layer (far-end saw an issue) + int_nack_sent 1'b0 W1C INT Nack has been sent from this application layer (near-end saw an issue) + axi_aw_nack_seen 1'b0 W1C AXI AW Channel Nack has been seen on this application layer (far-end saw an issue) + axi_aw_nack_sent 1'b0 W1C AXI AW Channel Nack has been sent from this application layer (near-end saw an issue) + axi_w_nack_seen 1'b0 W1C AXI W Channel Nack has been seen on this application layer (far-end saw an issue) + axi_w_nack_sent 1'b0 W1C AXI W Channel Nack has been sent from this application layer (near-end saw an issue) + axi_b_nack_seen 1'b0 W1C AXI B Channel Nack has been seen on this application layer (far-end saw an issue) + axi_b_nack_sent 1'b0 W1C AXI B Channel Nack has been sent from this application layer (near-end saw an issue) + axi_ar_nack_seen 1'b0 W1C AXI AR Channel Nack has been seen on this application layer (far-end saw an issue) + axi_ar_nack_sent 1'b0 W1C AXI AR Channel Nack has been sent from this application layer (near-end saw an issue) + axi_r_nack_seen 1'b0 W1C AXI R Channel Nack has been seen on this application layer (far-end saw an issue) + axi_r_nack_sent 1'b0 W1C AXI R Channel Nack has been sent from this application layer (near-end saw an issue) + +################################# +# PSTATE Controls +################################# +PSTATE_CONTROL RW + tick_1us 8'd39 Number of refclk cycles to equal 1us + inactivity_count 8'd5 Number of microseconds before starting a PState transition + pstate_req 3'd2 PState to transition to. If multiple bits are set, the lowest is used. [0] - P1, [1] - P2, [2] - P3. + pstate_ctrl_enable 1'PAR:'b1 Enables the PSTATE Controller + + + +################################# +# Application Layer IDs +# +################################# + + +################################# +# APB APP +################################# +APB_APP_CREDIT_IDS RW + apb_cr_id 8'h08 Credit Request Data ID for APB Application Channel + apb_crack_id 8'h09 Credit Request Data Acknowledgement ID for APB Application Channel + apb_ack_id 8'h0a Acknowledgement ID for APB Application Channel + apb_nack_id 8'h0b Non-Acknowledgement ID for APB Application Channel + + + +################################# +# INT APP +################################# +INT_APP_CREDIT_IDS RW + int_cr_id 8'h0c Credit Request Data ID for INT Application Channel + int_crack_id 8'h0d Credit Request Data Acknowledgement ID for INT Application Channel + int_ack_id 8'h0e Acknowledgement ID for INT Application Channel + int_nack_id 8'h0f Non-Acknowledgement ID for INT Application Channel + + +INT_APP_PKT_ID_WC RW + int_data_id 8'h50 INT Data ID + int_word_count 16'd3 INT Word Count + +INT_OVERRIDES RW + int_override 24'd0 + int_override_mux 1'b0 + +GPIO_OVERRIDES RW + gpio_override 8'd0 + gpio_override_mux 1'b0 + +INT_GPIO_ENABLE RW + int_gpio_enable 32'hffffffff Allows user to gate the Interrupts/GPIO signals in the event of a spurrious signal diff --git a/rtl/stacks/slink_apb_axi_gpio_top.v b/rtl/stacks/slink_apb_axi_gpio_top.v new file mode 100644 index 0000000..cb44d5c --- /dev/null +++ b/rtl/stacks/slink_apb_axi_gpio_top.v @@ -0,0 +1,1009 @@ +module slink_apb_axi_gpio_top #( + parameter IS_HOST = 1, + parameter IO_DATA_WIDTH = 1, + parameter IO_NUM_LANES = 1, + + parameter NUM_INTS = 24, + parameter NUM_GPIOS = 8, + parameter RETIME_FIFO_DEPTH = 0, + + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_WIDTH = 64 +)( + input wire core_scan_mode, + input wire core_scan_clk, + input wire core_scan_asyncrst_ctrl, + input wire core_scan_shift, + input wire core_scan_in, + output wire core_scan_out, + + input wire apb_clk, + input wire apb_reset, + input wire apb_psel, + input wire apb_penable, + input wire apb_pwrite, + input wire [31:0] apb_pwdata, + input wire [9:0] apb_paddr, + output wire apb_pslverr, + output wire apb_pready, + output wire [31:0] apb_prdata, + + output wire interrupt, + + //------------------------------- + // Interrupts / GPIOs + //------------------------------- + input wire [NUM_INTS-1:0] i_interrupt, + output wire [NUM_INTS-1:0] o_interrupt, + input wire [NUM_GPIOS-1:0] i_gpio, + output wire [NUM_GPIOS-1:0] o_gpio, + + //------------------------------- + // Target APB + //------------------------------- + input wire apb_tgt_psel, + input wire apb_tgt_penable, + input wire apb_tgt_pwrite, + input wire [31:0] apb_tgt_pwdata, + input wire [31:0] apb_tgt_paddr, + output wire apb_tgt_pslverr, + output wire apb_tgt_pready, + output wire [31:0] apb_tgt_prdata, + + //------------------------------- + // Initiator APB + //------------------------------- + output wire apb_ini_psel, + output wire apb_ini_penable, + output wire apb_ini_pwrite, + output wire [31:0] apb_ini_pwdata, + output wire [31:0] apb_ini_paddr, + input wire apb_ini_pslverr, + input wire apb_ini_pready, + input wire [31:0] apb_ini_prdata, + + + //-------------------------------------- + // AXI Target + //-------------------------------------- + input wire axi_clk, + input wire axi_reset, + + input wire [7:0] axi_tgt_awid, + input wire [AXI_ADDR_WIDTH-1:0] axi_tgt_awaddr, + input wire [7:0] axi_tgt_awlen, + input wire [2:0] axi_tgt_awsize, + input wire [1:0] axi_tgt_awburst, + input wire [1:0] axi_tgt_awlock, + input wire [3:0] axi_tgt_awcache, + input wire [2:0] axi_tgt_awprot, + input wire [3:0] axi_tgt_awqos, + input wire [3:0] axi_tgt_awregion, + input wire axi_tgt_awvalid, + output wire axi_tgt_awready, + + input wire [7:0] axi_tgt_wid, + input wire [AXI_DATA_WIDTH-1:0] axi_tgt_wdata, + input wire [(AXI_DATA_WIDTH/8)-1:0] axi_tgt_wstrb, + input wire axi_tgt_wlast, + input wire axi_tgt_wvalid, + output wire axi_tgt_wready, + + output wire [7:0] axi_tgt_bid, + output wire [1:0] axi_tgt_bresp, + output wire axi_tgt_bvalid, + input wire axi_tgt_bready, + + input wire [7:0] axi_tgt_arid, + input wire [AXI_ADDR_WIDTH-1:0] axi_tgt_araddr, + input wire [7:0] axi_tgt_arlen, + input wire [2:0] axi_tgt_arsize, + input wire [1:0] axi_tgt_arburst, + input wire [1:0] axi_tgt_arlock, + input wire [3:0] axi_tgt_arcache, + input wire [2:0] axi_tgt_arprot, + input wire [3:0] axi_tgt_arqos, + input wire [3:0] axi_tgt_arregion, + input wire axi_tgt_arvalid, + output wire axi_tgt_arready, + + output wire [7:0] axi_tgt_rid, + output wire [AXI_DATA_WIDTH-1:0] axi_tgt_rdata, + output wire [1:0] axi_tgt_rresp, + output wire axi_tgt_rlast, + output wire axi_tgt_rvalid, + input wire axi_tgt_rready, + + //-------------------------------------- + // AXI Initiator + //-------------------------------------- + output wire [7:0] axi_ini_awid, + output wire [AXI_ADDR_WIDTH-1:0] axi_ini_awaddr, + output wire [7:0] axi_ini_awlen, + output wire [2:0] axi_ini_awsize, + output wire [1:0] axi_ini_awburst, + output wire [1:0] axi_ini_awlock, + output wire [3:0] axi_ini_awcache, + output wire [2:0] axi_ini_awprot, + output wire [3:0] axi_ini_awqos, + output wire [3:0] axi_ini_awregion, + output wire axi_ini_awvalid, + input wire axi_ini_awready, + + output wire [7:0] axi_ini_wid, + output wire [AXI_DATA_WIDTH-1:0] axi_ini_wdata, + output wire [(AXI_DATA_WIDTH/8)-1:0] axi_ini_wstrb, + output wire axi_ini_wlast, + output wire axi_ini_wvalid, + input wire axi_ini_wready, + + input wire [7:0] axi_ini_bid, + input wire [1:0] axi_ini_bresp, + input wire axi_ini_bvalid, + output wire axi_ini_bready, + + output wire [7:0] axi_ini_arid, + output wire [AXI_ADDR_WIDTH-1:0] axi_ini_araddr, + output wire [7:0] axi_ini_arlen, + output wire [2:0] axi_ini_arsize, + output wire [1:0] axi_ini_arburst, + output wire [1:0] axi_ini_arlock, + output wire [3:0] axi_ini_arcache, + output wire [2:0] axi_ini_arprot, + output wire [3:0] axi_ini_arqos, + output wire [3:0] axi_ini_arregion, + output wire axi_ini_arvalid, + input wire axi_ini_arready, + + input wire [7:0] axi_ini_rid, + input wire [AXI_DATA_WIDTH-1:0] axi_ini_rdata, + input wire [1:0] axi_ini_rresp, + input wire axi_ini_rlast, + input wire axi_ini_rvalid, + output wire axi_ini_rready, + + + input wire por_reset, + input wire refclk, + input wire hsclk, + + //input wire slink_rx_clk, + output wire slink_tx_clk, + output wire [(IO_DATA_WIDTH* + IO_NUM_LANES)-1:0] slink_tx_data, + input wire [(IO_DATA_WIDTH* + IO_NUM_LANES)-1:0] slink_rx_data, + + output wire slink_gpio_reset_n_oen, + input wire slink_gpio_reset_n, + output wire slink_gpio_wake_n_oen, + input wire slink_gpio_wake_n + +); + +localparam TX_APP_DATA_WIDTH = 128; +localparam RX_APP_DATA_WIDTH = 128; + +wire link_clk; +wire link_reset; +wire tx_sop; +wire [7:0] tx_data_id; +wire [15:0] tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] tx_app_data; +wire tx_advance; +wire rx_sop; +wire [7:0] rx_data_id; +wire [15:0] rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] rx_app_data; +wire rx_valid; +wire rx_crc_corrupted; + + + + +wire link_interrupt; +wire p1_req; +wire p2_req; +wire p3_req; +wire in_px_state; +wire in_reset_state; +wire [IO_NUM_LANES-1:0] phy_clk; +wire phy_clk_en; +wire phy_clk_idle; +wire [IO_NUM_LANES-1:0] phy_clk_ready; +wire [IO_NUM_LANES-1:0] phy_tx_en; +wire [IO_NUM_LANES-1:0] phy_tx_ready; +wire [IO_NUM_LANES-1:0] phy_tx_dirdy; +wire [(IO_NUM_LANES*8)-1:0] phy_tx_data; +wire [IO_NUM_LANES-1:0] phy_rx_en; +wire [IO_NUM_LANES-1:0] phy_rx_clk; +wire [IO_NUM_LANES-1:0] phy_rx_ready; +wire [IO_NUM_LANES-1:0] phy_rx_valid; +wire [IO_NUM_LANES-1:0] phy_rx_dordy; +wire [IO_NUM_LANES-1:0] phy_rx_align; +wire [(IO_NUM_LANES*8)-1:0] phy_rx_data; + +wire [IO_NUM_LANES-1:0] slink_tx_clk_lane; + + +wire apb_psel_app; +wire apb_penable_app; +wire apb_pwrite_app; +wire [31:0] apb_pwdata_app; +wire [7:0] apb_paddr_app; +wire apb_pslverr_app; +wire apb_pready_app; +wire [31:0] apb_prdata_app; + +wire apb_psel_link; +wire apb_penable_link; +wire apb_pwrite_link; +wire [31:0] apb_pwdata_link; +wire [8:0] apb_paddr_link; +wire apb_pslverr_link; +wire apb_pready_link; +wire [31:0] apb_prdata_link; + + +wire apb_clk_scan; +wire apb_reset_scan; +slink_clock_mux u_slink_clock_mux_apb_clk ( + .clk0 ( apb_clk ), + .clk1 ( core_scan_clk ), + .sel ( core_scan_mode ), + .clk_out ( apb_clk_scan )); + +slink_reset_sync u_slink_reset_sync_apb_reset ( + .clk ( apb_clk_scan ), + .scan_ctrl ( core_scan_asyncrst_ctrl ), + .reset_in ( apb_reset ), + .reset_out ( apb_reset_scan )); + +wire refclk_scan; +wire por_reset_refclk_scan; +slink_clock_mux u_slink_clock_mux_ref_clk ( + .clk0 ( refclk ), + .clk1 ( core_scan_clk ), + .sel ( core_scan_mode ), + .clk_out ( refclk_scan )); + +slink_reset_sync u_slink_reset_sync_por_reset ( + .clk ( refclk_scan ), + .scan_ctrl ( core_scan_asyncrst_ctrl ), + .reset_in ( por_reset ), + .reset_out ( por_reset_refclk_scan )); + + +wire axi_clk_scan; +wire axi_reset_scan; +slink_clock_mux u_slink_clock_mux_axi_clk ( + .clk0 ( axi_clk ), + .clk1 ( core_scan_clk ), + .sel ( core_scan_mode ), + .clk_out ( axi_clk_scan )); + +slink_reset_sync u_slink_reset_sync_axi_reset ( + .clk ( axi_clk_scan ), + .scan_ctrl ( core_scan_asyncrst_ctrl ), + .reset_in ( axi_reset ), + .reset_out ( axi_reset_scan )); + + +localparam APB_LINK = 2'h0, + APB_LINK_BIST = 2'h1, + APB_APP = 2'h2; + + +assign apb_psel_app = (apb_paddr[9:8] == APB_APP) && apb_psel; +assign apb_penable_app = (apb_paddr[9:8] == APB_APP) && apb_penable; +assign apb_pwrite_app = (apb_paddr[9:8] == APB_APP) && apb_pwrite; +assign apb_paddr_app = apb_paddr[7:0]; +assign apb_pwdata_app = apb_pwdata; + +assign apb_psel_link = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) && apb_psel; +assign apb_penable_link = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) && apb_penable; +assign apb_pwrite_link = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) && apb_pwrite; +assign apb_paddr_link = apb_paddr[8:0]; +assign apb_pwdata_link = apb_pwdata; + +assign apb_prdata = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) ? apb_prdata_link : apb_prdata_app; +assign apb_pready = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) ? apb_pready_link : apb_pready_app; +assign apb_pslverr = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) ? apb_pslverr_link : apb_pslverr_app; + + + +wire swi_apb_app_enable_muxed; +wire swi_axi_app_enable_muxed; +wire swi_int_app_enable_muxed; + +wire [7:0] swi_tick_1us; +wire [7:0] swi_inactivity_count; +wire [2:0] swi_pstate_req; +wire swi_pstate_ctrl_enable; +wire [7:0] swi_apb_cr_id; +wire [7:0] swi_apb_crack_id; +wire [7:0] swi_apb_ack_id; +wire [7:0] swi_apb_nack_id; +wire [7:0] swi_int_cr_id; +wire [7:0] swi_int_crack_id; +wire [7:0] swi_int_ack_id; +wire [7:0] swi_int_nack_id; +wire [7:0] swi_int_data_id; +wire [15:0] swi_int_word_count; +wire [23:0] swi_int_override_muxed; +wire [7:0] swi_gpio_override_muxed; +wire [31:0] swi_int_gpio_enable; + +wire w1c_in_apb_nack_seen; +wire w1c_in_apb_nack_sent; +wire w1c_in_int_nack_seen; +wire w1c_in_int_nack_sent; +wire w1c_in_axi_aw_nack_seen ; +wire w1c_in_axi_aw_nack_sent ; +wire w1c_in_axi_w_nack_seen ; +wire w1c_in_axi_w_nack_sent ; +wire w1c_in_axi_b_nack_seen ; +wire w1c_in_axi_b_nack_sent ; +wire w1c_in_axi_ar_nack_seen ; +wire w1c_in_axi_ar_nack_sent ; +wire w1c_in_axi_r_nack_seen ; +wire w1c_in_axi_r_nack_sent ; + +wire w1c_out_apb_nack_seen; +wire w1c_out_apb_nack_sent; +wire w1c_out_int_nack_seen; +wire w1c_out_int_nack_sent; +wire w1c_out_axi_aw_nack_seen; +wire w1c_out_axi_aw_nack_sent; +wire w1c_out_axi_w_nack_seen; +wire w1c_out_axi_w_nack_sent; +wire w1c_out_axi_b_nack_seen; +wire w1c_out_axi_b_nack_sent; +wire w1c_out_axi_ar_nack_seen; +wire w1c_out_axi_ar_nack_sent; +wire w1c_out_axi_r_nack_seen; +wire w1c_out_axi_r_nack_sent; + + + +wire [4:0] axi_nack_sent; +wire [4:0] axi_nack_seen; +wire [4:0] axi_tx_fifo_empty; +wire [4:0] axi_rx_fifo_empty; + +wire apb_nack_sent; +wire apb_nack_seen; +wire apb_invalid_resp_pkt; + +wire int_nack_sent; +wire int_nack_seen; + +//All NACKs are handled in link clk domain +slink_sync_pulse u_slink_sync_pulse_nacks[13:0] ( + .clk_in ( link_clk ), + .clk_in_reset ( link_reset ), + .data_in ( {apb_nack_seen, + apb_nack_sent, + int_nack_seen, + int_nack_sent, + axi_nack_seen[0], + axi_nack_sent[0], + axi_nack_seen[1], + axi_nack_sent[1], + axi_nack_seen[2], + axi_nack_sent[2], + axi_nack_seen[3], + axi_nack_sent[3], + axi_nack_seen[4], + axi_nack_sent[4]} ), + .clk_out ( apb_clk_scan ), + .clk_out_reset ( apb_reset_scan ), + .data_out ( {w1c_in_apb_nack_seen, + w1c_in_apb_nack_sent, + w1c_in_int_nack_seen, + w1c_in_int_nack_sent, + w1c_in_axi_aw_nack_seen, + w1c_in_axi_aw_nack_sent, + w1c_in_axi_w_nack_seen, + w1c_in_axi_w_nack_sent, + w1c_in_axi_b_nack_seen, + w1c_in_axi_b_nack_sent, + w1c_in_axi_ar_nack_seen, + w1c_in_axi_ar_nack_sent, + w1c_in_axi_r_nack_seen, + w1c_in_axi_r_nack_sent} )); + + +slink_apb_axi_regs_top #( + .PSTATE_CTRL_ENABLE_RESET_PARAM ( IS_HOST ) //Slave should just listen +) u_slink_apb_axi_regs_top ( + .apb_app_enable ( ~por_reset_refclk_scan ), + .swi_apb_app_enable_muxed ( swi_apb_app_enable_muxed ), + .axi_app_enable ( ~por_reset_refclk_scan ), + .swi_axi_app_enable_muxed ( swi_axi_app_enable_muxed ), + .int_app_enable ( ~por_reset_refclk_scan ), + .swi_int_app_enable_muxed ( swi_int_app_enable_muxed ), + .w1c_in_apb_nack_seen ( w1c_in_apb_nack_seen ), + .w1c_out_apb_nack_seen ( w1c_out_apb_nack_seen ), + .w1c_in_apb_nack_sent ( w1c_in_apb_nack_sent ), + .w1c_out_apb_nack_sent ( w1c_out_apb_nack_sent ), + .w1c_in_int_nack_seen ( w1c_in_int_nack_seen ), + .w1c_out_int_nack_seen ( w1c_out_int_nack_seen ), + .w1c_in_int_nack_sent ( w1c_in_int_nack_sent ), + .w1c_out_int_nack_sent ( w1c_out_int_nack_sent ), + .w1c_in_axi_aw_nack_seen ( w1c_in_axi_aw_nack_seen ), + .w1c_out_axi_aw_nack_seen ( w1c_out_axi_aw_nack_seen ), + .w1c_in_axi_aw_nack_sent ( w1c_in_axi_aw_nack_sent ), + .w1c_out_axi_aw_nack_sent ( w1c_out_axi_aw_nack_sent ), + .w1c_in_axi_w_nack_seen ( w1c_in_axi_w_nack_seen ), + .w1c_out_axi_w_nack_seen ( w1c_out_axi_w_nack_seen ), + .w1c_in_axi_w_nack_sent ( w1c_in_axi_w_nack_sent ), + .w1c_out_axi_w_nack_sent ( w1c_out_axi_w_nack_sent ), + .w1c_in_axi_b_nack_seen ( w1c_in_axi_b_nack_seen ), + .w1c_out_axi_b_nack_seen ( w1c_out_axi_b_nack_seen ), + .w1c_in_axi_b_nack_sent ( w1c_in_axi_b_nack_sent ), + .w1c_out_axi_b_nack_sent ( w1c_out_axi_b_nack_sent ), + .w1c_in_axi_ar_nack_seen ( w1c_in_axi_ar_nack_seen ), + .w1c_out_axi_ar_nack_seen ( w1c_out_axi_ar_nack_seen ), + .w1c_in_axi_ar_nack_sent ( w1c_in_axi_ar_nack_sent ), + .w1c_out_axi_ar_nack_sent ( w1c_out_axi_ar_nack_sent ), + .w1c_in_axi_r_nack_seen ( w1c_in_axi_r_nack_seen ), + .w1c_out_axi_r_nack_seen ( w1c_out_axi_r_nack_seen ), + .w1c_in_axi_r_nack_sent ( w1c_in_axi_r_nack_sent ), + .w1c_out_axi_r_nack_sent ( w1c_out_axi_r_nack_sent ), + + .swi_tick_1us ( swi_tick_1us ), + .swi_inactivity_count ( swi_inactivity_count ), + .swi_pstate_req ( swi_pstate_req ), + .swi_pstate_ctrl_enable ( swi_pstate_ctrl_enable ), + .swi_apb_cr_id ( swi_apb_cr_id ), + .swi_apb_crack_id ( swi_apb_crack_id ), + .swi_apb_ack_id ( swi_apb_ack_id ), + .swi_apb_nack_id ( swi_apb_nack_id ), + .swi_int_cr_id ( swi_int_cr_id ), + .swi_int_crack_id ( swi_int_crack_id ), + .swi_int_ack_id ( swi_int_ack_id ), + .swi_int_nack_id ( swi_int_nack_id ), + .swi_int_data_id ( swi_int_data_id ), + .swi_int_word_count ( swi_int_word_count ), + .int_override ( i_interrupt ), + .swi_int_override_muxed ( swi_int_override_muxed ), + .gpio_override ( i_gpio ), + .swi_gpio_override_muxed ( swi_gpio_override_muxed ), + .swi_int_gpio_enable ( swi_int_gpio_enable ), + .debug_bus_ctrl_status ( ), + .RegReset ( apb_reset_scan ), + .RegClk ( apb_clk_scan ), + .PSEL ( apb_psel_app ), + .PENABLE ( apb_penable_app ), + .PWRITE ( apb_pwrite_app ), + .PSLVERR ( apb_pslverr_app ), + .PREADY ( apb_pready_app ), + .PADDR ( apb_paddr_app ), + .PWDATA ( apb_pwdata_app ), + .PRDATA ( apb_prdata_app )); + + +assign interrupt = link_interrupt || + w1c_out_apb_nack_seen || + w1c_out_apb_nack_sent || + w1c_out_int_nack_seen || + w1c_out_int_nack_sent || + w1c_out_axi_aw_nack_seen || + w1c_out_axi_aw_nack_sent || + w1c_out_axi_w_nack_seen || + w1c_out_axi_w_nack_sent || + w1c_out_axi_b_nack_seen || + w1c_out_axi_b_nack_sent || + w1c_out_axi_ar_nack_seen || + w1c_out_axi_ar_nack_sent || + w1c_out_axi_r_nack_seen || + w1c_out_axi_r_nack_sent; + + +//---------------------------------- +// APB +//---------------------------------- +wire apb_tx_sop; +wire [7:0] apb_tx_data_id; +wire [15:0] apb_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] apb_tx_app_data; +wire apb_tx_advance; +wire apb_rx_sop; +wire [7:0] apb_rx_data_id; +wire [15:0] apb_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] apb_rx_app_data; +wire apb_rx_valid; +wire apb_rx_crc_corrupted; + +slink_apb_top #( + //parameters + .APB_TARGET ( IS_HOST ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ) +) u_slink_apb_top ( + .apb_clk ( apb_clk_scan ), + .apb_reset ( apb_reset_scan ), + .enable ( swi_apb_app_enable_muxed ), + .swi_cr_id ( swi_apb_cr_id ), + .swi_crack_id ( swi_apb_crack_id ), + .swi_ack_id ( swi_apb_ack_id ), + .swi_nack_id ( swi_apb_nack_id ), + .nack_sent ( apb_nack_sent ), + .nack_seen ( apb_nack_seen ), + .invalid_resp_pkt ( apb_invalid_resp_pkt ), + .apb_tgt_psel ( apb_tgt_psel ), + .apb_tgt_penable ( apb_tgt_penable ), + .apb_tgt_pwrite ( apb_tgt_pwrite ), + .apb_tgt_pwdata ( apb_tgt_pwdata ), + .apb_tgt_paddr ( apb_tgt_paddr ), + .apb_tgt_pslverr ( apb_tgt_pslverr ), + .apb_tgt_pready ( apb_tgt_pready ), + .apb_tgt_prdata ( apb_tgt_prdata ), + .apb_ini_psel ( apb_ini_psel ), + .apb_ini_penable ( apb_ini_penable ), + .apb_ini_pwrite ( apb_ini_pwrite ), + .apb_ini_pwdata ( apb_ini_pwdata ), + .apb_ini_paddr ( apb_ini_paddr ), + .apb_ini_pslverr ( apb_ini_pslverr ), + .apb_ini_pready ( apb_ini_pready ), + .apb_ini_prdata ( apb_ini_prdata ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .tx_sop ( apb_tx_sop ), + .tx_data_id ( apb_tx_data_id ), + .tx_word_count ( apb_tx_word_count ), + .tx_app_data ( apb_tx_app_data ), + .tx_advance ( apb_tx_advance ), + .rx_sop ( apb_rx_sop ), + .rx_data_id ( apb_rx_data_id ), + .rx_word_count ( apb_rx_word_count ), + .rx_app_data ( apb_rx_app_data ), + .rx_valid ( apb_rx_valid ), + .rx_crc_corrupted ( apb_rx_crc_corrupted )); + + + +//---------------------------------- +// Interrupts / IO +//---------------------------------- +wire int_tx_sop; +wire [7:0] int_tx_data_id; +wire [15:0] int_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] int_tx_app_data; +wire int_tx_advance; +wire int_rx_sop; +wire [7:0] int_rx_data_id; +wire [15:0] int_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] int_rx_app_data; +wire int_rx_valid; +wire int_rx_crc_corrupted; + +slink_int_gpio_top #( + //parameters + .NUM_GPIOS ( NUM_GPIOS ), + .NUM_INTS ( NUM_INTS ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ) +) u_slink_int_gpio_top ( + .app_clk ( apb_clk_scan ), + .app_reset ( apb_reset_scan ), + .enable ( swi_int_app_enable_muxed ), + .swi_cr_id ( swi_int_cr_id ), + .swi_crack_id ( swi_int_crack_id ), + .swi_ack_id ( swi_int_ack_id ), + .swi_nack_id ( swi_int_nack_id ), + .swi_data_id ( swi_int_data_id ), + .swi_word_count ( swi_int_word_count ), + .nack_sent ( int_nack_sent ), + .nack_seen ( int_nack_seen ), + .i_interrupt ( swi_int_override_muxed & + swi_int_gpio_enable[23:0] ), //Need to fix this + .o_interrupt ( o_interrupt ), + .i_gpio ( swi_gpio_override_muxed & + swi_int_gpio_enable[31:24] ), //Need to fix this + .o_gpio ( o_gpio ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .tx_sop ( int_tx_sop ), + .tx_data_id ( int_tx_data_id ), + .tx_word_count ( int_tx_word_count ), + .tx_app_data ( int_tx_app_data ), + .tx_advance ( int_tx_advance ), + .rx_sop ( int_rx_sop ), + .rx_data_id ( int_rx_data_id ), + .rx_word_count ( int_rx_word_count ), + .rx_app_data ( int_rx_app_data ), + .rx_valid ( int_rx_valid ), + .rx_crc_corrupted ( int_rx_crc_corrupted )); + + +//---------------------------------- +// Interrupts / IO +//---------------------------------- +wire axi_tx_sop; +wire [7:0] axi_tx_data_id; +wire [15:0] axi_tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] axi_tx_app_data; +wire axi_tx_advance; +wire axi_rx_sop; +wire [7:0] axi_rx_data_id; +wire [15:0] axi_rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] axi_rx_app_data; +wire axi_rx_valid; +wire axi_rx_crc_corrupted; + +slink_axi_top #( + //parameters + .ADDR_CH_APP_DEPTH ( 4 ), + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), + .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), + .DATA_CH_APP_DEPTH ( 8 ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ) +) u_slink_axi_top ( + .axi_clk ( axi_clk_scan ), + .axi_reset ( axi_reset_scan ), + .tgt_awid ( axi_tgt_awid ), + .tgt_awaddr ( axi_tgt_awaddr ), + .tgt_awlen ( axi_tgt_awlen ), + .tgt_awsize ( axi_tgt_awsize ), + .tgt_awburst ( axi_tgt_awburst ), + .tgt_awlock ( axi_tgt_awlock ), + .tgt_awcache ( axi_tgt_awcache ), + .tgt_awprot ( axi_tgt_awprot ), + .tgt_awqos ( axi_tgt_awqos ), + .tgt_awregion ( axi_tgt_awregion ), + .tgt_awvalid ( axi_tgt_awvalid ), + .tgt_awready ( axi_tgt_awready ), + .tgt_wid ( axi_tgt_wid ), + .tgt_wdata ( axi_tgt_wdata ), + .tgt_wstrb ( axi_tgt_wstrb ), + .tgt_wlast ( axi_tgt_wlast ), + .tgt_wvalid ( axi_tgt_wvalid ), + .tgt_wready ( axi_tgt_wready ), + .tgt_bid ( axi_tgt_bid ), + .tgt_bresp ( axi_tgt_bresp ), + .tgt_bvalid ( axi_tgt_bvalid ), + .tgt_bready ( axi_tgt_bready ), + .tgt_arid ( axi_tgt_arid ), + .tgt_araddr ( axi_tgt_araddr ), + .tgt_arlen ( axi_tgt_arlen ), + .tgt_arsize ( axi_tgt_arsize ), + .tgt_arburst ( axi_tgt_arburst ), + .tgt_arlock ( axi_tgt_arlock ), + .tgt_arcache ( axi_tgt_arcache ), + .tgt_arprot ( axi_tgt_arprot ), + .tgt_arqos ( axi_tgt_arqos ), + .tgt_arregion ( axi_tgt_arregion ), + .tgt_arvalid ( axi_tgt_arvalid ), + .tgt_arready ( axi_tgt_arready ), + .tgt_rid ( axi_tgt_rid ), + .tgt_rdata ( axi_tgt_rdata ), + .tgt_rresp ( axi_tgt_rresp ), + .tgt_rlast ( axi_tgt_rlast ), + .tgt_rvalid ( axi_tgt_rvalid ), + .tgt_rready ( axi_tgt_rready ), + .ini_awid ( axi_ini_awid ), + .ini_awaddr ( axi_ini_awaddr ), + .ini_awlen ( axi_ini_awlen ), + .ini_awsize ( axi_ini_awsize ), + .ini_awburst ( axi_ini_awburst ), + .ini_awlock ( axi_ini_awlock ), + .ini_awcache ( axi_ini_awcache ), + .ini_awprot ( axi_ini_awprot ), + .ini_awqos ( axi_ini_awqos ), + .ini_awregion ( axi_ini_awregion ), + .ini_awvalid ( axi_ini_awvalid ), + .ini_awready ( axi_ini_awready ), + .ini_wid ( axi_ini_wid ), + .ini_wdata ( axi_ini_wdata ), + .ini_wstrb ( axi_ini_wstrb ), + .ini_wlast ( axi_ini_wlast ), + .ini_wvalid ( axi_ini_wvalid ), + .ini_wready ( axi_ini_wready ), + .ini_bid ( axi_ini_bid ), + .ini_bresp ( axi_ini_bresp ), + .ini_bvalid ( axi_ini_bvalid ), + .ini_bready ( axi_ini_bready ), + .ini_arid ( axi_ini_arid ), + .ini_araddr ( axi_ini_araddr ), + .ini_arlen ( axi_ini_arlen ), + .ini_arsize ( axi_ini_arsize ), + .ini_arburst ( axi_ini_arburst ), + .ini_arlock ( axi_ini_arlock ), + .ini_arcache ( axi_ini_arcache ), + .ini_arprot ( axi_ini_arprot ), + .ini_arqos ( axi_ini_arqos ), + .ini_arregion ( axi_ini_arregion ), + .ini_arvalid ( axi_ini_arvalid ), + .ini_arready ( axi_ini_arready ), + .ini_rid ( axi_ini_rid ), + .ini_rdata ( axi_ini_rdata ), + .ini_rresp ( axi_ini_rresp ), + .ini_rlast ( axi_ini_rlast ), + .ini_rvalid ( axi_ini_rvalid ), + .ini_rready ( axi_ini_rready ), + .enable ( swi_axi_app_enable_muxed ), + .swi_aw_cr_id ( 8'h10 ), + .swi_aw_crack_id ( 8'h11 ), + .swi_aw_ack_id ( 8'h12 ), + .swi_aw_nack_id ( 8'h13 ), + .swi_aw_data_id ( 8'h40 ), + .swi_w_cr_id ( 8'h14 ), + .swi_w_crack_id ( 8'h15 ), + .swi_w_ack_id ( 8'h16 ), + .swi_w_nack_id ( 8'h17 ), + .swi_w_data_id ( 8'h41 ), + .swi_b_cr_id ( 8'h18 ), + .swi_b_crack_id ( 8'h19 ), + .swi_b_ack_id ( 8'h1a ), + .swi_b_nack_id ( 8'h1b ), + .swi_b_data_id ( 8'h42 ), + .swi_ar_cr_id ( 8'h1c ), + .swi_ar_crack_id ( 8'h1d ), + .swi_ar_ack_id ( 8'h1e ), + .swi_ar_nack_id ( 8'h1f ), + .swi_ar_data_id ( 8'h43 ), + .swi_r_cr_id ( 8'h20 ), + .swi_r_crack_id ( 8'h21 ), + .swi_r_ack_id ( 8'h22 ), + .swi_r_nack_id ( 8'h23 ), + .swi_r_data_id ( 8'h44 ), + .nack_sent ( axi_nack_sent ), + .nack_seen ( axi_nack_seen ), + .tx_fifo_empty ( axi_tx_fifo_empty ), + .rx_fifo_empty ( axi_rx_fifo_empty ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .tx_sop ( axi_tx_sop ), + .tx_data_id ( axi_tx_data_id ), + .tx_word_count ( axi_tx_word_count ), + .tx_app_data ( axi_tx_app_data ), + .tx_advance ( axi_tx_advance ), + .rx_sop ( axi_rx_sop ), + .rx_data_id ( axi_rx_data_id ), + .rx_word_count ( axi_rx_word_count ), + .rx_app_data ( axi_rx_app_data ), + .rx_valid ( axi_rx_valid ), + .rx_crc_corrupted ( axi_rx_crc_corrupted )); + + + +slink_generic_tx_router #( + //parameters + .NUM_CHANNELS ( 3 ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ) +) u_slink_generic_tx_router ( + .clk ( link_clk ), + .reset ( link_reset ), + .enable ( 1'b1 ), //What is best way to connect? + .tx_sop_ch ( {int_tx_sop, + apb_tx_sop, + axi_tx_sop} ), + .tx_data_id_ch ( {int_tx_data_id, + apb_tx_data_id, + axi_tx_data_id} ), + .tx_word_count_ch ( {int_tx_word_count, + apb_tx_word_count, + axi_tx_word_count} ), + .tx_app_data_ch ( {int_tx_app_data, + apb_tx_app_data, + axi_tx_app_data} ), + .tx_advance_ch ( {int_tx_advance, + apb_tx_advance, + axi_tx_advance} ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance )); + + + +slink_generic_rx_router #( + //parameters + .NUM_CHANNELS ( 3 ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ) +) u_slink_generic_rx_router ( + .clk ( link_clk ), + .reset ( link_reset ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted ), + .swi_ch_sp_min ( {8'h0c, + 8'h08, + 8'h10} ), //input - [(NUM_CHANNELS*8)-1:0] + .swi_ch_sp_max ( {8'h0f, + 8'h0b, + 8'h23} ), //input - [(NUM_CHANNELS*8)-1:0] + .swi_ch_lp_min ( {8'h50, + 8'h30, + 8'h40} ), //input - [(NUM_CHANNELS*8)-1:0] + .swi_ch_lp_max ( {8'h50, + 8'h33, + 8'h44} ), //input - [(NUM_CHANNELS*8)-1:0] + .rx_sop_ch ( {int_rx_sop, + apb_rx_sop, + axi_rx_sop} ), + .rx_data_id_ch ( {int_rx_data_id, + apb_rx_data_id, + axi_rx_data_id} ), + .rx_word_count_ch ( {int_rx_word_count, + apb_rx_word_count, + axi_rx_word_count} ), + .rx_app_data_ch ( {int_rx_app_data, + apb_rx_app_data, + axi_rx_app_data} ), + .rx_valid_ch ( {int_rx_valid, + apb_rx_valid, + axi_rx_valid} ), + .rx_crc_corrupted_ch ( {int_rx_crc_corrupted, + apb_rx_crc_corrupted, + axi_rx_crc_corrupted} )); + + + +slink_generic_pstate_ctrl u_slink_generic_pstate_ctrl ( + .refclk ( refclk_scan ), + .refclk_reset ( por_reset_refclk_scan ), + .enable ( swi_pstate_ctrl_enable ), + .link_clk ( link_clk ), + .link_clk_reset ( link_reset ), + .link_active ( tx_sop ), // + .in_px_state ( in_px_state || + in_reset_state ), + .swi_1us_tick_count ( swi_tick_1us ), + .swi_inactivity_count ( swi_inactivity_count ), + .swi_pstate_req ( swi_pstate_req ), + .p1_req ( p1_req ), + .p2_req ( p2_req ), + .p3_req ( p3_req )); + + + +slink #( + //parameters + .DESKEW_FIFO_DEPTH ( 4 ), + .RETIME_FIFO_DEPTH ( RETIME_FIFO_DEPTH ), + .INCLUDE_BIST ( 1 ), + .LTSSM_REGISTER_TXDATA ( 0 ), + .NUM_RX_LANES ( IO_NUM_LANES ), + .NUM_TX_LANES ( IO_NUM_LANES ), + .P1_TS1_RX_RESET ( 1 ), + .P1_TS1_TX_RESET ( 1 ), + .P1_TS2_RX_RESET ( 1 ), + .P1_TS2_TX_RESET ( 1 ), + .P2_TS1_RX_RESET ( 1 ), + .P2_TS1_TX_RESET ( 1 ), + .P2_TS2_RX_RESET ( 1 ), + .P2_TS2_TX_RESET ( 1 ), + .P3R_TS1_RX_RESET ( 1 ), + .P3R_TS1_TX_RESET ( 1 ), + .P3R_TS2_RX_RESET ( 1 ), + .P3R_TS2_TX_RESET ( 1 ), + .PHY_DATA_WIDTH ( 8 ), + .PX_CLK_TRAIL_RESET ( 16 ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .START_IN_ONE_LANE ( 1 ), + .SYNC_FREQ_RESET ( 7 ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ) +) u_slink ( + .core_scan_mode ( core_scan_mode ), + .core_scan_clk ( core_scan_clk ), + .core_scan_asyncrst_ctrl ( core_scan_asyncrst_ctrl ), + .apb_clk ( apb_clk_scan ), + .apb_reset ( apb_reset_scan ), + .apb_paddr ( apb_paddr_link ), + .apb_pwrite ( apb_pwrite_link ), + .apb_psel ( apb_psel_link ), + .apb_penable ( apb_penable_link ), + .apb_pwdata ( apb_pwdata_link ), + .apb_prdata ( apb_prdata_link ), + .apb_pready ( apb_pready_link ), + .apb_pslverr ( apb_pslverr_link ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .slink_enable ( ~por_reset_refclk_scan ), + .por_reset ( por_reset_refclk_scan ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted ), + .interrupt ( link_interrupt ), + .p1_req ( p1_req ), + .p2_req ( p2_req ), + .p3_req ( p3_req ), + .in_px_state ( in_px_state ), + .in_reset_state ( in_reset_state ), + .slink_gpio_reset_n_oen ( slink_gpio_reset_n_oen ), + .slink_gpio_reset_n ( slink_gpio_reset_n ), + .slink_gpio_wake_n_oen ( slink_gpio_wake_n_oen ), + .slink_gpio_wake_n ( slink_gpio_wake_n ), + .refclk ( refclk_scan ), + .phy_clk ( phy_clk[0] ), + .phy_clk_en ( phy_clk_en ), + .phy_clk_idle ( phy_clk_idle ), + .phy_clk_ready ( phy_clk_ready[0] ), + .phy_tx_en ( phy_tx_en ), + .phy_tx_ready ( phy_tx_ready ), + .phy_tx_dirdy ( {IO_NUM_LANES{1'b1}} ), + .phy_tx_data ( phy_tx_data ), + .phy_rx_en ( phy_rx_en ), + .phy_rx_clk ( phy_rx_clk ), + .phy_rx_ready ( phy_rx_ready ), + .phy_rx_valid ( phy_rx_valid ), + .phy_rx_dordy ( {IO_NUM_LANES{1'b1}} ), + .phy_rx_align ( phy_rx_align ), + .phy_rx_data ( phy_rx_data )); + + +assign phy_rx_clk = phy_clk; + +wire slink_base_serial_clk; +// generate +// if(IS_HOST) begin +// slink_clock_mux u_slink_clock_mux_highspeed_clock ( +// .clk0 ( hsclk ), +// .clk1 ( core_scan_clk ), +// .sel ( core_scan_mode ), +// .clk_out ( slink_base_serial_clk )); +// end else begin +// slink_clock_mux u_slink_clock_mux_highspeed_clock ( +// .clk0 ( slink_rx_clk ), +// .clk1 ( core_scan_clk ), +// .sel ( core_scan_mode ), +// .clk_out ( slink_base_serial_clk )); +// end +// endgenerate + +slink_clock_mux u_slink_clock_mux_highspeed_clock ( + .clk0 ( hsclk ), + .clk1 ( core_scan_clk ), + .sel ( core_scan_mode ), + .clk_out ( slink_base_serial_clk )); + + +wire por_reset_serial_clk; +slink_reset_sync u_slink_reset_sync_hs_clk_porreset ( + .clk ( slink_base_serial_clk ), + .scan_ctrl ( core_scan_asyncrst_ctrl ), + .reset_in ( por_reset ), + .reset_out ( por_reset_serial_clk )); + +slink_gpio_serdes #( + //parameters + .IO_DATA_WIDTH ( IO_DATA_WIDTH ), + .PAR_DATA_WIDTH ( 8 ) +) u_slink_gpio_serdes[IO_NUM_LANES-1:0] ( + .core_scan_mode ( core_scan_mode ), + .core_scan_clk ( core_scan_clk ), + .serial_clk ( slink_base_serial_clk ), + .serial_reset ( por_reset_serial_clk ), + .clk_en ( phy_clk_en ), + .clk_idle ( phy_clk_idle ), + .clk_ready ( phy_clk_ready ), + .phy_clk ( phy_clk ), + .tx_en ( phy_tx_en ), + .tx_ready ( phy_tx_ready ), + .tx_par_data ( phy_tx_data ), + .rx_en ( phy_rx_en ), + .rx_ready ( phy_rx_ready ), + .rx_par_data ( phy_rx_data ), + .tx_ser_clk ( slink_tx_clk_lane ), + .tx_ser_data ( slink_tx_data ), + .rx_ser_data ( slink_rx_data )); + +assign slink_tx_clk = slink_tx_clk_lane[0]; + +endmodule diff --git a/rtl/stacks/slink_apb_axi_regs_top.v b/rtl/stacks/slink_apb_axi_regs_top.v new file mode 100644 index 0000000..ab573be --- /dev/null +++ b/rtl/stacks/slink_apb_axi_regs_top.v @@ -0,0 +1,1055 @@ +//=================================================================== +// +// Created by sbridges on February/02/2021 at 14:25:43 +// +// slink_apb_axi_regs_top.v +// +//=================================================================== + + + +module slink_apb_axi_regs_top #( + parameter PSTATE_CTRL_ENABLE_RESET_PARAM = 1'h1, + parameter ADDR_WIDTH = 8 +)( + //APB_APP_ENABLE + input wire apb_app_enable, + output wire swi_apb_app_enable_muxed, + //AXI_APP_ENABLE + input wire axi_app_enable, + output wire swi_axi_app_enable_muxed, + //INT_APP_ENABLE + input wire int_app_enable, + output wire swi_int_app_enable_muxed, + //INTERRUPT_STATUS + input wire w1c_in_apb_nack_seen, + output wire w1c_out_apb_nack_seen, + input wire w1c_in_apb_nack_sent, + output wire w1c_out_apb_nack_sent, + input wire w1c_in_int_nack_seen, + output wire w1c_out_int_nack_seen, + input wire w1c_in_int_nack_sent, + output wire w1c_out_int_nack_sent, + input wire w1c_in_axi_aw_nack_seen, + output wire w1c_out_axi_aw_nack_seen, + input wire w1c_in_axi_aw_nack_sent, + output wire w1c_out_axi_aw_nack_sent, + input wire w1c_in_axi_w_nack_seen, + output wire w1c_out_axi_w_nack_seen, + input wire w1c_in_axi_w_nack_sent, + output wire w1c_out_axi_w_nack_sent, + input wire w1c_in_axi_b_nack_seen, + output wire w1c_out_axi_b_nack_seen, + input wire w1c_in_axi_b_nack_sent, + output wire w1c_out_axi_b_nack_sent, + input wire w1c_in_axi_ar_nack_seen, + output wire w1c_out_axi_ar_nack_seen, + input wire w1c_in_axi_ar_nack_sent, + output wire w1c_out_axi_ar_nack_sent, + input wire w1c_in_axi_r_nack_seen, + output wire w1c_out_axi_r_nack_seen, + input wire w1c_in_axi_r_nack_sent, + output wire w1c_out_axi_r_nack_sent, + //PSTATE_CONTROL + output wire [7:0] swi_tick_1us, + output wire [7:0] swi_inactivity_count, + output wire [2:0] swi_pstate_req, + output wire swi_pstate_ctrl_enable, + //APB_APP_CREDIT_IDS + output wire [7:0] swi_apb_cr_id, + output wire [7:0] swi_apb_crack_id, + output wire [7:0] swi_apb_ack_id, + output wire [7:0] swi_apb_nack_id, + //INT_APP_CREDIT_IDS + output wire [7:0] swi_int_cr_id, + output wire [7:0] swi_int_crack_id, + output wire [7:0] swi_int_ack_id, + output wire [7:0] swi_int_nack_id, + //INT_APP_PKT_ID_WC + output wire [7:0] swi_int_data_id, + output wire [15:0] swi_int_word_count, + //INT_OVERRIDES + input wire [23:0] int_override, + output wire [23:0] swi_int_override_muxed, + //GPIO_OVERRIDES + input wire [7:0] gpio_override, + output wire [7:0] swi_gpio_override_muxed, + //INT_GPIO_ENABLE + output wire [31:0] swi_int_gpio_enable, + //DEBUG_BUS_STATUS + output reg [31:0] debug_bus_ctrl_status, + + //DFT Ports (if used) + + // APB Interface + input wire RegReset, + input wire RegClk, + input wire PSEL, + input wire PENABLE, + input wire PWRITE, + output wire PSLVERR, + output wire PREADY, + input wire [(ADDR_WIDTH-1):0] PADDR, + input wire [31:0] PWDATA, + output wire [31:0] PRDATA +); + + //DFT Tieoffs (if not used) + wire dft_core_scan_mode = 1'b0; + wire dft_iddq_mode = 1'b0; + wire dft_hiz_mode = 1'b0; + wire dft_bscan_mode = 1'b0; + + //APB Setup/Access + wire [(ADDR_WIDTH-1):0] RegAddr_in; + reg [(ADDR_WIDTH-1):0] RegAddr; + wire [31:0] RegWrData_in; + reg [31:0] RegWrData; + wire RegWrEn_in; + reg RegWrEn_pq; + wire RegWrEn; + + assign RegAddr_in = PSEL ? PADDR : RegAddr; + + always @(posedge RegClk or posedge RegReset) begin + if (RegReset) begin + RegAddr <= {(ADDR_WIDTH){1'b0}}; + end else begin + RegAddr <= RegAddr_in; + end + end + + assign RegWrData_in = PSEL ? PWDATA : RegWrData; + + always @(posedge RegClk or posedge RegReset) begin + if (RegReset) begin + RegWrData <= 32'h00000000; + end else begin + RegWrData <= RegWrData_in; + end + end + + assign RegWrEn_in = PSEL & PWRITE; + + always @(posedge RegClk or posedge RegReset) begin + if (RegReset) begin + RegWrEn_pq <= 1'b0; + end else begin + RegWrEn_pq <= RegWrEn_in; + end + end + + assign RegWrEn = RegWrEn_pq & PENABLE; + + //assign PSLVERR = 1'b0; + assign PREADY = 1'b1; + + + + //Regs for Mux Override sel + reg reg_apb_app_enable_mux; + reg reg_axi_app_enable_mux; + reg reg_int_app_enable_mux; + reg reg_int_override_mux; + reg reg_gpio_override_mux; + + + + //--------------------------- + // APB_APP_ENABLE + // apb_app_enable - Enables the APB Application Layer + // apb_app_enable_mux - 1 - Use regsiter, 0 - use external logic + //--------------------------- + wire [31:0] APB_APP_ENABLE_reg_read; + reg reg_apb_app_enable; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_apb_app_enable <= 1'h0; + reg_apb_app_enable_mux <= 1'h0; + end else if(RegAddr == 'h0 && RegWrEn) begin + reg_apb_app_enable <= RegWrData[0]; + reg_apb_app_enable_mux <= RegWrData[1]; + end else begin + reg_apb_app_enable <= reg_apb_app_enable; + reg_apb_app_enable_mux <= reg_apb_app_enable_mux; + end + end + + assign APB_APP_ENABLE_reg_read = {30'h0, + reg_apb_app_enable_mux, + reg_apb_app_enable}; + + //----------------------- + + wire swi_apb_app_enable_muxed_pre; + slink_clock_mux u_slink_clock_mux_apb_app_enable ( + .clk0 ( apb_app_enable ), + .clk1 ( reg_apb_app_enable ), + .sel ( reg_apb_app_enable_mux ), + .clk_out ( swi_apb_app_enable_muxed_pre )); + + assign swi_apb_app_enable_muxed = swi_apb_app_enable_muxed_pre; + + //----------------------- + + + + + //--------------------------- + // AXI_APP_ENABLE + // axi_app_enable - Enables the AXI Application Layer + // axi_app_enable_mux - 1 - Use regsiter, 0 - use external logic + //--------------------------- + wire [31:0] AXI_APP_ENABLE_reg_read; + reg reg_axi_app_enable; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_axi_app_enable <= 1'h0; + reg_axi_app_enable_mux <= 1'h0; + end else if(RegAddr == 'h4 && RegWrEn) begin + reg_axi_app_enable <= RegWrData[0]; + reg_axi_app_enable_mux <= RegWrData[1]; + end else begin + reg_axi_app_enable <= reg_axi_app_enable; + reg_axi_app_enable_mux <= reg_axi_app_enable_mux; + end + end + + assign AXI_APP_ENABLE_reg_read = {30'h0, + reg_axi_app_enable_mux, + reg_axi_app_enable}; + + //----------------------- + + wire swi_axi_app_enable_muxed_pre; + slink_clock_mux u_slink_clock_mux_axi_app_enable ( + .clk0 ( axi_app_enable ), + .clk1 ( reg_axi_app_enable ), + .sel ( reg_axi_app_enable_mux ), + .clk_out ( swi_axi_app_enable_muxed_pre )); + + assign swi_axi_app_enable_muxed = swi_axi_app_enable_muxed_pre; + + //----------------------- + + + + + //--------------------------- + // INT_APP_ENABLE + // int_app_enable - Enables the Interrupt/GPIO Application Layer + // int_app_enable_mux - 1 - Use regsiter, 0 - use external logic + //--------------------------- + wire [31:0] INT_APP_ENABLE_reg_read; + reg reg_int_app_enable; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_int_app_enable <= 1'h0; + reg_int_app_enable_mux <= 1'h0; + end else if(RegAddr == 'h8 && RegWrEn) begin + reg_int_app_enable <= RegWrData[0]; + reg_int_app_enable_mux <= RegWrData[1]; + end else begin + reg_int_app_enable <= reg_int_app_enable; + reg_int_app_enable_mux <= reg_int_app_enable_mux; + end + end + + assign INT_APP_ENABLE_reg_read = {30'h0, + reg_int_app_enable_mux, + reg_int_app_enable}; + + //----------------------- + + wire swi_int_app_enable_muxed_pre; + slink_clock_mux u_slink_clock_mux_int_app_enable ( + .clk0 ( int_app_enable ), + .clk1 ( reg_int_app_enable ), + .sel ( reg_int_app_enable_mux ), + .clk_out ( swi_int_app_enable_muxed_pre )); + + assign swi_int_app_enable_muxed = swi_int_app_enable_muxed_pre; + + //----------------------- + + + + + //--------------------------- + // INTERRUPT_STATUS + // apb_nack_seen - APB Nack has been seen on this application layer (far-end saw an issue) + // apb_nack_sent - APB Nack has been sent from this application layer (near-end saw an issue) + // int_nack_seen - INT Nack has been seen on this application layer (far-end saw an issue) + // int_nack_sent - INT Nack has been sent from this application layer (near-end saw an issue) + // axi_aw_nack_seen - AXI AW Channel Nack has been seen on this application layer (far-end saw an issue) + // axi_aw_nack_sent - AXI AW Channel Nack has been sent from this application layer (near-end saw an issue) + // axi_w_nack_seen - AXI W Channel Nack has been seen on this application layer (far-end saw an issue) + // axi_w_nack_sent - AXI W Channel Nack has been sent from this application layer (near-end saw an issue) + // axi_b_nack_seen - AXI B Channel Nack has been seen on this application layer (far-end saw an issue) + // axi_b_nack_sent - AXI B Channel Nack has been sent from this application layer (near-end saw an issue) + // axi_ar_nack_seen - AXI AR Channel Nack has been seen on this application layer (far-end saw an issue) + // axi_ar_nack_sent - AXI AR Channel Nack has been sent from this application layer (near-end saw an issue) + // axi_r_nack_seen - AXI R Channel Nack has been seen on this application layer (far-end saw an issue) + // axi_r_nack_sent - AXI R Channel Nack has been sent from this application layer (near-end saw an issue) + //--------------------------- + wire [31:0] INTERRUPT_STATUS_reg_read; + reg reg_w1c_apb_nack_seen; + wire reg_w1c_in_apb_nack_seen_ff2; + reg reg_w1c_in_apb_nack_seen_ff3; + reg reg_w1c_apb_nack_sent; + wire reg_w1c_in_apb_nack_sent_ff2; + reg reg_w1c_in_apb_nack_sent_ff3; + reg reg_w1c_int_nack_seen; + wire reg_w1c_in_int_nack_seen_ff2; + reg reg_w1c_in_int_nack_seen_ff3; + reg reg_w1c_int_nack_sent; + wire reg_w1c_in_int_nack_sent_ff2; + reg reg_w1c_in_int_nack_sent_ff3; + reg reg_w1c_axi_aw_nack_seen; + wire reg_w1c_in_axi_aw_nack_seen_ff2; + reg reg_w1c_in_axi_aw_nack_seen_ff3; + reg reg_w1c_axi_aw_nack_sent; + wire reg_w1c_in_axi_aw_nack_sent_ff2; + reg reg_w1c_in_axi_aw_nack_sent_ff3; + reg reg_w1c_axi_w_nack_seen; + wire reg_w1c_in_axi_w_nack_seen_ff2; + reg reg_w1c_in_axi_w_nack_seen_ff3; + reg reg_w1c_axi_w_nack_sent; + wire reg_w1c_in_axi_w_nack_sent_ff2; + reg reg_w1c_in_axi_w_nack_sent_ff3; + reg reg_w1c_axi_b_nack_seen; + wire reg_w1c_in_axi_b_nack_seen_ff2; + reg reg_w1c_in_axi_b_nack_seen_ff3; + reg reg_w1c_axi_b_nack_sent; + wire reg_w1c_in_axi_b_nack_sent_ff2; + reg reg_w1c_in_axi_b_nack_sent_ff3; + reg reg_w1c_axi_ar_nack_seen; + wire reg_w1c_in_axi_ar_nack_seen_ff2; + reg reg_w1c_in_axi_ar_nack_seen_ff3; + reg reg_w1c_axi_ar_nack_sent; + wire reg_w1c_in_axi_ar_nack_sent_ff2; + reg reg_w1c_in_axi_ar_nack_sent_ff3; + reg reg_w1c_axi_r_nack_seen; + wire reg_w1c_in_axi_r_nack_seen_ff2; + reg reg_w1c_in_axi_r_nack_seen_ff3; + reg reg_w1c_axi_r_nack_sent; + wire reg_w1c_in_axi_r_nack_sent_ff2; + reg reg_w1c_in_axi_r_nack_sent_ff3; + + // apb_nack_seen W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_apb_nack_seen <= 1'h0; + reg_w1c_in_apb_nack_seen_ff3 <= 1'h0; + end else begin + reg_w1c_apb_nack_seen <= RegWrData[0] && reg_w1c_apb_nack_seen && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_apb_nack_seen_ff2 & ~reg_w1c_in_apb_nack_seen_ff3 ? 1'b1 : reg_w1c_apb_nack_seen); + reg_w1c_in_apb_nack_seen_ff3 <= reg_w1c_in_apb_nack_seen_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_apb_nack_seen ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_apb_nack_seen ), + .sig_out ( reg_w1c_in_apb_nack_seen_ff2 )); + + + // apb_nack_sent W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_apb_nack_sent <= 1'h0; + reg_w1c_in_apb_nack_sent_ff3 <= 1'h0; + end else begin + reg_w1c_apb_nack_sent <= RegWrData[1] && reg_w1c_apb_nack_sent && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_apb_nack_sent_ff2 & ~reg_w1c_in_apb_nack_sent_ff3 ? 1'b1 : reg_w1c_apb_nack_sent); + reg_w1c_in_apb_nack_sent_ff3 <= reg_w1c_in_apb_nack_sent_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_apb_nack_sent ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_apb_nack_sent ), + .sig_out ( reg_w1c_in_apb_nack_sent_ff2 )); + + + // int_nack_seen W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_int_nack_seen <= 1'h0; + reg_w1c_in_int_nack_seen_ff3 <= 1'h0; + end else begin + reg_w1c_int_nack_seen <= RegWrData[2] && reg_w1c_int_nack_seen && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_int_nack_seen_ff2 & ~reg_w1c_in_int_nack_seen_ff3 ? 1'b1 : reg_w1c_int_nack_seen); + reg_w1c_in_int_nack_seen_ff3 <= reg_w1c_in_int_nack_seen_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_int_nack_seen ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_int_nack_seen ), + .sig_out ( reg_w1c_in_int_nack_seen_ff2 )); + + + // int_nack_sent W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_int_nack_sent <= 1'h0; + reg_w1c_in_int_nack_sent_ff3 <= 1'h0; + end else begin + reg_w1c_int_nack_sent <= RegWrData[3] && reg_w1c_int_nack_sent && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_int_nack_sent_ff2 & ~reg_w1c_in_int_nack_sent_ff3 ? 1'b1 : reg_w1c_int_nack_sent); + reg_w1c_in_int_nack_sent_ff3 <= reg_w1c_in_int_nack_sent_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_int_nack_sent ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_int_nack_sent ), + .sig_out ( reg_w1c_in_int_nack_sent_ff2 )); + + + // axi_aw_nack_seen W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_aw_nack_seen <= 1'h0; + reg_w1c_in_axi_aw_nack_seen_ff3 <= 1'h0; + end else begin + reg_w1c_axi_aw_nack_seen <= RegWrData[4] && reg_w1c_axi_aw_nack_seen && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_aw_nack_seen_ff2 & ~reg_w1c_in_axi_aw_nack_seen_ff3 ? 1'b1 : reg_w1c_axi_aw_nack_seen); + reg_w1c_in_axi_aw_nack_seen_ff3 <= reg_w1c_in_axi_aw_nack_seen_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_aw_nack_seen ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_aw_nack_seen ), + .sig_out ( reg_w1c_in_axi_aw_nack_seen_ff2 )); + + + // axi_aw_nack_sent W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_aw_nack_sent <= 1'h0; + reg_w1c_in_axi_aw_nack_sent_ff3 <= 1'h0; + end else begin + reg_w1c_axi_aw_nack_sent <= RegWrData[5] && reg_w1c_axi_aw_nack_sent && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_aw_nack_sent_ff2 & ~reg_w1c_in_axi_aw_nack_sent_ff3 ? 1'b1 : reg_w1c_axi_aw_nack_sent); + reg_w1c_in_axi_aw_nack_sent_ff3 <= reg_w1c_in_axi_aw_nack_sent_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_aw_nack_sent ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_aw_nack_sent ), + .sig_out ( reg_w1c_in_axi_aw_nack_sent_ff2 )); + + + // axi_w_nack_seen W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_w_nack_seen <= 1'h0; + reg_w1c_in_axi_w_nack_seen_ff3 <= 1'h0; + end else begin + reg_w1c_axi_w_nack_seen <= RegWrData[6] && reg_w1c_axi_w_nack_seen && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_w_nack_seen_ff2 & ~reg_w1c_in_axi_w_nack_seen_ff3 ? 1'b1 : reg_w1c_axi_w_nack_seen); + reg_w1c_in_axi_w_nack_seen_ff3 <= reg_w1c_in_axi_w_nack_seen_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_w_nack_seen ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_w_nack_seen ), + .sig_out ( reg_w1c_in_axi_w_nack_seen_ff2 )); + + + // axi_w_nack_sent W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_w_nack_sent <= 1'h0; + reg_w1c_in_axi_w_nack_sent_ff3 <= 1'h0; + end else begin + reg_w1c_axi_w_nack_sent <= RegWrData[7] && reg_w1c_axi_w_nack_sent && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_w_nack_sent_ff2 & ~reg_w1c_in_axi_w_nack_sent_ff3 ? 1'b1 : reg_w1c_axi_w_nack_sent); + reg_w1c_in_axi_w_nack_sent_ff3 <= reg_w1c_in_axi_w_nack_sent_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_w_nack_sent ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_w_nack_sent ), + .sig_out ( reg_w1c_in_axi_w_nack_sent_ff2 )); + + + // axi_b_nack_seen W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_b_nack_seen <= 1'h0; + reg_w1c_in_axi_b_nack_seen_ff3 <= 1'h0; + end else begin + reg_w1c_axi_b_nack_seen <= RegWrData[8] && reg_w1c_axi_b_nack_seen && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_b_nack_seen_ff2 & ~reg_w1c_in_axi_b_nack_seen_ff3 ? 1'b1 : reg_w1c_axi_b_nack_seen); + reg_w1c_in_axi_b_nack_seen_ff3 <= reg_w1c_in_axi_b_nack_seen_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_b_nack_seen ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_b_nack_seen ), + .sig_out ( reg_w1c_in_axi_b_nack_seen_ff2 )); + + + // axi_b_nack_sent W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_b_nack_sent <= 1'h0; + reg_w1c_in_axi_b_nack_sent_ff3 <= 1'h0; + end else begin + reg_w1c_axi_b_nack_sent <= RegWrData[9] && reg_w1c_axi_b_nack_sent && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_b_nack_sent_ff2 & ~reg_w1c_in_axi_b_nack_sent_ff3 ? 1'b1 : reg_w1c_axi_b_nack_sent); + reg_w1c_in_axi_b_nack_sent_ff3 <= reg_w1c_in_axi_b_nack_sent_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_b_nack_sent ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_b_nack_sent ), + .sig_out ( reg_w1c_in_axi_b_nack_sent_ff2 )); + + + // axi_ar_nack_seen W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_ar_nack_seen <= 1'h0; + reg_w1c_in_axi_ar_nack_seen_ff3 <= 1'h0; + end else begin + reg_w1c_axi_ar_nack_seen <= RegWrData[10] && reg_w1c_axi_ar_nack_seen && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_ar_nack_seen_ff2 & ~reg_w1c_in_axi_ar_nack_seen_ff3 ? 1'b1 : reg_w1c_axi_ar_nack_seen); + reg_w1c_in_axi_ar_nack_seen_ff3 <= reg_w1c_in_axi_ar_nack_seen_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_ar_nack_seen ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_ar_nack_seen ), + .sig_out ( reg_w1c_in_axi_ar_nack_seen_ff2 )); + + + // axi_ar_nack_sent W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_ar_nack_sent <= 1'h0; + reg_w1c_in_axi_ar_nack_sent_ff3 <= 1'h0; + end else begin + reg_w1c_axi_ar_nack_sent <= RegWrData[11] && reg_w1c_axi_ar_nack_sent && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_ar_nack_sent_ff2 & ~reg_w1c_in_axi_ar_nack_sent_ff3 ? 1'b1 : reg_w1c_axi_ar_nack_sent); + reg_w1c_in_axi_ar_nack_sent_ff3 <= reg_w1c_in_axi_ar_nack_sent_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_ar_nack_sent ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_ar_nack_sent ), + .sig_out ( reg_w1c_in_axi_ar_nack_sent_ff2 )); + + + // axi_r_nack_seen W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_r_nack_seen <= 1'h0; + reg_w1c_in_axi_r_nack_seen_ff3 <= 1'h0; + end else begin + reg_w1c_axi_r_nack_seen <= RegWrData[12] && reg_w1c_axi_r_nack_seen && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_r_nack_seen_ff2 & ~reg_w1c_in_axi_r_nack_seen_ff3 ? 1'b1 : reg_w1c_axi_r_nack_seen); + reg_w1c_in_axi_r_nack_seen_ff3 <= reg_w1c_in_axi_r_nack_seen_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_r_nack_seen ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_r_nack_seen ), + .sig_out ( reg_w1c_in_axi_r_nack_seen_ff2 )); + + + // axi_r_nack_sent W1C Logic + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_w1c_axi_r_nack_sent <= 1'h0; + reg_w1c_in_axi_r_nack_sent_ff3 <= 1'h0; + end else begin + reg_w1c_axi_r_nack_sent <= RegWrData[13] && reg_w1c_axi_r_nack_sent && (RegAddr == 'hc) && RegWrEn ? 1'b0 : (reg_w1c_in_axi_r_nack_sent_ff2 & ~reg_w1c_in_axi_r_nack_sent_ff3 ? 1'b1 : reg_w1c_axi_r_nack_sent); + reg_w1c_in_axi_r_nack_sent_ff3 <= reg_w1c_in_axi_r_nack_sent_ff2; + end + end + + slink_demet_reset u_slink_demet_reset_axi_r_nack_sent ( + .clk ( RegClk ), + .reset ( RegReset ), + .sig_in ( w1c_in_axi_r_nack_sent ), + .sig_out ( reg_w1c_in_axi_r_nack_sent_ff2 )); + + assign INTERRUPT_STATUS_reg_read = {18'h0, + reg_w1c_axi_r_nack_sent, + reg_w1c_axi_r_nack_seen, + reg_w1c_axi_ar_nack_sent, + reg_w1c_axi_ar_nack_seen, + reg_w1c_axi_b_nack_sent, + reg_w1c_axi_b_nack_seen, + reg_w1c_axi_w_nack_sent, + reg_w1c_axi_w_nack_seen, + reg_w1c_axi_aw_nack_sent, + reg_w1c_axi_aw_nack_seen, + reg_w1c_int_nack_sent, + reg_w1c_int_nack_seen, + reg_w1c_apb_nack_sent, + reg_w1c_apb_nack_seen}; + + //----------------------- + assign w1c_out_apb_nack_seen = reg_w1c_apb_nack_seen; + //----------------------- + assign w1c_out_apb_nack_sent = reg_w1c_apb_nack_sent; + //----------------------- + assign w1c_out_int_nack_seen = reg_w1c_int_nack_seen; + //----------------------- + assign w1c_out_int_nack_sent = reg_w1c_int_nack_sent; + //----------------------- + assign w1c_out_axi_aw_nack_seen = reg_w1c_axi_aw_nack_seen; + //----------------------- + assign w1c_out_axi_aw_nack_sent = reg_w1c_axi_aw_nack_sent; + //----------------------- + assign w1c_out_axi_w_nack_seen = reg_w1c_axi_w_nack_seen; + //----------------------- + assign w1c_out_axi_w_nack_sent = reg_w1c_axi_w_nack_sent; + //----------------------- + assign w1c_out_axi_b_nack_seen = reg_w1c_axi_b_nack_seen; + //----------------------- + assign w1c_out_axi_b_nack_sent = reg_w1c_axi_b_nack_sent; + //----------------------- + assign w1c_out_axi_ar_nack_seen = reg_w1c_axi_ar_nack_seen; + //----------------------- + assign w1c_out_axi_ar_nack_sent = reg_w1c_axi_ar_nack_sent; + //----------------------- + assign w1c_out_axi_r_nack_seen = reg_w1c_axi_r_nack_seen; + //----------------------- + assign w1c_out_axi_r_nack_sent = reg_w1c_axi_r_nack_sent; + + + + + //--------------------------- + // PSTATE_CONTROL + // tick_1us - Number of refclk cycles to equal 1us + // inactivity_count - Number of microseconds before starting a PState transition + // pstate_req - PState to transition to. If multiple bits are set, the lowest is used. [0] - P1, [1] - P2, [2] - P3. + // pstate_ctrl_enable - Enables the PSTATE Controller + //--------------------------- + wire [31:0] PSTATE_CONTROL_reg_read; + reg [7:0] reg_tick_1us; + reg [7:0] reg_inactivity_count; + reg [2:0] reg_pstate_req; + reg reg_pstate_ctrl_enable; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_tick_1us <= 8'h27; + reg_inactivity_count <= 8'h5; + reg_pstate_req <= 3'h2; + reg_pstate_ctrl_enable <= PSTATE_CTRL_ENABLE_RESET_PARAM; + end else if(RegAddr == 'h10 && RegWrEn) begin + reg_tick_1us <= RegWrData[7:0]; + reg_inactivity_count <= RegWrData[15:8]; + reg_pstate_req <= RegWrData[18:16]; + reg_pstate_ctrl_enable <= RegWrData[19]; + end else begin + reg_tick_1us <= reg_tick_1us; + reg_inactivity_count <= reg_inactivity_count; + reg_pstate_req <= reg_pstate_req; + reg_pstate_ctrl_enable <= reg_pstate_ctrl_enable; + end + end + + assign PSTATE_CONTROL_reg_read = {12'h0, + reg_pstate_ctrl_enable, + reg_pstate_req, + reg_inactivity_count, + reg_tick_1us}; + + //----------------------- + assign swi_tick_1us = reg_tick_1us; + + //----------------------- + assign swi_inactivity_count = reg_inactivity_count; + + //----------------------- + assign swi_pstate_req = reg_pstate_req; + + //----------------------- + assign swi_pstate_ctrl_enable = reg_pstate_ctrl_enable; + + + + + + //--------------------------- + // APB_APP_CREDIT_IDS + // apb_cr_id - Credit Request Data ID for APB Application Channel + // apb_crack_id - Credit Request Data Acknowledgement ID for APB Application Channel + // apb_ack_id - Acknowledgement ID for APB Application Channel + // apb_nack_id - Non-Acknowledgement ID for APB Application Channel + //--------------------------- + wire [31:0] APB_APP_CREDIT_IDS_reg_read; + reg [7:0] reg_apb_cr_id; + reg [7:0] reg_apb_crack_id; + reg [7:0] reg_apb_ack_id; + reg [7:0] reg_apb_nack_id; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_apb_cr_id <= 8'h8; + reg_apb_crack_id <= 8'h9; + reg_apb_ack_id <= 8'ha; + reg_apb_nack_id <= 8'hb; + end else if(RegAddr == 'h14 && RegWrEn) begin + reg_apb_cr_id <= RegWrData[7:0]; + reg_apb_crack_id <= RegWrData[15:8]; + reg_apb_ack_id <= RegWrData[23:16]; + reg_apb_nack_id <= RegWrData[31:24]; + end else begin + reg_apb_cr_id <= reg_apb_cr_id; + reg_apb_crack_id <= reg_apb_crack_id; + reg_apb_ack_id <= reg_apb_ack_id; + reg_apb_nack_id <= reg_apb_nack_id; + end + end + + assign APB_APP_CREDIT_IDS_reg_read = { reg_apb_nack_id, + reg_apb_ack_id, + reg_apb_crack_id, + reg_apb_cr_id}; + + //----------------------- + assign swi_apb_cr_id = reg_apb_cr_id; + + //----------------------- + assign swi_apb_crack_id = reg_apb_crack_id; + + //----------------------- + assign swi_apb_ack_id = reg_apb_ack_id; + + //----------------------- + assign swi_apb_nack_id = reg_apb_nack_id; + + + + + + //--------------------------- + // INT_APP_CREDIT_IDS + // int_cr_id - Credit Request Data ID for INT Application Channel + // int_crack_id - Credit Request Data Acknowledgement ID for INT Application Channel + // int_ack_id - Acknowledgement ID for INT Application Channel + // int_nack_id - Non-Acknowledgement ID for INT Application Channel + //--------------------------- + wire [31:0] INT_APP_CREDIT_IDS_reg_read; + reg [7:0] reg_int_cr_id; + reg [7:0] reg_int_crack_id; + reg [7:0] reg_int_ack_id; + reg [7:0] reg_int_nack_id; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_int_cr_id <= 8'hc; + reg_int_crack_id <= 8'hd; + reg_int_ack_id <= 8'he; + reg_int_nack_id <= 8'hf; + end else if(RegAddr == 'h18 && RegWrEn) begin + reg_int_cr_id <= RegWrData[7:0]; + reg_int_crack_id <= RegWrData[15:8]; + reg_int_ack_id <= RegWrData[23:16]; + reg_int_nack_id <= RegWrData[31:24]; + end else begin + reg_int_cr_id <= reg_int_cr_id; + reg_int_crack_id <= reg_int_crack_id; + reg_int_ack_id <= reg_int_ack_id; + reg_int_nack_id <= reg_int_nack_id; + end + end + + assign INT_APP_CREDIT_IDS_reg_read = { reg_int_nack_id, + reg_int_ack_id, + reg_int_crack_id, + reg_int_cr_id}; + + //----------------------- + assign swi_int_cr_id = reg_int_cr_id; + + //----------------------- + assign swi_int_crack_id = reg_int_crack_id; + + //----------------------- + assign swi_int_ack_id = reg_int_ack_id; + + //----------------------- + assign swi_int_nack_id = reg_int_nack_id; + + + + + + //--------------------------- + // INT_APP_PKT_ID_WC + // int_data_id - INT Data ID + // int_word_count - INT Word Count + //--------------------------- + wire [31:0] INT_APP_PKT_ID_WC_reg_read; + reg [7:0] reg_int_data_id; + reg [15:0] reg_int_word_count; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_int_data_id <= 8'h50; + reg_int_word_count <= 16'h3; + end else if(RegAddr == 'h1c && RegWrEn) begin + reg_int_data_id <= RegWrData[7:0]; + reg_int_word_count <= RegWrData[23:8]; + end else begin + reg_int_data_id <= reg_int_data_id; + reg_int_word_count <= reg_int_word_count; + end + end + + assign INT_APP_PKT_ID_WC_reg_read = {8'h0, + reg_int_word_count, + reg_int_data_id}; + + //----------------------- + assign swi_int_data_id = reg_int_data_id; + + //----------------------- + assign swi_int_word_count = reg_int_word_count; + + + + + + //--------------------------- + // INT_OVERRIDES + // int_override - + // int_override_mux - + //--------------------------- + wire [31:0] INT_OVERRIDES_reg_read; + reg [23:0] reg_int_override; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_int_override <= 24'h0; + reg_int_override_mux <= 1'h0; + end else if(RegAddr == 'h20 && RegWrEn) begin + reg_int_override <= RegWrData[23:0]; + reg_int_override_mux <= RegWrData[24]; + end else begin + reg_int_override <= reg_int_override; + reg_int_override_mux <= reg_int_override_mux; + end + end + + assign INT_OVERRIDES_reg_read = {7'h0, + reg_int_override_mux, + reg_int_override}; + + //----------------------- + + wire [23:0] swi_int_override_muxed_pre; + slink_clock_mux u_slink_clock_mux_int_override[23:0] ( + .clk0 ( int_override ), + .clk1 ( reg_int_override ), + .sel ( reg_int_override_mux ), + .clk_out ( swi_int_override_muxed_pre )); + + assign swi_int_override_muxed = swi_int_override_muxed_pre; + + //----------------------- + + + + + //--------------------------- + // GPIO_OVERRIDES + // gpio_override - + // gpio_override_mux - + //--------------------------- + wire [31:0] GPIO_OVERRIDES_reg_read; + reg [7:0] reg_gpio_override; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_gpio_override <= 8'h0; + reg_gpio_override_mux <= 1'h0; + end else if(RegAddr == 'h24 && RegWrEn) begin + reg_gpio_override <= RegWrData[7:0]; + reg_gpio_override_mux <= RegWrData[8]; + end else begin + reg_gpio_override <= reg_gpio_override; + reg_gpio_override_mux <= reg_gpio_override_mux; + end + end + + assign GPIO_OVERRIDES_reg_read = {23'h0, + reg_gpio_override_mux, + reg_gpio_override}; + + //----------------------- + + wire [7:0] swi_gpio_override_muxed_pre; + slink_clock_mux u_slink_clock_mux_gpio_override[7:0] ( + .clk0 ( gpio_override ), + .clk1 ( reg_gpio_override ), + .sel ( reg_gpio_override_mux ), + .clk_out ( swi_gpio_override_muxed_pre )); + + assign swi_gpio_override_muxed = swi_gpio_override_muxed_pre; + + //----------------------- + + + + + //--------------------------- + // INT_GPIO_ENABLE + // int_gpio_enable - Allows user to gate the Interrupts/GPIO signals in the event of a spurrious signal + //--------------------------- + wire [31:0] INT_GPIO_ENABLE_reg_read; + reg [31:0] reg_int_gpio_enable; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_int_gpio_enable <= 32'hffffffff; + end else if(RegAddr == 'h28 && RegWrEn) begin + reg_int_gpio_enable <= RegWrData[31:0]; + end else begin + reg_int_gpio_enable <= reg_int_gpio_enable; + end + end + + assign INT_GPIO_ENABLE_reg_read = { reg_int_gpio_enable}; + + //----------------------- + assign swi_int_gpio_enable = reg_int_gpio_enable; + + + + + + //--------------------------- + // DEBUG_BUS_CTRL + // DEBUG_BUS_CTRL_SEL - Select signal for DEBUG_BUS_CTRL + //--------------------------- + wire [31:0] DEBUG_BUS_CTRL_reg_read; + reg [2:0] reg_debug_bus_ctrl_sel; + wire [2:0] swi_debug_bus_ctrl_sel; + + always @(posedge RegClk or posedge RegReset) begin + if(RegReset) begin + reg_debug_bus_ctrl_sel <= 3'h0; + end else if(RegAddr == 'h2c && RegWrEn) begin + reg_debug_bus_ctrl_sel <= RegWrData[2:0]; + end else begin + reg_debug_bus_ctrl_sel <= reg_debug_bus_ctrl_sel; + end + end + + assign DEBUG_BUS_CTRL_reg_read = {29'h0, + reg_debug_bus_ctrl_sel}; + + //----------------------- + assign swi_debug_bus_ctrl_sel = reg_debug_bus_ctrl_sel; + + + + + + //--------------------------- + // DEBUG_BUS_STATUS + // DEBUG_BUS_CTRL_STATUS - Status output for DEBUG_BUS_STATUS + //--------------------------- + wire [31:0] DEBUG_BUS_STATUS_reg_read; + + //Debug bus control logic + always @(*) begin + case(swi_debug_bus_ctrl_sel) + 'd0 : debug_bus_ctrl_status = {31'd0, swi_apb_app_enable_muxed}; + 'd1 : debug_bus_ctrl_status = {31'd0, swi_axi_app_enable_muxed}; + 'd2 : debug_bus_ctrl_status = {31'd0, swi_int_app_enable_muxed}; + 'd3 : debug_bus_ctrl_status = {8'd0, swi_int_override_muxed}; + 'd4 : debug_bus_ctrl_status = {24'd0, swi_gpio_override_muxed}; + default : debug_bus_ctrl_status = 32'd0; + endcase + end + + assign DEBUG_BUS_STATUS_reg_read = { debug_bus_ctrl_status}; + + //----------------------- + + + + + //--------------------------- + // PRDATA Selection + //--------------------------- + reg [31:0] prdata_sel; + + always @(*) begin + case(RegAddr) + 'h0 : prdata_sel = APB_APP_ENABLE_reg_read; + 'h4 : prdata_sel = AXI_APP_ENABLE_reg_read; + 'h8 : prdata_sel = INT_APP_ENABLE_reg_read; + 'hc : prdata_sel = INTERRUPT_STATUS_reg_read; + 'h10 : prdata_sel = PSTATE_CONTROL_reg_read; + 'h14 : prdata_sel = APB_APP_CREDIT_IDS_reg_read; + 'h18 : prdata_sel = INT_APP_CREDIT_IDS_reg_read; + 'h1c : prdata_sel = INT_APP_PKT_ID_WC_reg_read; + 'h20 : prdata_sel = INT_OVERRIDES_reg_read; + 'h24 : prdata_sel = GPIO_OVERRIDES_reg_read; + 'h28 : prdata_sel = INT_GPIO_ENABLE_reg_read; + 'h2c : prdata_sel = DEBUG_BUS_CTRL_reg_read; + 'h30 : prdata_sel = DEBUG_BUS_STATUS_reg_read; + + default : prdata_sel = 32'd0; + endcase + end + + assign PRDATA = prdata_sel; + + + + + //--------------------------- + // PSLVERR Detection + //--------------------------- + reg pslverr_pre; + + always @(*) begin + case(RegAddr) + 'h0 : pslverr_pre = 1'b0; + 'h4 : pslverr_pre = 1'b0; + 'h8 : pslverr_pre = 1'b0; + 'hc : pslverr_pre = 1'b0; + 'h10 : pslverr_pre = 1'b0; + 'h14 : pslverr_pre = 1'b0; + 'h18 : pslverr_pre = 1'b0; + 'h1c : pslverr_pre = 1'b0; + 'h20 : pslverr_pre = 1'b0; + 'h24 : pslverr_pre = 1'b0; + 'h28 : pslverr_pre = 1'b0; + 'h2c : pslverr_pre = 1'b0; + 'h30 : pslverr_pre = 1'b0; + + default : pslverr_pre = 1'b1; + endcase + end + + assign PSLVERR = pslverr_pre; + +endmodule diff --git a/rtl/stacks/slink_apb_gpio_top.v b/rtl/stacks/slink_apb_gpio_top.v new file mode 100644 index 0000000..41f8538 --- /dev/null +++ b/rtl/stacks/slink_apb_gpio_top.v @@ -0,0 +1,339 @@ +module slink_apb_gpio_top #( + parameter IS_HOST = 1, + parameter IO_DATA_WIDTH = 1 +)( + input wire core_scan_mode, + input wire core_scan_clk, + input wire core_scan_asyncrst_ctrl, + input wire core_scan_shift, + input wire core_scan_in, + output wire core_scan_out, + + input wire apb_clk, + input wire apb_reset, + input wire apb_psel, + input wire apb_penable, + input wire apb_pwrite, + input wire [31:0] apb_pwdata, + input wire [9:0] apb_paddr, + output wire apb_pslverr, + output wire apb_pready, + output wire [31:0] apb_prdata, + + //------------------------------- + // Target APB + //------------------------------- + input wire apb_tgt_psel, + input wire apb_tgt_penable, + input wire apb_tgt_pwrite, + input wire [31:0] apb_tgt_pwdata, + input wire [31:0] apb_tgt_paddr, + output wire apb_tgt_pslverr, + output wire apb_tgt_pready, + output wire [31:0] apb_tgt_prdata, + + //------------------------------- + // Initiator APB + //------------------------------- + output wire apb_ini_psel, + output wire apb_ini_penable, + output wire apb_ini_pwrite, + output wire [31:0] apb_ini_pwdata, + output wire [31:0] apb_ini_paddr, + input wire apb_ini_pslverr, + input wire apb_ini_pready, + input wire [31:0] apb_ini_prdata, + + input wire por_reset, + input wire refclk, + input wire hsclk, + + input wire slink_rx_clk, + output wire slink_tx_clk, + output wire [IO_DATA_WIDTH-1:0] slink_tx_data, + input wire [IO_DATA_WIDTH-1:0] slink_rx_data, + + output wire slink_gpio_reset_n_oen, + input wire slink_gpio_reset_n, + output wire slink_gpio_wake_n_oen, + input wire slink_gpio_wake_n + +); + +localparam TX_APP_DATA_WIDTH = 128; +localparam RX_APP_DATA_WIDTH = 128; + +wire link_clk; +wire link_reset; +wire tx_sop; +wire [7:0] tx_data_id; +wire [15:0] tx_word_count; +wire [TX_APP_DATA_WIDTH-1:0] tx_app_data; +wire tx_advance; +wire rx_sop; +wire [7:0] rx_data_id; +wire [15:0] rx_word_count; +wire [RX_APP_DATA_WIDTH-1:0] rx_app_data; +wire rx_valid; +wire rx_crc_corrupted; +wire interrupt; +wire p1_req; +wire p2_req; +wire p3_req; +wire in_px_state; +wire in_reset_state; +wire phy_clk; +wire phy_clk_en; +wire phy_clk_idle; +wire phy_clk_ready; +wire phy_tx_en; +wire phy_tx_ready; +wire phy_tx_dirdy; +wire [7:0] phy_tx_data; +wire phy_rx_en; +wire phy_rx_clk; +wire phy_rx_ready; +wire phy_rx_valid; +wire phy_rx_dordy; +wire phy_rx_align; +wire [7:0] phy_rx_data; + + +wire apb_psel_app; +wire apb_penable_app; +wire apb_pwrite_app; +wire [31:0] apb_pwdata_app; +wire [7:0] apb_paddr_app; +wire apb_pslverr_app; +wire apb_pready_app; +wire [31:0] apb_prdata_app; + +wire apb_psel_link; +wire apb_penable_link; +wire apb_pwrite_link; +wire [31:0] apb_pwdata_link; +wire [8:0] apb_paddr_link; +wire apb_pslverr_link; +wire apb_pready_link; +wire [31:0] apb_prdata_link; + + +wire apb_clk_scan; +wire apb_reset_scan; +slink_clock_mux u_slink_clock_mux_apb_clk ( + .clk0 ( apb_clk ), + .clk1 ( core_scan_clk ), + .sel ( core_scan_mode ), + .clk_out ( apb_clk_scan )); + +slink_reset_sync u_slink_reset_sync_apb_reset ( + .clk ( apb_clk_scan ), + .scan_ctrl ( core_scan_asyncrst_ctrl ), + .reset_in ( apb_reset ), + .reset_out ( apb_reset_scan )); + +localparam APB_LINK = 2'h0, + APB_LINK_BIST = 2'h1, + APB_APP = 2'h2; + + +assign apb_psel_app = (apb_paddr[9:8] == APB_APP) && apb_psel; +assign apb_penable_app = (apb_paddr[9:8] == APB_APP) && apb_penable; +assign apb_pwrite_app = (apb_paddr[9:8] == APB_APP) && apb_pwrite; +assign apb_paddr_app = apb_paddr[7:0]; +assign apb_pwdata_app = apb_pwdata; + +assign apb_psel_link = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) && apb_psel; +assign apb_penable_link = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) && apb_penable; +assign apb_pwrite_link = (apb_paddr[9:8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) && apb_pwrite; +assign apb_paddr_link = apb_paddr[8:0]; +assign apb_pwdata_link = apb_pwdata; + +assign apb_prdata = (apb_paddr[8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) ? apb_prdata_link : apb_prdata_app; +assign apb_pready = (apb_paddr[8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) ? apb_pready_link : apb_pready_app; +assign apb_pslverr = (apb_paddr[8] == APB_LINK || apb_paddr[9:8] == APB_LINK_BIST) ? apb_pslverr_link : apb_pslverr_app; + +slink_apb_top #( + //parameters + .APB_TARGET ( IS_HOST ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ) +) u_slink_apb_top ( + .apb_clk ( apb_clk_scan ), + .apb_reset ( apb_reset_scan ), + .apb_psel ( apb_psel_app ), + .apb_penable ( apb_penable_app ), + .apb_pwrite ( apb_pwrite_app ), + .apb_pwdata ( apb_pwdata_app ), + .apb_paddr ( apb_paddr_app ), + .apb_pslverr ( apb_pslverr_app ), + .apb_pready ( apb_pready_app ), + .apb_prdata ( apb_prdata_app ), + .apb_tgt_psel ( apb_tgt_psel ), + .apb_tgt_penable ( apb_tgt_penable ), + .apb_tgt_pwrite ( apb_tgt_pwrite ), + .apb_tgt_pwdata ( apb_tgt_pwdata ), + .apb_tgt_paddr ( apb_tgt_paddr ), + .apb_tgt_pslverr ( apb_tgt_pslverr ), + .apb_tgt_pready ( apb_tgt_pready ), + .apb_tgt_prdata ( apb_tgt_prdata ), + .apb_ini_psel ( apb_ini_psel ), + .apb_ini_penable ( apb_ini_penable ), + .apb_ini_pwrite ( apb_ini_pwrite ), + .apb_ini_pwdata ( apb_ini_pwdata ), + .apb_ini_paddr ( apb_ini_paddr ), + .apb_ini_pslverr ( apb_ini_pslverr ), + .apb_ini_pready ( apb_ini_pready ), + .apb_ini_prdata ( apb_ini_prdata ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted )); + + +assign p1_req = 1'b0; +assign p2_req = 1'b0; +assign p3_req = 1'b0; + +slink #( + //parameters + .DESKEW_FIFO_DEPTH ( 4 ), + .INCLUDE_BIST ( 1 ), + .LTSSM_REGISTER_TXDATA ( 0 ), + .NUM_RX_LANES ( 1 ), + .NUM_TX_LANES ( 1 ), + .P1_TS1_RX_RESET ( 1 ), + .P1_TS1_TX_RESET ( 1 ), + .P1_TS2_RX_RESET ( 1 ), + .P1_TS2_TX_RESET ( 1 ), + .P2_TS1_RX_RESET ( 1 ), + .P2_TS1_TX_RESET ( 1 ), + .P2_TS2_RX_RESET ( 1 ), + .P2_TS2_TX_RESET ( 1 ), + .P3R_TS1_RX_RESET ( 1 ), + .P3R_TS1_TX_RESET ( 1 ), + .P3R_TS2_RX_RESET ( 1 ), + .P3R_TS2_TX_RESET ( 1 ), + .PHY_DATA_WIDTH ( 8 ), + .PX_CLK_TRAIL_RESET ( 16 ), + .RX_APP_DATA_WIDTH ( RX_APP_DATA_WIDTH ), + .START_IN_ONE_LANE ( 1 ), + .SYNC_FREQ_RESET ( 8 ), + .TX_APP_DATA_WIDTH ( TX_APP_DATA_WIDTH ) +) u_slink ( + .core_scan_mode ( core_scan_mode ), + .core_scan_clk ( core_scan_clk ), + .core_scan_asyncrst_ctrl ( core_scan_asyncrst_ctrl ), + .apb_clk ( apb_clk_scan ), + .apb_reset ( apb_reset_scan ), + .apb_paddr ( apb_paddr_link ), + .apb_pwrite ( apb_pwrite_link ), + .apb_psel ( apb_psel_link ), + .apb_penable ( apb_penable_link ), + .apb_pwdata ( apb_pwdata_link ), + .apb_prdata ( apb_prdata_link ), + .apb_pready ( apb_pready_link ), + .apb_pslverr ( apb_pslverr_link ), + .link_clk ( link_clk ), + .link_reset ( link_reset ), + .slink_enable ( ~por_reset ), + .por_reset ( por_reset ), + .tx_sop ( tx_sop ), + .tx_data_id ( tx_data_id ), + .tx_word_count ( tx_word_count ), + .tx_app_data ( tx_app_data ), + .tx_advance ( tx_advance ), + .rx_sop ( rx_sop ), + .rx_data_id ( rx_data_id ), + .rx_word_count ( rx_word_count ), + .rx_app_data ( rx_app_data ), + .rx_valid ( rx_valid ), + .rx_crc_corrupted ( rx_crc_corrupted ), + .interrupt ( interrupt ), + .p1_req ( p1_req ), + .p2_req ( p2_req ), + .p3_req ( p3_req ), + .in_px_state ( in_px_state ), + .in_reset_state ( in_reset_state ), + .slink_gpio_reset_n_oen ( slink_gpio_reset_n_oen ), + .slink_gpio_reset_n ( slink_gpio_reset_n ), + .slink_gpio_wake_n_oen ( slink_gpio_wake_n_oen ), + .slink_gpio_wake_n ( slink_gpio_wake_n ), + .refclk ( refclk ), + .phy_clk ( phy_clk ), + .phy_clk_en ( phy_clk_en ), + .phy_clk_idle ( phy_clk_idle ), + .phy_clk_ready ( phy_clk_ready ), + .phy_tx_en ( phy_tx_en ), + .phy_tx_ready ( phy_tx_ready ), + .phy_tx_dirdy ( 1'b1 ), + .phy_tx_data ( phy_tx_data ), + .phy_rx_en ( phy_rx_en ), + .phy_rx_clk ( phy_rx_clk ), + .phy_rx_ready ( phy_rx_ready ), + .phy_rx_valid ( phy_rx_valid ), + .phy_rx_dordy ( 1'b1 ), + .phy_rx_align ( phy_rx_align ), + .phy_rx_data ( phy_rx_data )); + + +assign phy_rx_clk = phy_clk; + +wire slink_base_serial_clk; +generate + if(IS_HOST) begin + slink_clock_mux u_slink_clock_mux_highspeed_clock ( + .clk0 ( hsclk ), + .clk1 ( core_scan_clk ), + .sel ( core_scan_mode ), + .clk_out ( slink_base_serial_clk )); + end else begin + slink_clock_mux u_slink_clock_mux_highspeed_clock ( + .clk0 ( slink_rx_clk ), + .clk1 ( core_scan_clk ), + .sel ( core_scan_mode ), + .clk_out ( slink_base_serial_clk )); + end +endgenerate + + +wire por_reset_serial_clk; +slink_reset_sync u_slink_reset_sync_hs_clk_porreset ( + .clk ( slink_base_serial_clk ), + .scan_ctrl ( core_scan_asyncrst_ctrl ), + .reset_in ( por_reset ), + .reset_out ( por_reset_serial_clk )); + +slink_gpio_serdes #( + //parameters + .IO_DATA_WIDTH ( IO_DATA_WIDTH ), + .IS_MASTER ( IS_HOST ), + .PAR_DATA_WIDTH ( 8 ) +) u_slink_gpio_serdes ( + .core_scan_mode ( core_scan_mode ), + .serial_clk ( slink_base_serial_clk ), + .serial_reset ( por_reset_serial_clk ), + .clk_en ( phy_clk_en ), + .clk_idle ( phy_clk_idle ), + .clk_ready ( phy_clk_ready ), + .phy_clk ( phy_clk ), + .tx_en ( phy_tx_en ), + .tx_ready ( phy_tx_ready ), + .tx_par_data ( phy_tx_data ), + .rx_en ( phy_rx_en ), + .rx_ready ( phy_rx_ready ), + .rx_par_data ( phy_rx_data ), + .tx_ser_clk ( slink_tx_clk ), + .tx_ser_data ( slink_tx_data ), + .rx_ser_data ( slink_rx_data )); + +endmodule diff --git a/rtl/tech/slink_tech_lib.v b/rtl/tech/slink_tech_lib.v index 1585978..7e3c505 100644 --- a/rtl/tech/slink_tech_lib.v +++ b/rtl/tech/slink_tech_lib.v @@ -66,8 +66,8 @@ module slink_reset_sync .sig_in ( 1'b0 ), .sig_out ( reset_in_ff2 )); - assign reset_out = ~scan_ctrl & (reset_in | reset_in_ff2); - + //assign reset_out = ~scan_ctrl & (reset_in | reset_in_ff2); + assign reset_out = ~scan_ctrl & reset_in_ff2; endmodule @@ -496,3 +496,154 @@ end endmodule + + + +/** + * Creates a 2-deep fifo for synchronizing multibit signals + * + * Literally stolen from http://www.sunburst-design.com/papers/CummingsSNUG2008Boston_CDC.pdf + * I'm shameless + */ +module slink_multibit_sync #( + parameter DATA_SIZE = 8 +)( + input wire wclk, + input wire wreset, + input wire winc, + output wire wready, + input wire [DATA_SIZE-1:0] wdata, + + input wire rclk, + input wire rreset, + input wire rinc, + output wire rready, + output wire [DATA_SIZE-1:0] rdata +); + +//reg [DATA_SIZE-1:0] mem [2]; +reg [DATA_SIZE-1:0] mem [1:0]; + +reg wptr; +wire wptr_in; +wire we; +wire rptr_wclk; + +reg rptr; +wire rptr_in; +wire wptr_rclk; + + +always @(posedge wclk or posedge wreset) begin + if(wreset) begin + wptr <= 1'b0; + mem[0] <= {DATA_SIZE{1'b0}}; + mem[1] <= {DATA_SIZE{1'b0}}; + end else begin + wptr <= wptr_in; + if(we) begin + mem[wptr] <= wdata; + end + end +end + +slink_demet_reset u_slink_demet_rptr_wclk ( + .clk ( wclk ), + .reset ( wreset ), + .sig_in ( rptr ), + .sig_out ( rptr_wclk )); + +assign wptr_in = we ^ wptr; +assign wready = ~(rptr_wclk ^ wptr); +assign we = winc & wready; + + + +always @(posedge rclk or posedge rreset) begin + if(rreset) begin + rptr <= 1'b0; + end else begin + rptr <= rptr_in; + end +end + + +slink_demet_reset u_slink_demet_wptr_rclk ( + .clk ( rclk ), + .reset ( rreset ), + .sig_in ( wptr ), + .sig_out ( wptr_rclk )); + +assign rready = rptr ^ wptr_rclk; +assign rptr_in = rptr ^ (rinc & rready); + +assign rdata = mem[rptr]; + +endmodule + + + +module slink_dp_ram #( + parameter DWIDTH = 32, // Data width + parameter SIZE = 256, // RAM size in DWIDTHs + parameter AWIDTH = $clog2(SIZE) // Address width +) ( + input wire clk_0, + input wire [AWIDTH-1:0] addr_0, + input wire en_0, + input wire we_0, + input wire [DWIDTH-1:0] wdata_0, + output wire [DWIDTH-1:0] rdata_0, + + input wire clk_1, + input wire [AWIDTH-1:0] addr_1, + input wire en_1, + input wire we_1, + input wire [DWIDTH-1:0] wdata_1, + output wire [DWIDTH-1:0] rdata_1 +); + +reg [DWIDTH-1:0] mem [SIZE-1:0]; +wire write_0, read_0; +wire write_1, read_1; +reg [AWIDTH-1:0] addr_0_reg, addr_1_reg; + +assign write_0 = en_0 & we_0; +assign read_0 = en_0 & ~we_0; + +integer i; +always @(posedge clk_0) begin + if (write_0) begin + mem[addr_0] <= wdata_0; + end +end + +always @(posedge clk_0) begin + if (read_0) begin + addr_0_reg <= addr_0; + end +end + +assign rdata_0 = read_0 ? mem[addr_0] : mem[addr_0_reg]; + +assign write_1 = en_1 & we_1; +assign read_1 = en_1 & ~we_1; + +integer j; +// always @(posedge clk_1) begin +// if (write_1) begin +// mem[addr_1] <= wdata_1; +// end +// end + +always @(posedge clk_1) begin + if (read_1) begin + addr_1_reg <= addr_1; + end +end + +assign rdata_1 = read_1 ? mem[addr_1] : mem[addr_1_reg]; + +endmodule + + diff --git a/verif/slink/run/run_regression.py b/verif/slink/run/run_regression.py index 9284f3d..c94f65c 100644 --- a/verif/slink/run/run_regression.py +++ b/verif/slink/run/run_regression.py @@ -56,7 +56,7 @@ 'slink_force_hard_reset' : 1} #tests = {'sanity_test' : 1} -tests = {'ecc_corruption' : 3, 'ecc_corruption' : 3} +#tests = {'ecc_corruption' : 3, 'ecc_corruption' : 3} for comp in compile_opts: csub = re.sub(r'[^0-9a-zA-Z]+', '_', comp) diff --git a/verif/slink/run/simulate.sh b/verif/slink/run/simulate.sh index 7d0bd0b..3695601 100755 --- a/verif/slink/run/simulate.sh +++ b/verif/slink/run/simulate.sh @@ -45,11 +45,13 @@ iverilog -g2012 \ $SLINK_TOP/rtl/*.v \ $SLINK_TOP/rtl/bist/*.v \ $SLINK_TOP/rtl/serdes/*.v \ - $SLINK_TOP/rtl/tech/*.v \ + $SLINK_TOP/rtl/tech/slink_tech_lib.v \ $SLINK_TOP/verif/slink/sub/slink_cfg.v \ $SLINK_TOP/verif/slink/tb_top/slink_tb_top.v \ $SLINK_TOP/verif/slink/tb_top/serdes_phy_model.v \ + $SLINK_TOP/verif/slink/tb_top/slink_simple_io_phy_model.v \ $SLINK_TOP/verif/slink/tb_top/slink_gpio_model.v \ + $SLINK_TOP/verif/slink/tb_top/slink_b2b_tb_wrapper.v \ $SLINK_TOP/verif/slink/sub/slink_app_monitor.v \ $SLINK_TOP/verif/slink/sub/slink_app_driver.v \ $SLINK_TOP/verif/slink/sub/slink_apb_driver.v \ @@ -62,10 +64,10 @@ iverilog -g2012 \ if [ -z $regress ] then - # Running local + # Running local -lxt2-speed if test -f "$VVP_FILE"; then - vvp -n $log $VVP_FILE +SLINK_TEST=$test $plusargs $nosave -lxt2-speed + vvp -n $log $VVP_FILE +SLINK_TEST=$test $plusargs $nosave else echo "$VVP_FILE doesn't exists." fi diff --git a/verif/slink/sub/slink_app_driver.v b/verif/slink/sub/slink_app_driver.v index 9c6c7d6..3220d6a 100644 --- a/verif/slink/sub/slink_app_driver.v +++ b/verif/slink/sub/slink_app_driver.v @@ -120,7 +120,7 @@ task sendRandomShortPacket; bit [ 7: 0] di; bit [15: 0] wc; - di = 'ha + {$urandom} % ('h1f - 'ha); + di = 'h2 + {$urandom} % ('h2f - 'h2); wc = $urandom; sendShortPacket(di, wc); endtask @@ -139,7 +139,7 @@ task sendRandomLongPacket(input bit random_data=1); bit [ 7: 0] di; bit [15: 0] wc; - di = 'h20 + {$urandom} % ('h3f - 'h20); + di = 'h30 + {$urandom} % ('hef - 'h30); wc = 1 + {$urandom} % (1024 - 1); //NEED TO FIX THE 0 BYTE PAYLOAD //wc = 1 + {$urandom} % (20 - 1); //NEED TO FIX THE 0 BYTE PAYLOAD sendLongPacket(di, wc, random_data); @@ -154,7 +154,7 @@ sendShortPacket * ``input bit[15:0] wc`` - Word Count/Payload for this packet SendShortPacket will handle the sending of the desired short packet on the S-Link -interface. If a data ID of >= 0x20 is attempted, it will error. The dataid, and payload +interface. If a data ID of >= 0x30 is attempted, it will error. The dataid, and payload are send to the monitor for checking reception. .rst_end @@ -164,8 +164,8 @@ task sendShortPacket(input bit[7:0] dataid, input bit[15:0] wc); `sim_info($display("Starting Short Packet Send with DI: %2h and WC: %4h", dataid, wc)) - if(dataid >= 'h20) begin - `sim_error($display("DATA ID should be 0x0 <-> 0x1F. Not sending this packet")) + if(dataid >= 'h30) begin + `sim_error($display("DATA ID should be 0x0 <-> 0x2F. Not sending this packet")) end else begin @(posedge link_clk); @@ -203,7 +203,7 @@ sendLongPacket * ``input bit random_data`` - 1: Random data is send for each byte 0: byte data is a counter sendLongPacket will handle the sending of the desired long packet on the S-Link -interface. If a data ID of < 0x20 is attempted, it will error. The dataid, wc, and payload +interface. If a data ID of < 0x30 is attempted, it will error. The dataid, wc, and payload are send to the monitor for checking reception. Payload data is created based on the word count. The user can send random data for each byte by @@ -227,8 +227,8 @@ task sendLongPacket(input bit [7:0] dataid, input bit [15:0] wc, input bit rando `sim_info($display("Starting Long Packet Send with DI: %2h and WC: %4h", dataid, wc)) - if(dataid < 'h20) begin - `sim_error($display("DATA ID should be > 0x1F. Not sending this packet")) + if(dataid < 'h30) begin + `sim_error($display("DATA ID should be > 0x2F. Not sending this packet")) end else begin //push to monitor for check diff --git a/verif/slink/sub/slink_app_monitor.v b/verif/slink/sub/slink_app_monitor.v index 073f139..ea2b994 100644 --- a/verif/slink/sub/slink_app_monitor.v +++ b/verif/slink/sub/slink_app_monitor.v @@ -63,7 +63,7 @@ task monitorIntf; if(~disable_monitor) begin if(rx_sop && rx_valid) begin //SOP - if(rx_data_id <= 'h1f) begin + if(rx_data_id <= 'h2f) begin //Short Packet `sim_info($display("Short packet Received ID: %2h WC: %4h", rx_data_id, rx_word_count)) checkByte(rx_data_id); diff --git a/verif/slink/tb_top/serdes_phy_model.v b/verif/slink/tb_top/serdes_phy_model.v index b567a53..2ceb782 100644 --- a/verif/slink/tb_top/serdes_phy_model.v +++ b/verif/slink/tb_top/serdes_phy_model.v @@ -9,7 +9,8 @@ //-------------------------------------------- module serdes_clk_model #( - parameter IS_MASTER = 1 + parameter IS_MASTER = 1, + parameter real CLK_PER_NS = 0.0625 ) ( input wire enable, input wire idle, @@ -21,7 +22,7 @@ initial begin bitclk = 0; end -always #0.0625ns bitclk <= enable && ~idle && IS_MASTER ? ~bitclk : 1'b0; +always #((CLK_PER_NS/2.0)*1ns) bitclk <= enable && ~idle && IS_MASTER ? ~bitclk : 1'b0; always @(*) begin if(enable) begin diff --git a/verif/slink/tb_top/slink_b2b_tb_wrapper.v b/verif/slink/tb_top/slink_b2b_tb_wrapper.v new file mode 100644 index 0000000..f858d49 --- /dev/null +++ b/verif/slink/tb_top/slink_b2b_tb_wrapper.v @@ -0,0 +1,448 @@ +module slink_b2b_tb_wrapper #( + parameter MST_TX_APP_DATA_WIDTH = 32, + parameter MST_RX_APP_DATA_WIDTH = 32, + parameter SLV_TX_APP_DATA_WIDTH = 32, + parameter SLV_RX_APP_DATA_WIDTH = 32, + parameter NUM_TX_LANES = 8, + parameter NUM_RX_LANES = 8, + parameter MST_PHY_DATA_WIDTH = 16, + parameter SLV_PHY_DATA_WIDTH = 16, + parameter SERDES_MODE = 1 +)( + input wire main_reset, + + input wire mst_apb_clk, + input wire mst_apb_reset, + input wire [8:0] mst_apb_paddr, + input wire mst_apb_pwrite, + input wire mst_apb_psel, + input wire mst_apb_penable, + input wire [31:0] mst_apb_pwdata, + output wire [31:0] mst_apb_prdata, + output wire mst_apb_pready, + output wire mst_apb_pslverr, + + + output wire mst_link_clk, + output wire mst_link_reset, + input wire mst_tx_sop, + input wire [7:0] mst_tx_data_id, + input wire [15:0] mst_tx_word_count, + input wire [MST_TX_APP_DATA_WIDTH-1:0] mst_tx_app_data, + output wire mst_tx_advance, + output wire mst_rx_sop, + output wire [7:0] mst_rx_data_id, + output wire [15:0] mst_rx_word_count, + output wire [MST_RX_APP_DATA_WIDTH-1:0] mst_rx_app_data, + output wire mst_rx_valid, + output wire mst_rx_crc_corrupted, + output wire mst_interrupt, + input wire mst_p1_req, + input wire mst_p2_req, + input wire mst_p3_req, + output wire mst_in_px_state, + output wire mst_in_reset_state, + + + input wire slv_apb_clk, + input wire slv_apb_reset, + input wire [8:0] slv_apb_paddr, + input wire slv_apb_pwrite, + input wire slv_apb_psel, + input wire slv_apb_penable, + input wire [31:0] slv_apb_pwdata, + output wire [31:0] slv_apb_prdata, + output wire slv_apb_pready, + output wire slv_apb_pslverr, + + output wire slv_link_clk, + output wire slv_link_reset, + input wire slv_tx_sop, + input wire [7:0] slv_tx_data_id, + input wire [15:0] slv_tx_word_count, + input wire [SLV_TX_APP_DATA_WIDTH-1:0] slv_tx_app_data, + output wire slv_tx_advance, + output wire slv_rx_sop, + output wire [7:0] slv_rx_data_id, + output wire [15:0] slv_rx_word_count, + output wire [SLV_RX_APP_DATA_WIDTH-1:0] slv_rx_app_data, + output wire slv_rx_valid, + output wire slv_rx_crc_corrupted, + output wire slv_interrupt, + input wire slv_p1_req, + input wire slv_p2_req, + input wire slv_p3_req, + output wire slv_in_px_state, + output wire slv_in_reset_state, + + input wire refclk +); + + +wire [NUM_TX_LANES-1:0] mst_phy_tx_clk; +wire mst_phy_clk_en; +wire mst_phy_clk_idle; +wire mst_phy_clk_ready; +wire [NUM_TX_LANES-1:0] mst_phy_tx_en; +wire [NUM_TX_LANES-1:0] mst_phy_tx_ready; +wire [NUM_TX_LANES-1:0] mst_phy_tx_dirdy; +wire [(NUM_TX_LANES*MST_PHY_DATA_WIDTH)-1:0] mst_phy_tx_data; +wire [NUM_RX_LANES-1:0] mst_phy_rx_en; +wire [NUM_RX_LANES-1:0] mst_phy_rx_clk; +wire [NUM_RX_LANES-1:0] mst_phy_rx_ready; +wire [NUM_RX_LANES-1:0] mst_phy_rx_valid; +wire [NUM_RX_LANES-1:0] mst_phy_rx_dordy; +wire [NUM_RX_LANES-1:0] mst_phy_rx_align; +wire [(NUM_RX_LANES*MST_PHY_DATA_WIDTH)-1:0] mst_phy_rx_data; + +wire [NUM_RX_LANES-1:0] slv_phy_tx_clk; +wire slv_phy_clk_en; +wire slv_phy_clk_idle; +wire slv_phy_clk_ready; +wire [NUM_RX_LANES-1:0] slv_phy_tx_en; +wire [NUM_RX_LANES-1:0] slv_phy_tx_ready; +wire [NUM_RX_LANES-1:0] slv_phy_tx_dirdy; +wire [(NUM_RX_LANES*SLV_PHY_DATA_WIDTH)-1:0] slv_phy_tx_data; +wire [NUM_TX_LANES-1:0] slv_phy_rx_en; +wire [NUM_TX_LANES-1:0] slv_phy_rx_clk; +wire [NUM_TX_LANES-1:0] slv_phy_rx_ready; +wire [NUM_TX_LANES-1:0] slv_phy_rx_valid; +wire [NUM_TX_LANES-1:0] slv_phy_rx_dordy; +wire [NUM_TX_LANES-1:0] slv_phy_rx_align; +wire [(NUM_TX_LANES*SLV_PHY_DATA_WIDTH)-1:0] slv_phy_rx_data; + +wire mst_slink_gpio_reset_n_oen; +wire mst_slink_gpio_reset_n ; +wire mst_slink_gpio_wake_n_oen; +wire mst_slink_gpio_wake_n ; +wire slv_slink_gpio_reset_n_oen; +wire slv_slink_gpio_reset_n ; +wire slv_slink_gpio_wake_n_oen; +wire slv_slink_gpio_wake_n ; + + + + +slink #( + //parameters + .NUM_TX_LANES ( NUM_TX_LANES ), + .NUM_RX_LANES ( NUM_RX_LANES ), + .TX_APP_DATA_WIDTH ( MST_TX_APP_DATA_WIDTH ), + .RX_APP_DATA_WIDTH ( MST_RX_APP_DATA_WIDTH ), + .PHY_DATA_WIDTH ( MST_PHY_DATA_WIDTH ), + .DESKEW_FIFO_DEPTH ( 4 ) +) u_slink_MASTER ( + .core_scan_mode ( 1'b0 ), + .core_scan_clk ( 1'b0 ), + .core_scan_asyncrst_ctrl ( 1'b0 ), + .apb_clk ( mst_apb_clk ), + .apb_reset ( mst_apb_reset ), + .apb_paddr ( mst_apb_paddr ), + .apb_pwrite ( mst_apb_pwrite ), + .apb_psel ( mst_apb_psel ), + .apb_penable ( mst_apb_penable ), + .apb_pwdata ( mst_apb_pwdata ), + .apb_prdata ( mst_apb_prdata ), + .apb_pready ( mst_apb_pready ), + .apb_pslverr ( mst_apb_pslverr ), + .link_clk ( mst_link_clk ), + .link_reset ( mst_link_reset ), + + .slink_enable ( ~main_reset ), + .por_reset ( main_reset ), + + .tx_sop ( mst_tx_sop ), + .tx_data_id ( mst_tx_data_id ), + .tx_word_count ( mst_tx_word_count ), + .tx_app_data ( mst_tx_app_data ), + .tx_advance ( mst_tx_advance ), + .rx_sop ( mst_rx_sop ), + .rx_data_id ( mst_rx_data_id ), + .rx_word_count ( mst_rx_word_count ), + .rx_app_data ( mst_rx_app_data ), + .rx_valid ( mst_rx_valid ), + .rx_crc_corrupted ( mst_rx_crc_corrupted ), + .interrupt ( mst_interrupt ), + + .p1_req ( mst_p1_req ), + .p2_req ( mst_p2_req ), + .p3_req ( mst_p3_req ), + .in_px_state ( mst_in_px_state ), + .in_reset_state ( mst_in_reset_state ), + + .slink_gpio_reset_n_oen ( mst_slink_gpio_reset_n_oen ), + .slink_gpio_reset_n ( mst_slink_gpio_reset_n ), + .slink_gpio_wake_n_oen ( mst_slink_gpio_wake_n_oen ), + .slink_gpio_wake_n ( mst_slink_gpio_wake_n ), + + .refclk ( refclk ), + .phy_clk ( mst_phy_tx_clk[0] ), + .phy_clk_en ( mst_phy_clk_en ), + .phy_clk_idle ( mst_phy_clk_idle ), + .phy_clk_ready ( mst_phy_clk_ready ), + .phy_tx_en ( mst_phy_tx_en ), + .phy_tx_ready ( mst_phy_tx_ready ), + .phy_tx_dirdy ( mst_phy_tx_dirdy ), + .phy_tx_data ( mst_phy_tx_data ), + .phy_rx_en ( mst_phy_rx_en ), + .phy_rx_clk ( mst_phy_rx_clk ), + .phy_rx_ready ( mst_phy_rx_ready ), + .phy_rx_valid ( mst_phy_rx_valid ), + .phy_rx_dordy ( mst_phy_rx_dordy ), + .phy_rx_align ( mst_phy_rx_align ), + .phy_rx_data ( mst_phy_rx_data )); + + + +slink #( + //parameters + .NUM_TX_LANES ( NUM_RX_LANES ), + .NUM_RX_LANES ( NUM_TX_LANES ), + .TX_APP_DATA_WIDTH ( SLV_TX_APP_DATA_WIDTH ), + .RX_APP_DATA_WIDTH ( SLV_RX_APP_DATA_WIDTH ), + .PHY_DATA_WIDTH ( SLV_PHY_DATA_WIDTH ), + .DESKEW_FIFO_DEPTH ( 4 ) +) u_slink_SLAVE ( + .core_scan_mode ( 1'b0 ), + .core_scan_clk ( 1'b0 ), + .core_scan_asyncrst_ctrl ( 1'b0 ), + .apb_clk ( slv_apb_clk ), + .apb_reset ( slv_apb_reset ), + .apb_paddr ( slv_apb_paddr ), + .apb_pwrite ( slv_apb_pwrite ), + .apb_psel ( slv_apb_psel ), + .apb_penable ( slv_apb_penable ), + .apb_pwdata ( slv_apb_pwdata ), + .apb_prdata ( slv_apb_prdata ), + .apb_pready ( slv_apb_pready ), + .apb_pslverr ( slv_apb_pslverr ), + .link_clk ( slv_link_clk ), + .link_reset ( slv_link_reset ), + + .slink_enable ( ~main_reset ), + .por_reset ( main_reset ), + + .tx_sop ( slv_tx_sop ), + .tx_data_id ( slv_tx_data_id ), + .tx_word_count ( slv_tx_word_count ), + .tx_app_data ( slv_tx_app_data ), + .tx_advance ( slv_tx_advance ), + .rx_sop ( slv_rx_sop ), + .rx_data_id ( slv_rx_data_id ), + .rx_word_count ( slv_rx_word_count ), + .rx_app_data ( slv_rx_app_data ), + .rx_valid ( slv_rx_valid ), + .rx_crc_corrupted ( slv_rx_crc_corrupted ), + .interrupt ( slv_interrupt ), + + .p1_req ( slv_p1_req ), + .p2_req ( slv_p2_req ), + .p3_req ( slv_p3_req ), + .in_px_state ( slv_in_px_state ), + .in_reset_state ( slv_in_reset_state ), + + .slink_gpio_reset_n_oen ( slv_slink_gpio_reset_n_oen ), + .slink_gpio_reset_n ( slv_slink_gpio_reset_n ), + .slink_gpio_wake_n_oen ( slv_slink_gpio_wake_n_oen ), + .slink_gpio_wake_n ( slv_slink_gpio_wake_n ), + + .refclk ( refclk ), + .phy_clk ( slv_phy_tx_clk[0] ), + .phy_clk_en ( slv_phy_clk_en ), + .phy_clk_idle ( slv_phy_clk_idle ), + .phy_clk_ready ( slv_phy_clk_ready ), + .phy_tx_en ( slv_phy_tx_en ), + .phy_tx_ready ( slv_phy_tx_ready ), + .phy_tx_dirdy ( slv_phy_tx_dirdy ), + .phy_tx_data ( slv_phy_tx_data ), + .phy_rx_en ( slv_phy_rx_en ), + .phy_rx_clk ( slv_phy_rx_clk ), + .phy_rx_ready ( slv_phy_rx_ready ), + .phy_rx_valid ( slv_phy_rx_valid ), + .phy_rx_dordy ( slv_phy_rx_dordy ), + .phy_rx_align ( slv_phy_rx_align ), + .phy_rx_data ( slv_phy_rx_data )); + + +// Sideband signals +wire slink_reset_n_io; +wire slink_wake_n_io; + +slink_gpio_model u_slink_gpio_model_MASTER[1:0] ( + .oen ( {mst_slink_gpio_reset_n_oen, + mst_slink_gpio_wake_n_oen} ), + .sig_in ( {mst_slink_gpio_reset_n, + mst_slink_gpio_wake_n} ), + .pad ( {slink_reset_n_io, + slink_wake_n_io} )); + + +slink_gpio_model u_slink_gpio_model_SLAVE[1:0] ( + .oen ( {slv_slink_gpio_reset_n_oen, + slv_slink_gpio_wake_n_oen} ), + .sig_in ( {slv_slink_gpio_reset_n, + slv_slink_gpio_wake_n} ), + .pad ( {slink_reset_n_io, + slink_wake_n_io} )); + + + + + +generate + if(SERDES_MODE == 1) begin : gen_serdes_mode + //------------------------------------ + // PHY + //------------------------------------ + wire [NUM_TX_LANES-1:0] txp, txn; + wire [NUM_RX_LANES-1:0] rxp, rxn; + wire clk_bitclk; + + serdes_phy_model #( + //parameters + .IS_MASTER ( 1 ), + .MAX_DELAY_CYC ( 16 ), + .DATA_WIDTH ( MST_PHY_DATA_WIDTH), + .NUM_TX_LANES ( NUM_TX_LANES ), + .NUM_RX_LANES ( NUM_RX_LANES ) + ) u_serdes_phy_model_MASTER ( + .clk_enable ( mst_phy_clk_en ), + .clk_idle ( mst_phy_clk_idle ), + .clk_ready ( mst_phy_clk_ready ), + .clk_bitclk ( clk_bitclk ), + .tx_enable ( mst_phy_tx_en ), + .txclk ( mst_phy_tx_clk ), + .tx_data ( mst_phy_tx_data ), + .tx_reset ( {NUM_TX_LANES{main_reset}} ), + .tx_dirdy ( mst_phy_tx_dirdy ), + .tx_ready ( mst_phy_tx_ready ), + .rx_enable ( mst_phy_rx_en ), + .rxclk ( mst_phy_rx_clk ), + .rx_align ( mst_phy_rx_align ), + .rx_data ( mst_phy_rx_data ), + .rx_reset ( {NUM_RX_LANES{main_reset}} ), + .rx_locked ( ), + .rx_valid ( mst_phy_rx_valid ), + .rx_dordy ( mst_phy_rx_dordy ), + .rx_ready ( mst_phy_rx_ready ), + .txp ( txp ), + .txn ( txn ), + .rxp ( rxp ), + .rxn ( rxn )); + + serdes_phy_model #( + //parameters + .IS_MASTER ( 0 ), + .MAX_DELAY_CYC ( 16 ), + .DATA_WIDTH ( SLV_PHY_DATA_WIDTH), + .NUM_TX_LANES ( NUM_RX_LANES ), + .NUM_RX_LANES ( NUM_TX_LANES ) + ) u_serdes_phy_model_SLAVE ( + .clk_enable ( slv_phy_clk_en ), + .clk_idle ( slv_phy_clk_idle ), + .clk_ready ( slv_phy_clk_ready ), + .clk_bitclk ( clk_bitclk ), + .tx_enable ( slv_phy_tx_en ), + .txclk ( slv_phy_tx_clk ), + .tx_data ( slv_phy_tx_data ), + .tx_reset ( {NUM_RX_LANES{main_reset}} ), + .tx_dirdy ( slv_phy_tx_dirdy ), + .tx_ready ( slv_phy_tx_ready ), + .rx_enable ( slv_phy_rx_en ), + .rxclk ( slv_phy_rx_clk ), + .rx_align ( slv_phy_rx_align ), + .rx_data ( slv_phy_rx_data ), + .rx_reset ( {NUM_TX_LANES{main_reset}} ), + .rx_locked ( ), + .rx_valid ( slv_phy_rx_valid ), + .rx_dordy ( slv_phy_rx_dordy ), + .rx_ready ( slv_phy_rx_ready ), + .txp ( rxp ), + .txn ( rxn ), + .rxp ( txp ), + .rxn ( txn )); + + end else begin : gen_parallel_mode + wire [(NUM_TX_LANES*MST_PHY_DATA_WIDTH)-1:0] tx_par; + wire tx_ctrl; + wire [(NUM_RX_LANES*MST_PHY_DATA_WIDTH)-1:0] rx_par; + wire rx_ctrl; + wire clk_byteclk; + wire parclk; + + //TEMP + assign mst_phy_tx_clk = {NUM_TX_LANES{parclk}}; + assign mst_phy_rx_clk = {NUM_RX_LANES{parclk}}; + assign slv_phy_tx_clk = {NUM_RX_LANES{parclk}}; + assign slv_phy_rx_clk = {NUM_TX_LANES{parclk}}; + + //Size Check + initial begin + if(MST_PHY_DATA_WIDTH != SLV_PHY_DATA_WIDTH) begin + `sim_fatal($display("MST_PHY_DATA_WIDTH must equal SLV_PHY_DATA_WIDTH in PARALLEL MODE!!")) + end + end + + slink_simple_io_phy_model #( + //parameters + .IS_MASTER ( 1 ), + .CLK_PER_NS ( 2 ), + .DATA_WIDTH ( MST_PHY_DATA_WIDTH ), + .NUM_TX_LANES ( NUM_TX_LANES ), + .NUM_RX_LANES ( NUM_RX_LANES ) + ) u_slink_simple_io_phy_model_MASTER ( + .clk_enable ( mst_phy_clk_en ), + .clk_idle ( mst_phy_clk_idle ), + .clk_ready ( mst_phy_clk_ready ), + .clk_byteclk ( clk_byteclk ), + .parclk ( parclk ), + .tx_enable ( mst_phy_tx_en ), + .tx_data ( mst_phy_tx_data ), + .tx_data_ctrl ( 1'b0 ), + .tx_reset ( {NUM_TX_LANES{main_reset}} ), + .tx_dirdy ( mst_phy_tx_dirdy ), + .tx_ready ( mst_phy_tx_ready ), + .rx_enable ( mst_phy_rx_en ), + .rx_data ( mst_phy_rx_data ), + .rx_data_ctrl ( /*connme*/ ), + .rx_reset ( {NUM_RX_LANES{main_reset}} ), + .rx_dordy ( mst_phy_rx_dordy ), + .rx_ready ( mst_phy_rx_ready ), + .tx ( tx_par ), + .tx_ctrl ( tx_ctrl ), + .rx ( rx_par ), + .rx_ctrl ( rx_ctrl )); + + slink_simple_io_phy_model #( + //parameters + .IS_MASTER ( 1 ), + .CLK_PER_NS ( 2 ), + .DATA_WIDTH ( SLV_PHY_DATA_WIDTH ), + .NUM_TX_LANES ( NUM_RX_LANES ), + .NUM_RX_LANES ( NUM_TX_LANES ) + ) u_slink_simple_io_phy_model_SLAVE ( + .clk_enable ( slv_phy_clk_en ), + .clk_idle ( slv_phy_clk_idle ), + .clk_ready ( slv_phy_clk_ready ), + .clk_byteclk ( clk_byteclk ), + .parclk ( parclk ), + .tx_enable ( slv_phy_tx_en ), + .tx_data ( slv_phy_tx_data ), + .tx_data_ctrl ( 1'b0 ), + .tx_reset ( {NUM_TX_LANES{main_reset}} ), + .tx_dirdy ( slv_phy_tx_dirdy ), + .tx_ready ( slv_phy_tx_ready ), + .rx_enable ( slv_phy_rx_en ), + .rx_data ( slv_phy_rx_data ), + .rx_data_ctrl ( /*connme*/ ), + .rx_reset ( {NUM_RX_LANES{main_reset}} ), + .rx_dordy ( slv_phy_rx_dordy ), + .rx_ready ( slv_phy_rx_ready ), + .tx ( rx_par ), + .tx_ctrl ( rx_ctrl ), + .rx ( tx_par ), + .rx_ctrl ( tx_ctrl )); + + end +endgenerate +endmodule diff --git a/verif/slink/tb_top/slink_cfg_params.vh b/verif/slink/tb_top/slink_cfg_params.vh new file mode 100644 index 0000000..be356bd --- /dev/null +++ b/verif/slink/tb_top/slink_cfg_params.vh @@ -0,0 +1,63 @@ +`ifndef MAX_TX_LANES + `define MAX_TX_LANES 8 +`endif + +`ifndef MAX_RX_LANES + `define MAX_RX_LANES 8 +`endif + + + +`ifndef MST_PHY_DATA_WIDTH + `define MST_PHY_DATA_WIDTH 16 +`endif + +`ifndef SLV_PHY_DATA_WIDTH + `define SLV_PHY_DATA_WIDTH 16 +`endif + + +`ifndef MST_TX_APP_DATA_WIDTH + `define MST_TX_APP_DATA_WIDTH (`MAX_TX_LANES * `MST_PHY_DATA_WIDTH) +`endif +`ifndef MST_RX_APP_DATA_WIDTH + `define MST_RX_APP_DATA_WIDTH (`MAX_RX_LANES * `MST_PHY_DATA_WIDTH) +`endif + +`ifndef SLV_TX_APP_DATA_WIDTH + `define SLV_TX_APP_DATA_WIDTH (`MAX_RX_LANES * `SLV_PHY_DATA_WIDTH) +`endif +`ifndef SLV_RX_APP_DATA_WIDTH + `define SLV_RX_APP_DATA_WIDTH (`MAX_TX_LANES * `SLV_PHY_DATA_WIDTH) +`endif + +`ifndef SERDES_MODE + `define SERDES_MODE 1 +`endif +parameter SERDES_MODE = `SERDES_MODE; + +parameter MST_TX_APP_DATA_WIDTH = `MST_TX_APP_DATA_WIDTH; +parameter MST_RX_APP_DATA_WIDTH = `MST_RX_APP_DATA_WIDTH; +parameter SLV_TX_APP_DATA_WIDTH = `SLV_TX_APP_DATA_WIDTH; +parameter SLV_RX_APP_DATA_WIDTH = `SLV_RX_APP_DATA_WIDTH; +parameter NUM_TX_LANES = `MAX_TX_LANES; +parameter NUM_RX_LANES = `MAX_RX_LANES; +parameter MST_PHY_DATA_WIDTH = `MST_PHY_DATA_WIDTH; +parameter SLV_PHY_DATA_WIDTH = `SLV_PHY_DATA_WIDTH; + +//App Data Width Check +initial begin + if(MST_TX_APP_DATA_WIDTH < (NUM_TX_LANES * MST_PHY_DATA_WIDTH)) begin + `sim_fatal($display("MST_TX_APP_DATA_WIDTH is too small")) + end + if(MST_RX_APP_DATA_WIDTH < (NUM_RX_LANES * MST_PHY_DATA_WIDTH)) begin + `sim_fatal($display("MST_RX_APP_DATA_WIDTH is too small")) + end + + if(SLV_TX_APP_DATA_WIDTH < (NUM_RX_LANES * SLV_PHY_DATA_WIDTH)) begin + `sim_fatal($display("SLV_TX_APP_DATA_WIDTH is too small")) + end + if(SLV_RX_APP_DATA_WIDTH < (NUM_TX_LANES * SLV_PHY_DATA_WIDTH)) begin + `sim_fatal($display("SLV_RX_APP_DATA_WIDTH is too small")) + end +end diff --git a/verif/slink/tb_top/slink_drivers_inst.vh b/verif/slink/tb_top/slink_drivers_inst.vh new file mode 100644 index 0000000..9531a72 --- /dev/null +++ b/verif/slink/tb_top/slink_drivers_inst.vh @@ -0,0 +1,73 @@ +slink_app_driver #( + //parameters + .DRIVER_APP_DATA_WIDTH ( MST_TX_APP_DATA_WIDTH ), + .MONITOR_APP_DATA_WIDTH ( SLV_RX_APP_DATA_WIDTH ) +) driver_m2s ( + .link_clk ( mst_link_clk ), + .link_reset ( mst_link_reset ), + .tx_sop ( mst_tx_sop ), + .tx_data_id ( mst_tx_data_id ), + .tx_word_count ( mst_tx_word_count ), + .tx_app_data ( mst_tx_app_data ), + .tx_valid ( mst_tx_valid ), + .tx_advance ( mst_tx_advance ), + + + .rx_link_clk ( slv_link_clk ), + .rx_link_reset ( slv_link_reset ), + .rx_sop ( slv_rx_sop ), + .rx_data_id ( slv_rx_data_id ), + .rx_word_count ( slv_rx_word_count ), + .rx_app_data ( slv_rx_app_data ), + .rx_valid ( slv_rx_valid ), + .rx_crc_corrupted ( slv_rx_crc_corrupted ), + + .interrupt ( mst_interrupt ), + + .apb_clk ( apb_clk ), + .apb_reset ( main_reset ), + .apb_paddr ( mst_apb_paddr ), + .apb_pwrite ( mst_apb_pwrite ), + .apb_psel ( mst_apb_psel ), + .apb_penable ( mst_apb_penable ), + .apb_pwdata ( mst_apb_pwdata ), + .apb_prdata ( mst_apb_prdata ), + .apb_pready ( mst_apb_pready ), + .apb_pslverr ( mst_apb_pslverr )); + + +slink_app_driver #( + //parameters + .DRIVER_APP_DATA_WIDTH ( SLV_TX_APP_DATA_WIDTH ), + .MONITOR_APP_DATA_WIDTH ( MST_RX_APP_DATA_WIDTH ) +) driver_s2m ( + .link_clk ( slv_link_clk ), + .link_reset ( slv_link_reset ), + .tx_sop ( slv_tx_sop ), + .tx_data_id ( slv_tx_data_id ), + .tx_word_count ( slv_tx_word_count ), + .tx_app_data ( slv_tx_app_data ), + .tx_valid ( slv_tx_valid ), + .tx_advance ( slv_tx_advance ), + + .rx_link_clk ( mst_link_clk ), + .rx_link_reset ( mst_link_reset ), + .rx_sop ( mst_rx_sop ), + .rx_data_id ( mst_rx_data_id ), + .rx_word_count ( mst_rx_word_count ), + .rx_app_data ( mst_rx_app_data ), + .rx_valid ( mst_rx_valid ), + .rx_crc_corrupted ( mst_rx_crc_corrupted ), + + .interrupt ( slv_interrupt ), + + .apb_clk ( apb_clk ), + .apb_reset ( main_reset ), + .apb_paddr ( slv_apb_paddr ), + .apb_pwrite ( slv_apb_pwrite ), + .apb_psel ( slv_apb_psel ), + .apb_penable ( slv_apb_penable ), + .apb_pwdata ( slv_apb_pwdata ), + .apb_prdata ( slv_apb_prdata ), + .apb_pready ( slv_apb_pready ), + .apb_pslverr ( slv_apb_pslverr )); diff --git a/verif/slink/tb_top/slink_gpio_model.v b/verif/slink/tb_top/slink_gpio_model.v index 233433b..549072e 100644 --- a/verif/slink/tb_top/slink_gpio_model.v +++ b/verif/slink/tb_top/slink_gpio_model.v @@ -6,6 +6,7 @@ module slink_gpio_model( assign pad = oen ? 1'b0 : 1'bz; +pullup (weak1) pad_pu (pad); assign sig_in = pad === 1'bz ? 1'b1 : pad; endmodule diff --git a/verif/slink/tb_top/slink_inst.vh b/verif/slink/tb_top/slink_inst.vh index 51534ee..b58c8a1 100644 --- a/verif/slink/tb_top/slink_inst.vh +++ b/verif/slink/tb_top/slink_inst.vh @@ -1,62 +1,4 @@ -`ifndef MAX_TX_LANES - `define MAX_TX_LANES 8 -`endif -`ifndef MAX_RX_LANES - `define MAX_RX_LANES 8 -`endif - - - -`ifndef MST_PHY_DATA_WIDTH - `define MST_PHY_DATA_WIDTH 16 -`endif - -`ifndef SLV_PHY_DATA_WIDTH - `define SLV_PHY_DATA_WIDTH 16 -`endif - - -`ifndef MST_TX_APP_DATA_WIDTH - `define MST_TX_APP_DATA_WIDTH (`MAX_TX_LANES * `MST_PHY_DATA_WIDTH) -`endif -`ifndef MST_RX_APP_DATA_WIDTH - `define MST_RX_APP_DATA_WIDTH (`MAX_RX_LANES * `MST_PHY_DATA_WIDTH) -`endif - -`ifndef SLV_TX_APP_DATA_WIDTH - `define SLV_TX_APP_DATA_WIDTH (`MAX_RX_LANES * `SLV_PHY_DATA_WIDTH) -`endif -`ifndef SLV_RX_APP_DATA_WIDTH - `define SLV_RX_APP_DATA_WIDTH (`MAX_TX_LANES * `SLV_PHY_DATA_WIDTH) -`endif - - -parameter MST_TX_APP_DATA_WIDTH = `MST_TX_APP_DATA_WIDTH; -parameter MST_RX_APP_DATA_WIDTH = `MST_RX_APP_DATA_WIDTH; -parameter SLV_TX_APP_DATA_WIDTH = `SLV_TX_APP_DATA_WIDTH; -parameter SLV_RX_APP_DATA_WIDTH = `SLV_RX_APP_DATA_WIDTH; -parameter NUM_TX_LANES = `MAX_TX_LANES; -parameter NUM_RX_LANES = `MAX_RX_LANES; -parameter MST_PHY_DATA_WIDTH = `MST_PHY_DATA_WIDTH; -parameter SLV_PHY_DATA_WIDTH = `SLV_PHY_DATA_WIDTH; - -//App Data Width Check -initial begin - if(MST_TX_APP_DATA_WIDTH < (NUM_TX_LANES * MST_PHY_DATA_WIDTH)) begin - `sim_fatal($display("MST_TX_APP_DATA_WIDTH is too small")) - end - if(MST_RX_APP_DATA_WIDTH < (NUM_RX_LANES * MST_PHY_DATA_WIDTH)) begin - `sim_fatal($display("MST_RX_APP_DATA_WIDTH is too small")) - end - - if(SLV_TX_APP_DATA_WIDTH < (NUM_RX_LANES * SLV_PHY_DATA_WIDTH)) begin - `sim_fatal($display("SLV_TX_APP_DATA_WIDTH is too small")) - end - if(SLV_RX_APP_DATA_WIDTH < (NUM_TX_LANES * SLV_PHY_DATA_WIDTH)) begin - `sim_fatal($display("SLV_RX_APP_DATA_WIDTH is too small")) - end -end //------------------------- // Clocks / Reset @@ -65,14 +7,20 @@ reg main_reset = 0; reg apb_clk = 0; reg refclk = 0; -//reg phy_clk = 0; -wire [NUM_TX_LANES-1:0] mst_phy_clk; //fix -wire [NUM_TX_LANES-1:0] slv_phy_clk; always #5 apb_clk <= ~apb_clk; always #13.02 refclk <= ~refclk; +wire [8:0] mst_apb_paddr; +wire mst_apb_pwrite; +wire mst_apb_psel; +wire mst_apb_penable; +wire [31:0] mst_apb_pwdata; +wire [31:0] mst_apb_prdata; +wire mst_apb_pready; +wire mst_apb_pslverr; + wire mst_link_clk; wire mst_link_reset; @@ -91,6 +39,27 @@ wire mst_rx_valid; wire mst_rx_crc_corrupted; wire mst_interrupt; +wire mst_p1_req; +wire mst_p2_req; +wire mst_p3_req; +wire mst_in_px_state; +wire mst_in_reset_state; + +assign mst_p1_req = 1'b0; +assign mst_p2_req = 1'b0; +assign mst_p3_req = 1'b0; + + + +wire [8:0] slv_apb_paddr; +wire slv_apb_pwrite; +wire slv_apb_psel; +wire slv_apb_penable; +wire [31:0] slv_apb_pwdata; +wire [31:0] slv_apb_prdata; +wire slv_apb_pready; +wire slv_apb_pslverr; + wire slv_link_clk; wire slv_link_reset; @@ -109,411 +78,91 @@ wire slv_rx_valid; wire slv_rx_crc_corrupted; wire slv_interrupt; +wire slv_p1_req; +wire slv_p2_req; +wire slv_p3_req; +wire slv_in_px_state; +wire slv_in_reset_state; -wire [NUM_TX_LANES-1:0] mst_phy_txclk; -wire mst_phy_clk_en; -wire mst_phy_clk_idle; -wire mst_phy_clk_ready; -wire [NUM_TX_LANES-1:0] mst_phy_tx_en; -wire [NUM_TX_LANES-1:0] mst_phy_tx_ready; -wire [NUM_TX_LANES-1:0] mst_phy_tx_dirdy; -wire [(NUM_TX_LANES*MST_PHY_DATA_WIDTH)-1:0] mst_phy_tx_data; -wire [NUM_RX_LANES-1:0] mst_phy_rx_en; -wire [NUM_RX_LANES-1:0] mst_phy_rx_clk; -wire [NUM_RX_LANES-1:0] mst_phy_rx_ready; -wire [NUM_RX_LANES-1:0] mst_phy_rx_valid; -wire [NUM_RX_LANES-1:0] mst_phy_rx_dordy; -wire [NUM_RX_LANES-1:0] mst_phy_rx_align; -wire [(NUM_RX_LANES*MST_PHY_DATA_WIDTH)-1:0] mst_phy_rx_data; - -wire [NUM_RX_LANES-1:0] slv_phy_txclk; -wire slv_phy_clk_en; -wire slv_phy_clk_idle; -wire slv_phy_clk_ready; -wire [NUM_RX_LANES-1:0] slv_phy_tx_en; -wire [NUM_RX_LANES-1:0] slv_phy_tx_ready; -wire [NUM_RX_LANES-1:0] slv_phy_tx_dirdy; -wire [(NUM_RX_LANES*SLV_PHY_DATA_WIDTH)-1:0] slv_phy_tx_data; -wire [NUM_TX_LANES-1:0] slv_phy_rx_en; -wire [NUM_TX_LANES-1:0] slv_phy_rx_clk; -wire [NUM_TX_LANES-1:0] slv_phy_rx_ready; -wire [NUM_TX_LANES-1:0] slv_phy_rx_valid; -wire [NUM_TX_LANES-1:0] slv_phy_rx_dordy; -wire [NUM_TX_LANES-1:0] slv_phy_rx_align; -wire [(NUM_TX_LANES*SLV_PHY_DATA_WIDTH)-1:0] slv_phy_rx_data; - - -bit pkt_type = 0; - - - - - -wire [8:0] apb_paddr; -wire apb_pwrite; -wire apb_psel; -wire apb_penable; -wire [31:0] apb_pwdata; -wire [31:0] apb_prdata; -wire apb_pready; -wire apb_pslverr; - -wire [8:0] slv_apb_paddr; -wire slv_apb_pwrite; -wire slv_apb_psel; -wire slv_apb_penable; -wire [31:0] slv_apb_pwdata; -wire [31:0] slv_apb_prdata; -wire slv_apb_pready; -wire slv_apb_pslverr; - -wire mst_slink_gpio_reset_n_oen; -wire mst_slink_gpio_reset_n ; -wire mst_slink_gpio_wake_n_oen; -wire mst_slink_gpio_wake_n ; -wire slv_slink_gpio_reset_n_oen; -wire slv_slink_gpio_reset_n ; -wire slv_slink_gpio_wake_n_oen; -wire slv_slink_gpio_wake_n ; - - -slink_app_driver #( - //parameters - .DRIVER_APP_DATA_WIDTH ( MST_TX_APP_DATA_WIDTH ), - .MONITOR_APP_DATA_WIDTH ( SLV_RX_APP_DATA_WIDTH ) -) driver_m2s ( - .link_clk ( mst_link_clk ), - .link_reset ( mst_link_reset ), - .tx_sop ( mst_tx_sop ), - .tx_data_id ( mst_tx_data_id ), - .tx_word_count ( mst_tx_word_count ), - .tx_app_data ( mst_tx_app_data ), - .tx_valid ( mst_tx_valid ), - .tx_advance ( mst_tx_advance ), - - - .rx_link_clk ( slv_link_clk ), - .rx_link_reset ( slv_link_reset ), - .rx_sop ( slv_rx_sop ), - .rx_data_id ( slv_rx_data_id ), - .rx_word_count ( slv_rx_word_count ), - .rx_app_data ( slv_rx_app_data ), - .rx_valid ( slv_rx_valid ), - .rx_crc_corrupted ( slv_rx_crc_corrupted ), - - .interrupt ( mst_interrupt ), - - .apb_clk ( apb_clk ), - .apb_reset ( main_reset ), - .apb_paddr ( apb_paddr ), - .apb_pwrite ( apb_pwrite ), - .apb_psel ( apb_psel ), - .apb_penable ( apb_penable ), - .apb_pwdata ( apb_pwdata ), - .apb_prdata ( apb_prdata ), - .apb_pready ( apb_pready ), - .apb_pslverr ( apb_pslverr )); - - -slink_app_driver #( - //parameters - .DRIVER_APP_DATA_WIDTH ( SLV_TX_APP_DATA_WIDTH ), - .MONITOR_APP_DATA_WIDTH ( MST_RX_APP_DATA_WIDTH ) -) driver_s2m ( - .link_clk ( slv_link_clk ), - .link_reset ( slv_link_reset ), - .tx_sop ( slv_tx_sop ), - .tx_data_id ( slv_tx_data_id ), - .tx_word_count ( slv_tx_word_count ), - .tx_app_data ( slv_tx_app_data ), - .tx_valid ( slv_tx_valid ), - .tx_advance ( slv_tx_advance ), - - .rx_link_clk ( mst_link_clk ), - .rx_link_reset ( mst_link_reset ), - .rx_sop ( mst_rx_sop ), - .rx_data_id ( mst_rx_data_id ), - .rx_word_count ( mst_rx_word_count ), - .rx_app_data ( mst_rx_app_data ), - .rx_valid ( mst_rx_valid ), - .rx_crc_corrupted ( mst_rx_crc_corrupted ), - - .interrupt ( slv_interrupt ), - - .apb_clk ( apb_clk ), - .apb_reset ( main_reset ), - .apb_paddr ( slv_apb_paddr ), - .apb_pwrite ( slv_apb_pwrite ), - .apb_psel ( slv_apb_psel ), - .apb_penable ( slv_apb_penable ), - .apb_pwdata ( slv_apb_pwdata ), - .apb_prdata ( slv_apb_prdata ), - .apb_pready ( slv_apb_pready ), - .apb_pslverr ( slv_apb_pslverr )); +assign slv_p1_req = 1'b0; +assign slv_p2_req = 1'b0; +assign slv_p3_req = 1'b0; - -slink #( +slink_b2b_tb_wrapper #( //parameters - .NUM_TX_LANES ( NUM_TX_LANES ), - .NUM_RX_LANES ( NUM_RX_LANES ), - .TX_APP_DATA_WIDTH ( MST_TX_APP_DATA_WIDTH ), - .RX_APP_DATA_WIDTH ( MST_RX_APP_DATA_WIDTH ), - .PHY_DATA_WIDTH ( MST_PHY_DATA_WIDTH ), - .DESKEW_FIFO_DEPTH ( 4 ) -) u_slink_MASTER ( - .core_scan_mode ( 1'b0 ), - .core_scan_clk ( 1'b0 ), - .core_scan_asyncrst_ctrl ( 1'b0 ), - .apb_clk ( apb_clk ), - .apb_reset ( main_reset ), - .apb_paddr ( apb_paddr ), - .apb_pwrite ( apb_pwrite ), - .apb_psel ( apb_psel ), - .apb_penable ( apb_penable ), - .apb_pwdata ( apb_pwdata ), - .apb_prdata ( apb_prdata ), - .apb_pready ( apb_pready ), - .apb_pslverr ( apb_pslverr ), - .link_clk ( mst_link_clk ), - .link_reset ( mst_link_reset ), - -// .app_attr_addr ( 16'd0 ), -// .app_attr_data ( 16'd0 ), -// .app_shadow_update ( 1'b0 ), -// .app_attr_data_read ( ), - - .tx_sop ( mst_tx_sop ), - .tx_data_id ( mst_tx_data_id ), - .tx_word_count ( mst_tx_word_count ), - .tx_app_data ( mst_tx_app_data ), - .tx_advance ( mst_tx_advance ), - .rx_sop ( mst_rx_sop ), - .rx_data_id ( mst_rx_data_id ), - .rx_word_count ( mst_rx_word_count ), - .rx_app_data ( mst_rx_app_data ), - .rx_valid ( mst_rx_valid ), - .rx_crc_corrupted ( mst_rx_crc_corrupted ), - .interrupt ( mst_interrupt ), - - .p1_req ( 1'b0 ), - .p2_req ( 1'b0 ), - .p3_req ( 1'b0 ), - - .slink_gpio_reset_n_oen ( mst_slink_gpio_reset_n_oen ), - .slink_gpio_reset_n ( mst_slink_gpio_reset_n ), - .slink_gpio_wake_n_oen ( mst_slink_gpio_wake_n_oen ), - .slink_gpio_wake_n ( mst_slink_gpio_wake_n ), - - .refclk ( refclk ), - .phy_clk ( mst_phy_txclk[0] ), - .phy_clk_en ( mst_phy_clk_en ), - .phy_clk_idle ( mst_phy_clk_idle ), - .phy_clk_ready ( mst_phy_clk_ready ), - .phy_tx_en ( mst_phy_tx_en ), - .phy_tx_ready ( mst_phy_tx_ready ), - .phy_tx_dirdy ( mst_phy_tx_dirdy ), - .phy_tx_data ( mst_phy_tx_data ), - .phy_rx_en ( mst_phy_rx_en ), - .phy_rx_clk ( mst_phy_rx_clk ), - .phy_rx_ready ( mst_phy_rx_ready ), - .phy_rx_valid ( mst_phy_rx_valid ), - .phy_rx_dordy ( mst_phy_rx_dordy ), - .phy_rx_align ( mst_phy_rx_align ), - .phy_rx_data ( mst_phy_rx_data )); - + .MST_TX_APP_DATA_WIDTH ( MST_TX_APP_DATA_WIDTH ), + .MST_RX_APP_DATA_WIDTH ( MST_RX_APP_DATA_WIDTH ), + .NUM_TX_LANES ( NUM_TX_LANES ), + .NUM_RX_LANES ( NUM_RX_LANES ), + .MST_PHY_DATA_WIDTH ( MST_PHY_DATA_WIDTH ), + + .SLV_TX_APP_DATA_WIDTH ( SLV_TX_APP_DATA_WIDTH ), + .SLV_RX_APP_DATA_WIDTH ( SLV_RX_APP_DATA_WIDTH ), + .SLV_PHY_DATA_WIDTH ( SLV_PHY_DATA_WIDTH ), + + .SERDES_MODE ( SERDES_MODE ) +) u_slink_b2b_tb_wrapper ( + .main_reset ( main_reset ), + .mst_apb_clk ( apb_clk ), + .mst_apb_reset ( main_reset ), + .mst_apb_paddr ( mst_apb_paddr ), + .mst_apb_pwrite ( mst_apb_pwrite ), + .mst_apb_psel ( mst_apb_psel ), + .mst_apb_penable ( mst_apb_penable ), + .mst_apb_pwdata ( mst_apb_pwdata ), + .mst_apb_prdata ( mst_apb_prdata ), + .mst_apb_pready ( mst_apb_pready ), + .mst_apb_pslverr ( mst_apb_pslverr ), + .mst_link_clk ( mst_link_clk ), + .mst_link_reset ( mst_link_reset ), + .mst_tx_sop ( mst_tx_sop ), + .mst_tx_data_id ( mst_tx_data_id ), + .mst_tx_word_count ( mst_tx_word_count ), + .mst_tx_app_data ( mst_tx_app_data ), + .mst_tx_advance ( mst_tx_advance ), + .mst_rx_sop ( mst_rx_sop ), + .mst_rx_data_id ( mst_rx_data_id ), + .mst_rx_word_count ( mst_rx_word_count ), + .mst_rx_app_data ( mst_rx_app_data ), + .mst_rx_valid ( mst_rx_valid ), + .mst_rx_crc_corrupted ( mst_rx_crc_corrupted ), + .mst_interrupt ( mst_interrupt ), + .mst_p1_req ( mst_p1_req ), + .mst_p2_req ( mst_p2_req ), + .mst_p3_req ( mst_p3_req ), + .mst_in_px_state ( mst_in_px_state ), + .mst_in_reset_state ( mst_in_reset_state ), + + + .slv_apb_clk ( apb_clk ), + .slv_apb_reset ( main_reset ), + .slv_apb_paddr ( slv_apb_paddr ), + .slv_apb_pwrite ( slv_apb_pwrite ), + .slv_apb_psel ( slv_apb_psel ), + .slv_apb_penable ( slv_apb_penable ), + .slv_apb_pwdata ( slv_apb_pwdata ), + .slv_apb_prdata ( slv_apb_prdata ), + .slv_apb_pready ( slv_apb_pready ), + .slv_apb_pslverr ( slv_apb_pslverr ), + .slv_link_clk ( slv_link_clk ), + .slv_link_reset ( slv_link_reset ), + .slv_tx_sop ( slv_tx_sop ), + .slv_tx_data_id ( slv_tx_data_id ), + .slv_tx_word_count ( slv_tx_word_count ), + .slv_tx_app_data ( slv_tx_app_data ), + .slv_tx_advance ( slv_tx_advance ), + .slv_rx_sop ( slv_rx_sop ), + .slv_rx_data_id ( slv_rx_data_id ), + .slv_rx_word_count ( slv_rx_word_count ), + .slv_rx_app_data ( slv_rx_app_data ), + .slv_rx_valid ( slv_rx_valid ), + .slv_rx_crc_corrupted ( slv_rx_crc_corrupted ), + .slv_interrupt ( slv_interrupt ), + .slv_p1_req ( slv_p1_req ), + .slv_p2_req ( slv_p2_req ), + .slv_p3_req ( slv_p3_req ), + .slv_in_px_state ( slv_in_px_state ), + .slv_in_reset_state ( slv_in_reset_state ), + .refclk ( refclk )); -slink #( - //parameters - .NUM_TX_LANES ( NUM_RX_LANES ), - .NUM_RX_LANES ( NUM_TX_LANES ), - .TX_APP_DATA_WIDTH ( SLV_TX_APP_DATA_WIDTH ), - .RX_APP_DATA_WIDTH ( SLV_RX_APP_DATA_WIDTH ), - .PHY_DATA_WIDTH ( SLV_PHY_DATA_WIDTH ), - .DESKEW_FIFO_DEPTH ( 4 ) -) u_slink_SLAVE ( - .core_scan_mode ( 1'b0 ), - .core_scan_clk ( 1'b0 ), - .core_scan_asyncrst_ctrl ( 1'b0 ), - //.main_reset ( main_reset ), - .apb_clk ( apb_clk ), - .apb_reset ( main_reset ), - .apb_paddr ( slv_apb_paddr ), - .apb_pwrite ( slv_apb_pwrite ), - .apb_psel ( slv_apb_psel ), - .apb_penable ( slv_apb_penable ), - .apb_pwdata ( slv_apb_pwdata ), - .apb_prdata ( slv_apb_prdata ), - .apb_pready ( slv_apb_pready ), - .apb_pslverr ( slv_apb_pslverr ), - .link_clk ( slv_link_clk ), - .link_reset ( slv_link_reset ), - -// .app_attr_addr ( 16'd0 ), -// .app_attr_data ( 16'd0 ), -// .app_shadow_update ( 1'b0 ), -// .app_attr_data_read ( ), - - .tx_sop ( slv_tx_sop ), - .tx_data_id ( slv_tx_data_id ), - .tx_word_count ( slv_tx_word_count ), - .tx_app_data ( slv_tx_app_data ), - .tx_advance ( slv_tx_advance ), - .rx_sop ( slv_rx_sop ), - .rx_data_id ( slv_rx_data_id ), - .rx_word_count ( slv_rx_word_count ), - .rx_app_data ( slv_rx_app_data ), - .rx_valid ( slv_rx_valid ), - .rx_crc_corrupted ( slv_rx_crc_corrupted ), - .interrupt ( slv_interrupt ), - - .p1_req ( 1'b0 ), - .p2_req ( 1'b0 ), - .p3_req ( 1'b0 ), - - .slink_gpio_reset_n_oen ( slv_slink_gpio_reset_n_oen ), - .slink_gpio_reset_n ( slv_slink_gpio_reset_n ), - .slink_gpio_wake_n_oen ( slv_slink_gpio_wake_n_oen ), - .slink_gpio_wake_n ( slv_slink_gpio_wake_n ), - - .refclk ( refclk ), - .phy_clk ( slv_phy_txclk[0] ), - .phy_clk_en ( slv_phy_clk_en ), - .phy_clk_idle ( slv_phy_clk_idle ), - .phy_clk_ready ( slv_phy_clk_ready ), - .phy_tx_en ( slv_phy_tx_en ), - .phy_tx_ready ( slv_phy_tx_ready ), - .phy_tx_dirdy ( slv_phy_tx_dirdy ), - .phy_tx_data ( slv_phy_tx_data ), - .phy_rx_en ( slv_phy_rx_en ), - .phy_rx_clk ( slv_phy_rx_clk ), - .phy_rx_ready ( slv_phy_rx_ready ), - .phy_rx_valid ( slv_phy_rx_valid ), - .phy_rx_dordy ( slv_phy_rx_dordy ), - .phy_rx_align ( slv_phy_rx_align ), - .phy_rx_data ( slv_phy_rx_data )); - - -// Sideband signals -wire slink_reset_n_io; -wire slink_wake_n_io; -wire bla; - -slink_gpio_model u_slink_gpio_model_MASTER[1:0] ( - .oen ( {mst_slink_gpio_reset_n_oen, - mst_slink_gpio_wake_n_oen} ), - .sig_in ( {mst_slink_gpio_reset_n, - mst_slink_gpio_wake_n} ), - .pad ( {slink_reset_n_io, - slink_wake_n_io} )); - - -slink_gpio_model u_slink_gpio_model_SLAVE[1:0] ( - .oen ( {slv_slink_gpio_reset_n_oen, - slv_slink_gpio_wake_n_oen} ), - .sig_in ( {slv_slink_gpio_reset_n, - slv_slink_gpio_wake_n} ), - .pad ( {slink_reset_n_io, - slink_wake_n_io} )); - - -initial begin - if($test$plusargs("NO_WAVES")) begin - `sim_info($display("No waveform saving this sim")) - end else begin - $dumpvars(0); -// for(int i = 0; i < 32; i++) begin -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.gen_block_align[0].u_slink_rx_blockalign_128b13xb.data_out_sel[i]); -// end -// -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.data_fifo[0][0]); -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.data_fifo[0][1]); -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.data_fifo[0][2]); -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.data_fifo[0][3]); -// -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.data_fifo[1][0]); -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.data_fifo[1][1]); -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.data_fifo[1][2]); -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.data_fifo[1][3]); -// -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.fifo_ptr_in[0]); -// $dumpvars(0, u_slink_SLAVE.u_slink_rx_align_deskew.u_slink_rx_deskew.fifo_ptr_in[1]); -// -// $dumpvars(0, u_slink_MASTER.u_slink_rx_align_deskew.u_slink_rx_deskew.sds_byte_count[0]); -// $dumpvars(0, u_slink_MASTER.u_slink_rx_align_deskew.u_slink_rx_deskew.sds_byte_count[1]); - - end - #1ms; - `sim_fatal($display("sim timeout")); - $finish(); -end - - - -wire [NUM_TX_LANES-1:0] txp, txn; -wire [NUM_RX_LANES-1:0] rxp, rxn; -wire clk_bitclk; - -serdes_phy_model #( - //parameters - .IS_MASTER ( 1 ), - .MAX_DELAY_CYC ( 16 ), - .DATA_WIDTH ( MST_PHY_DATA_WIDTH), - .NUM_TX_LANES ( NUM_TX_LANES ), - .NUM_RX_LANES ( NUM_RX_LANES ) -) u_serdes_phy_model_MASTER ( - .clk_enable ( mst_phy_clk_en ), - .clk_idle ( mst_phy_clk_idle ), - .clk_ready ( mst_phy_clk_ready ), - .clk_bitclk ( clk_bitclk ), - .tx_enable ( mst_phy_tx_en ), - .txclk ( mst_phy_txclk ), - .tx_data ( mst_phy_tx_data ), - .tx_reset ( {NUM_TX_LANES{main_reset}} ), - .tx_dirdy ( mst_phy_tx_dirdy ), - .tx_ready ( mst_phy_tx_ready ), - .rx_enable ( mst_phy_rx_en ), - .rxclk ( mst_phy_rx_clk ), - .rx_align ( mst_phy_rx_align ), - .rx_data ( mst_phy_rx_data ), - .rx_reset ( {NUM_RX_LANES{main_reset}} ), - .rx_locked ( ), - .rx_valid ( mst_phy_rx_valid ), - .rx_dordy ( mst_phy_rx_dordy ), - .rx_ready ( mst_phy_rx_ready ), - .txp ( txp ), - .txn ( txn ), - .rxp ( rxp ), - .rxn ( rxn )); - -serdes_phy_model #( - //parameters - .IS_MASTER ( 0 ), - .MAX_DELAY_CYC ( 16 ), - .DATA_WIDTH ( SLV_PHY_DATA_WIDTH), - .NUM_TX_LANES ( NUM_RX_LANES ), - .NUM_RX_LANES ( NUM_TX_LANES ) -) u_serdes_phy_model_SLAVE ( - .clk_enable ( slv_phy_clk_en ), - .clk_idle ( slv_phy_clk_idle ), - .clk_ready ( slv_phy_clk_ready ), - .clk_bitclk ( clk_bitclk ), - .tx_enable ( slv_phy_tx_en ), - .txclk ( slv_phy_txclk ), - .tx_data ( slv_phy_tx_data ), - .tx_reset ( {NUM_RX_LANES{main_reset}} ), - .tx_dirdy ( slv_phy_tx_dirdy ), - .tx_ready ( slv_phy_tx_ready ), - .rx_enable ( slv_phy_rx_en ), - .rxclk ( slv_phy_rx_clk ), - .rx_align ( slv_phy_rx_align ), - .rx_data ( slv_phy_rx_data ), - .rx_reset ( {NUM_TX_LANES{main_reset}} ), - .rx_locked ( ), - .rx_valid ( slv_phy_rx_valid ), - .rx_dordy ( slv_phy_rx_dordy ), - .rx_ready ( slv_phy_rx_ready ), - .txp ( rxp ), - .txn ( rxn ), - .rxp ( txp ), - .rxn ( txn )); diff --git a/verif/slink/tb_top/slink_simple_io_phy_model.v b/verif/slink/tb_top/slink_simple_io_phy_model.v new file mode 100644 index 0000000..d871ee9 --- /dev/null +++ b/verif/slink/tb_top/slink_simple_io_phy_model.v @@ -0,0 +1,79 @@ +module slink_simple_io_phy_model #( + parameter IS_MASTER = 1, + parameter CLK_PER_NS = 2, + parameter DATA_WIDTH = 8, + parameter NUM_TX_LANES = 4, + parameter NUM_RX_LANES = 4 +)( + input wire clk_enable, + input wire clk_idle, + output wire clk_ready, + inout wire clk_byteclk, + + output wire parclk, + + input wire [NUM_TX_LANES-1:0] tx_enable, + input wire [(NUM_TX_LANES*DATA_WIDTH)-1:0] tx_data, + input wire tx_data_ctrl, + input wire [NUM_TX_LANES-1:0] tx_reset, + output wire [NUM_TX_LANES-1:0] tx_dirdy, + output wire [NUM_TX_LANES-1:0] tx_ready, + + input wire [NUM_RX_LANES-1:0] rx_enable, + output reg [(NUM_RX_LANES*DATA_WIDTH)-1:0] rx_data, + output reg rx_data_ctrl, + input wire [NUM_RX_LANES-1:0] rx_reset, + output wire [NUM_RX_LANES-1:0] rx_dordy, + output wire [NUM_RX_LANES-1:0] rx_ready, + + output reg [(NUM_TX_LANES*DATA_WIDTH)-1:0] tx, + output reg tx_ctrl, + input wire [(NUM_RX_LANES*DATA_WIDTH)-1:0] rx, + input wire rx_ctrl +); + +wire bitclk; + + +serdes_clk_model #( + //parameters + .IS_MASTER ( IS_MASTER ), + .CLK_PER_NS ( CLK_PER_NS ) +) u_serdes_clk_model ( + .enable ( clk_enable ), + .idle ( clk_idle ), + .ready ( clk_ready ), + .bitclk ( bitclk )); //really a byteclk here + +assign clk_byteclk = IS_MASTER ? bitclk : 1'bz; + +assign parclk = clk_byteclk; + +// TODO CLEAN UP THESE RESETS! +always @(negedge clk_byteclk or posedge tx_reset) begin + if(tx_reset) begin + tx <= {NUM_TX_LANES*DATA_WIDTH{1'b0}}; + tx_ctrl <= 1'b0; + end else begin + tx <= tx_data; + tx_ctrl <= tx_data_ctrl; + end +end + + +always @(posedge clk_byteclk or posedge rx_reset) begin + if(rx_reset) begin + rx_data <= {NUM_RX_LANES*DATA_WIDTH{1'b0}}; + rx_data_ctrl <= 1'b0; + end else begin + rx_data <= rx; + rx_data_ctrl <= rx_ctrl; + end +end + + +//temp +assign tx_ready = {NUM_TX_LANES{1'b1}}; +assign rx_ready = {NUM_TX_LANES{1'b1}}; + +endmodule diff --git a/verif/slink/tb_top/slink_tb_top.v b/verif/slink/tb_top/slink_tb_top.v index 88d1491..24c5433 100644 --- a/verif/slink/tb_top/slink_tb_top.v +++ b/verif/slink/tb_top/slink_tb_top.v @@ -119,11 +119,19 @@ new changes and most users of S-Link shouldn't have to run them. module tb_top; +//Parameters/Defines for config +`include "slink_cfg_params.vh" + `include "slink_msg.v" `include "slink_tests.vh" +//Usually shared `include "slink_inst.vh" +//Per TB +`include "slink_drivers_inst.vh" + + initial begin #1ps; main_reset = 1; @@ -138,6 +146,17 @@ initial begin end +initial begin + if($test$plusargs("NO_WAVES")) begin + `sim_info($display("No waveform saving this sim")) + end else begin + $dumpvars(0); + + end + #1ms; + `sim_fatal($display("sim timeout")); + $finish(); +end endmodule diff --git a/verif/slink/tests/slink_ctrl_addr_defines.vh b/verif/slink/tests/slink_ctrl_addr_defines.vh index 039bfd0..770ebe9 100644 --- a/verif/slink/tests/slink_ctrl_addr_defines.vh +++ b/verif/slink/tests/slink_ctrl_addr_defines.vh @@ -1,6 +1,6 @@ //=================================================================== // -// Created by steven on August/30/2020 at 11:55:35 +// Created by sbridges on February/02/2021 at 13:47:34 // // slink_ctrl_addr_defines.vh // @@ -9,10 +9,12 @@ `define SLINK_CTRL_SWRESET 'h00000000 +`define SLINK_CTRL_SWRESET__SWRESET_MUX 1 `define SLINK_CTRL_SWRESET__SWRESET 0 `define SLINK_CTRL_SWRESET___POR 32'h00000001 `define SLINK_CTRL_ENABLE 'h00000004 +`define SLINK_CTRL_ENABLE__ENABLE_MUX 1 `define SLINK_CTRL_ENABLE__ENABLE 0 `define SLINK_CTRL_ENABLE___POR 32'h00000000 @@ -54,36 +56,40 @@ `define SLINK_CTRL_COUNT_VAL_1US__COUNT_VAL_1US 9:0 `define SLINK_CTRL_COUNT_VAL_1US___POR 32'h00000026 -`define SLINK_CTRL_SW_ATTR_ADDR_DATA 'h0000001C +`define SLINK_CTRL_SHORT_PACKET_MAX 'h0000001C +`define SLINK_CTRL_SHORT_PACKET_MAX__SHORT_PACKET_MAX 7:0 +`define SLINK_CTRL_SHORT_PACKET_MAX___POR 32'h0000002F + +`define SLINK_CTRL_SW_ATTR_ADDR_DATA 'h00000020 `define SLINK_CTRL_SW_ATTR_ADDR_DATA__SW_ATTR_WDATA 31:16 `define SLINK_CTRL_SW_ATTR_ADDR_DATA__SW_ATTR_ADDR 15:0 `define SLINK_CTRL_SW_ATTR_ADDR_DATA___POR 32'h00000000 -`define SLINK_CTRL_SW_ATTR_CONTROLS 'h00000020 +`define SLINK_CTRL_SW_ATTR_CONTROLS 'h00000024 `define SLINK_CTRL_SW_ATTR_CONTROLS__SW_ATTR_LOCAL 1 `define SLINK_CTRL_SW_ATTR_CONTROLS__SW_ATTR_WRITE 0 `define SLINK_CTRL_SW_ATTR_CONTROLS___POR 32'h00000003 -`define SLINK_CTRL_SW_ATTR_DATA_READ 'h00000024 +`define SLINK_CTRL_SW_ATTR_DATA_READ 'h00000028 `define SLINK_CTRL_SW_ATTR_DATA_READ__SW_ATTR_RDATA 15:0 `define SLINK_CTRL_SW_ATTR_DATA_READ___POR 32'h00000000 -`define SLINK_CTRL_SW_ATTR_FIFO_STATUS 'h00000028 +`define SLINK_CTRL_SW_ATTR_FIFO_STATUS 'h0000002C `define SLINK_CTRL_SW_ATTR_FIFO_STATUS__SW_ATTR_RECV_FIFO_EMPTY 3 `define SLINK_CTRL_SW_ATTR_FIFO_STATUS__SW_ATTR_RECV_FIFO_FULL 2 `define SLINK_CTRL_SW_ATTR_FIFO_STATUS__SW_ATTR_SEND_FIFO_EMPTY 1 `define SLINK_CTRL_SW_ATTR_FIFO_STATUS__SW_ATTR_SEND_FIFO_FULL 0 `define SLINK_CTRL_SW_ATTR_FIFO_STATUS___POR 32'h00000000 -`define SLINK_CTRL_SW_ATTR_SHADOW_UPDATE 'h0000002C +`define SLINK_CTRL_SW_ATTR_SHADOW_UPDATE 'h00000030 `define SLINK_CTRL_SW_ATTR_SHADOW_UPDATE__SW_ATTR_SHADOW_UPDATE 0 `define SLINK_CTRL_SW_ATTR_SHADOW_UPDATE___POR 32'h00000000 -`define SLINK_CTRL_SW_ATTR_EFFECTIVE_UPDATE 'h00000030 +`define SLINK_CTRL_SW_ATTR_EFFECTIVE_UPDATE 'h00000034 `define SLINK_CTRL_SW_ATTR_EFFECTIVE_UPDATE__SW_ATTR_EFFECTIVE_UPDATE 0 `define SLINK_CTRL_SW_ATTR_EFFECTIVE_UPDATE___POR 32'h00000000 -`define SLINK_CTRL_STATE_STATUS 'h00000034 +`define SLINK_CTRL_STATE_STATUS 'h00000038 `define SLINK_CTRL_STATE_STATUS__DESKEW_STATE 17:16 `define SLINK_CTRL_STATE_STATUS__LL_RX_STATE 15:12 `define SLINK_CTRL_STATE_STATUS__LL_TX_STATE 11:8 @@ -91,11 +97,11 @@ `define SLINK_CTRL_STATE_STATUS__LTSSM_STATE 4:0 `define SLINK_CTRL_STATE_STATUS___POR 32'h00000000 -`define SLINK_CTRL_DEBUG_BUS_CTRL 'h00000038 -`define SLINK_CTRL_DEBUG_BUS_CTRL__DEBUG_BUS_CTRL_SEL 1:0 +`define SLINK_CTRL_DEBUG_BUS_CTRL 'h0000003C +`define SLINK_CTRL_DEBUG_BUS_CTRL__DEBUG_BUS_CTRL_SEL 2:0 `define SLINK_CTRL_DEBUG_BUS_CTRL___POR 32'h00000000 -`define SLINK_CTRL_DEBUG_BUS_STATUS 'h0000003C +`define SLINK_CTRL_DEBUG_BUS_STATUS 'h00000040 `define SLINK_CTRL_DEBUG_BUS_STATUS__DEBUG_BUS_CTRL_STATUS 31:0 `define SLINK_CTRL_DEBUG_BUS_STATUS___POR 32'h00000000 diff --git a/verif/slink/tests/slink_tests.vh b/verif/slink/tests/slink_tests.vh index 9fa6bef..c4e2c91 100644 --- a/verif/slink/tests/slink_tests.vh +++ b/verif/slink/tests/slink_tests.vh @@ -92,7 +92,7 @@ sanity_test Just brings up the link and send a few packets. Commonly used for trying out specific usecases .rst_end -/****************************************/ +****************************************/ task sanity_test; bit [31:0] val; int delay_ns; @@ -101,20 +101,20 @@ task sanity_test; driver_m2s.sendShortPacket('ha, 'h1234); #10ns; - driver_m2s.sendLongPacket('h22, 1); + driver_m2s.sendLongPacket('h32, 1); #10ns; - driver_m2s.sendLongPacket('h22, 2); + driver_m2s.sendLongPacket('h32, 2); #10ns; - driver_m2s.sendLongPacket('h22, 3); + driver_m2s.sendLongPacket('h32, 3); #10ns; - driver_m2s.sendLongPacket('h22, 4); + driver_m2s.sendLongPacket('h32, 4); #10ns; - driver_m2s.sendLongPacket('h22, 5); + driver_m2s.sendLongPacket('h32, 5); #10ns; - driver_m2s.sendLongPacket('h22, 16); - driver_m2s.sendLongPacket('h22, 17); - driver_m2s.sendLongPacket('h22, 18); + driver_m2s.sendLongPacket('h32, 16); + driver_m2s.sendLongPacket('h32, 17); + driver_m2s.sendLongPacket('h32, 18); driver_m2s.write_local_attr (ATTR_P1_TS1_TX, 4); driver_m2s.write_local_attr (ATTR_P1_TS1_TX, 4); @@ -128,7 +128,7 @@ task sanity_test; #10ns; for(int i = 1; i < 53; i++) begin - driver_m2s.sendLongPacket('h22, i); + driver_m2s.sendLongPacket('h32, i); #1ps; end @@ -142,7 +142,7 @@ pstate_sanity +++++++++++++ Sends some packets and goes into each P state .rst_end -/*****************************************/ +*****************************************/ task pstate_sanity; `sim_info($display("P-State Sanity")) driver_m2s.sendShortPacket('ha, 'h1234); @@ -201,7 +201,7 @@ random_packets ++++++++++++++ Brings up the link and sends a random number of packets .rst_end -/*****************************************/ +*****************************************/ task random_packets; `sim_info($display("Starting random_packets")) @@ -244,7 +244,7 @@ link_width_change - Go to lower P1 state - wakeup and send some random packets .rst_end -/*****************************************/ +*****************************************/ task link_width_change; int tx_lanes_rand; @@ -329,7 +329,7 @@ slink_force_reset Bring up slink and force a reset through SW. Wake link back up and see if we can send packets again .rst_end -/*****************************************/ +*****************************************/ task slink_force_reset; fork @@ -370,7 +370,7 @@ slink_force_hard_reset - Read those attributes to see if they are back to defaults - Wake up link and send some packets .rst_end -/*****************************************/ +*****************************************/ task slink_force_hard_reset; bit [31:0] val; @@ -512,7 +512,7 @@ Corrupts one of the Packet Header, looks to see if this error was seen in the monitor. The receiving side should have receieved the packet with no errors since one bit error should be resolvable. .rst_end -/*****************************************/ +*****************************************/ task ecc_correction; reg [(NUM_TX_LANES*MST_PHY_DATA_WIDTH)-1:0] bit_corrupt; @@ -523,15 +523,15 @@ task ecc_correction; driver_m2s.sendRandomShortPacket; end begin - wait((u_slink_MASTER.u_slink_ll_tx.state == 'd1) && - (u_slink_MASTER.u_slink_ll_tx.sop == 1'b1) && - (u_slink_MASTER.u_slink_ll_tx.delim_start == 1'b1)); //wait for it to not be idle + wait((u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.state == 'd1) && + (u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.sop == 1'b1) && + (u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.delim_start == 1'b1)); //wait for it to not be idle #1ps; - bit_corrupt = ph_err_inj(u_slink_MASTER.u_slink_ll_tx.link_data_reg_in, 0); - force u_slink_MASTER.u_slink_ll_tx.link_data_reg_in = bit_corrupt; - @(posedge u_slink_MASTER.u_slink_ll_tx.clk); - release u_slink_MASTER.u_slink_ll_tx.link_data_reg_in; + bit_corrupt = ph_err_inj(u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.link_data_reg_in, 0); + force u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.link_data_reg_in = bit_corrupt; + @(posedge u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.clk); + release u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.link_data_reg_in; end join @@ -556,7 +556,7 @@ Corrupts two bits of the Packet Header, looks to see if this error was seen in the monitor. Allows the link to reset then checks to see if a valid packet can be sent to indicate recovery. .rst_end -/*****************************************/ +*****************************************/ task ecc_corruption; reg [(NUM_TX_LANES*MST_PHY_DATA_WIDTH)-1:0] bit_corrupt; @@ -569,15 +569,15 @@ task ecc_corruption; driver_m2s.sendRandomShortPacket; end begin - wait((u_slink_MASTER.u_slink_ll_tx.state == 'd1) && - (u_slink_MASTER.u_slink_ll_tx.sop == 1'b1) && - (u_slink_MASTER.u_slink_ll_tx.delim_start == 1'b1)); //wait for it to not be idle + wait((u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.state == 'd1) && + (u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.sop == 1'b1) && + (u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.delim_start == 1'b1)); //wait for it to not be idle #1ps; - bit_corrupt = ph_err_inj(u_slink_MASTER.u_slink_ll_tx.link_data_reg_in, 1); - force u_slink_MASTER.u_slink_ll_tx.link_data_reg_in = bit_corrupt; - @(posedge u_slink_MASTER.u_slink_ll_tx.clk); - release u_slink_MASTER.u_slink_ll_tx.link_data_reg_in; + bit_corrupt = ph_err_inj(u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.link_data_reg_in, 1); + force u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.link_data_reg_in = bit_corrupt; + @(posedge u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.clk); + release u_slink_b2b_tb_wrapper.u_slink_MASTER.u_slink_ll_tx.link_data_reg_in; end join diff --git a/verif/slink_apb/run/simulate.sh b/verif/slink_apb/run/simulate.sh new file mode 100755 index 0000000..e4b3b39 --- /dev/null +++ b/verif/slink_apb/run/simulate.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +# -t , also creates the test_.log + +log="-lvvp.log" +jobname="slink_test" + +while [[ "$#" -gt 0 ]]; do + case $1 in + -t|--test) test="$2"; shift ;; + -c|--compile) compargs="$2"; shift ;; + -p|--plusarg) plusargs="$2"; shift ;; + -l|--log) log="-l$2"; shift; ;; + -r|--regress) regress="$2"; shift; ;; + -jn|--job_name) jobname="$2"; shift; ;; + *) echo "Unknown parameter passed: $1"; exit 1 ;; + esac + shift +done + + +if test $test; then + echo "Running test $test" +else + echo "No test defined! running sanity_test" + test="sanity_test" +fi + + + +VVP_FILE=slink_apb_tb +SLINK_TOP=../../.. + + + + + +rm -rf $VVP_FILE + + +#Compile +iverilog -g2012 \ + -DSIMULATION \ + -I$SLINK_TOP/rtl \ + $SLINK_TOP/rtl/*.v \ + $SLINK_TOP/rtl/bist/*.v \ + $SLINK_TOP/rtl/serdes/*.v \ + $SLINK_TOP/rtl/tech/*.v \ + $SLINK_TOP/rtl/app/*.v \ + $SLINK_TOP/rtl/gpio/*.v \ + $SLINK_TOP/rtl/app/amba/*apb*.v \ + $SLINK_TOP/verif/slink/sub/slink_cfg.v \ + $SLINK_TOP/verif/slink_apb/tb_top/slink_apb_tb_top.v \ + $SLINK_TOP/verif/slink/tb_top/serdes_phy_model.v \ + $SLINK_TOP/verif/slink/tb_top/slink_simple_io_phy_model.v \ + $SLINK_TOP/verif/slink/tb_top/slink_gpio_model.v \ + $SLINK_TOP/verif/slink/tb_top/slink_b2b_tb_wrapper.v \ + $SLINK_TOP/verif/slink/sub/slink_app_monitor.v \ + $SLINK_TOP/verif/slink/sub/slink_app_driver.v \ + $SLINK_TOP/verif/slink/sub/slink_apb_driver.v \ + $SLINK_TOP/verif/slink_apb/sub/slink_apb_app_driver_monitor.v \ + -I$SLINK_TOP/verif/slink/sub \ + -I$SLINK_TOP/verif/slink/tests \ + -I$SLINK_TOP/verif/slink/tb_top \ + $compargs \ + -o $VVP_FILE + + +if [ -z $regress ] +then + # Running local + + if test -f "$VVP_FILE"; then + vvp -n $log $VVP_FILE +SLINK_TEST=$test $plusargs $nosave -lxt2-speed + else + echo "$VVP_FILE doesn't exists." + fi +else + # Copies the vvp file to the dir and creates a run script to call + + echo "Saving $VVP_FILE to regress dir $regress" + cp $VVP_FILE $regress/$VVP_FILE + touch $regress/runme.sh + echo "#!/bin/sh" >> $regress/runme.sh + echo "#SBATCH --job-name=$jobname" >> $regress/runme.sh + echo "#SBATCH --ntasks=1" >> $regress/runme.sh + echo "#SBATCH --cpus-per-task=1" >> $regress/runme.sh + echo "vvp -n $log $VVP_FILE +SLINK_TEST=$test $plusargs +NO_WAVES" >> $regress/runme.sh + chmod +x $regress/runme.sh +fi diff --git a/verif/slink_apb/sub/slink_apb_app_driver_monitor.v b/verif/slink_apb/sub/slink_apb_app_driver_monitor.v new file mode 100644 index 0000000..a8f8a90 --- /dev/null +++ b/verif/slink_apb/sub/slink_apb_app_driver_monitor.v @@ -0,0 +1,110 @@ +module slink_apb_app_driver_monitor #( + parameter APB_ADDR_WIDTH = 32 +) ( + input wire interrupt, + + input wire app_apb_clk, + input wire app_apb_reset, + output reg [APB_ADDR_WIDTH-1:0] app_apb_paddr, + output reg app_apb_pwrite, + output reg app_apb_psel, + output reg app_apb_penable, + output reg [31:0] app_apb_pwdata, + input wire [31:0] app_apb_prdata, + input wire app_apb_pready, + input wire app_apb_pslverr, + + input wire link_apb_clk, + input wire link_apb_reset, + output wire [8:0] link_apb_paddr, + output wire link_apb_pwrite, + output wire link_apb_psel, + output wire link_apb_penable, + output wire [31:0] link_apb_pwdata, + input wire [31:0] link_apb_prdata, + input wire link_apb_pready, + input wire link_apb_pslverr + +); + + +initial begin + app_apb_paddr <= 'd0; + app_apb_pwrite <= 1'b0; + app_apb_psel <= 1'b0; + app_apb_penable <= 1'b0; + app_apb_pwdata <= 32'd0; +end + +task send_apb_write(input bit[APB_ADDR_WIDTH-1:0] addr, input bit[31:0] wdata); + @(posedge app_apb_clk); + app_apb_paddr <= addr; + app_apb_pwdata <= wdata; + app_apb_pwrite <= 1; + app_apb_psel <= 1; + @(posedge app_apb_clk); + app_apb_penable <= 1; + while(~app_apb_pready) begin + @(posedge app_apb_clk); + end + app_apb_psel <= 0; + app_apb_penable <= 0; + app_apb_pwrite <= 0; +endtask + + +task send_apb_read(input bit[APB_ADDR_WIDTH-1:0] addr, output bit[31:0] rdata); + @(posedge app_apb_clk); + app_apb_paddr <= addr; + app_apb_psel <= 1; + @(posedge app_apb_clk); + app_apb_penable <= 1; + while(~app_apb_pready) begin + @(posedge app_apb_clk); + end + app_apb_psel <= 0; + app_apb_penable <= 0; + rdata = app_apb_prdata; //ensure non-blocking +endtask + + +// This is just for the software tasks +slink_app_driver #( + //parameters + .DRIVER_APP_DATA_WIDTH ( 32 ), + .MONITOR_APP_DATA_WIDTH ( 32 ) +) link_driver ( + .link_clk ( 1'b0 ), + .link_reset ( 1'b1 ), + .tx_sop ( ), + .tx_data_id ( ), + .tx_word_count ( ), + .tx_app_data ( ), + .tx_valid ( ), + .tx_advance ( 1'b0 ), + + + .rx_link_clk ( 1'b0 ), + .rx_link_reset ( 1'b1 ), + .rx_sop ( 1'b0 ), + .rx_data_id ( 8'd0 ), + .rx_word_count ( 16'd0 ), + .rx_app_data ( {32{1'b0}} ), + .rx_valid ( 1'b0 ), + .rx_crc_corrupted ( 1'b0 ), + + .interrupt ( interrupt ), + + .apb_clk ( link_apb_clk ), + .apb_reset ( link_apb_reset ), + .apb_paddr ( link_apb_paddr ), + .apb_pwrite ( link_apb_pwrite ), + .apb_psel ( link_apb_psel ), + .apb_penable ( link_apb_penable ), + .apb_pwdata ( link_apb_pwdata ), + .apb_prdata ( link_apb_prdata ), + .apb_pready ( link_apb_pready ), + .apb_pslverr ( link_apb_pslverr )); + + +endmodule diff --git a/verif/slink_apb/tb_top/slink_apb_tb_top.v b/verif/slink_apb/tb_top/slink_apb_tb_top.v new file mode 100644 index 0000000..cfb0d86 --- /dev/null +++ b/verif/slink_apb/tb_top/slink_apb_tb_top.v @@ -0,0 +1,249 @@ +`timescale 1ns/1ps + +module slink_apb_tb_top; + + +`define MAX_TX_LANES 1 +`define MAX_RX_LANES 1 + +`define MST_PHY_DATA_WIDTH 8 +`define SLV_PHY_DATA_WIDTH 8 + + +`define MST_TX_APP_DATA_WIDTH 128 +`define MST_RX_APP_DATA_WIDTH 128 +`define SLV_TX_APP_DATA_WIDTH 128 +`define SLV_RX_APP_DATA_WIDTH 128 +`define SERDES_MODE 0 + +parameter APB_ADDR_WIDTH = 32; + +`include "slink_cfg_params.vh" + +`include "slink_msg.v" + +//Usually shared +`include "slink_inst.vh" + +wire app_apb_clk; +wire app_apb_reset; +wire [APB_ADDR_WIDTH-1:0] app_apb_paddr; +wire app_apb_pwrite; +wire app_apb_psel; +wire app_apb_penable; +wire [31:0] app_apb_pwdata; +wire [31:0] app_apb_prdata; +wire app_apb_pready; +wire app_apb_pslverr; + +assign app_apb_clk = apb_clk; +assign app_apb_reset = main_reset; + + +slink_apb_app_driver_monitor #( + //parameters + .APB_ADDR_WIDTH ( 32 ) +) u_slink_apb_app_driver_monitor_mst ( + .interrupt ( 1'b0 ), //input - 1 + .app_apb_clk ( app_apb_clk ), + .app_apb_reset ( app_apb_reset ), + .app_apb_paddr ( app_apb_paddr ), + .app_apb_pwrite ( app_apb_pwrite ), + .app_apb_psel ( app_apb_psel ), + .app_apb_penable ( app_apb_penable ), + .app_apb_pwdata ( app_apb_pwdata ), + .app_apb_prdata ( app_apb_prdata ), + .app_apb_pready ( app_apb_pready ), + .app_apb_pslverr ( app_apb_pslverr ), + + .link_apb_clk ( apb_clk ), + .link_apb_reset ( mst_apb_reset ), + .link_apb_paddr ( mst_apb_paddr ), + .link_apb_pwrite ( mst_apb_pwrite ), + .link_apb_psel ( mst_apb_psel ), + .link_apb_penable ( mst_apb_penable ), + .link_apb_pwdata ( mst_apb_pwdata ), + .link_apb_prdata ( mst_apb_prdata ), + .link_apb_pready ( mst_apb_pready ), + .link_apb_pslverr ( mst_apb_pslverr )); + + +slink_apb_app_driver_monitor #( + //parameters + .APB_ADDR_WIDTH ( 32 ) +) u_slink_apb_app_driver_monitor_slv ( + .interrupt ( 1'b0 ), //input - 1 + .app_apb_clk ( ), + .app_apb_reset ( ), + .app_apb_paddr ( ), + .app_apb_pwrite ( ), + .app_apb_psel ( ), + .app_apb_penable ( ), + .app_apb_pwdata ( ), + .app_apb_prdata ( ), + .app_apb_pready ( ), + .app_apb_pslverr ( ), + + .link_apb_clk ( apb_clk ), + .link_apb_reset ( slv_apb_reset ), + .link_apb_paddr ( slv_apb_paddr ), + .link_apb_pwrite ( slv_apb_pwrite ), + .link_apb_psel ( slv_apb_psel ), + .link_apb_penable ( slv_apb_penable ), + .link_apb_pwdata ( slv_apb_pwdata ), + .link_apb_prdata ( slv_apb_prdata ), + .link_apb_pready ( slv_apb_pready ), + .link_apb_pslverr ( slv_apb_pslverr )); + + +slink_apb_tgt #( + //parameters + .TX_APP_DATA_WIDTH ( 128 ), + .RX_APP_DATA_WIDTH ( 128 ), + .APB_WRITE_RSP_DT ( 8'h33 ), + .APB_WRITE_DT ( 8'h32 ), + .APB_READ_RSP_DT ( 8'h31 ), + .APB_READ_DT ( 8'h30 ) +) u_slink_apb_tgt ( + .apb_clk ( app_apb_clk ), + .apb_reset ( app_apb_reset ), + .apb_paddr ( app_apb_paddr ), + .apb_pwrite ( app_apb_pwrite ), + .apb_psel ( app_apb_psel ), + .apb_penable ( app_apb_penable ), + .apb_pwdata ( app_apb_pwdata ), + .apb_prdata ( app_apb_prdata ), + .apb_pready ( app_apb_pready ), + .apb_pslverr ( app_apb_pslverr ), + .enable ( ~main_reset ), + .link_clk ( mst_link_clk ), + .link_reset ( mst_link_reset ), + .tx_sop ( mst_tx_sop ), + .tx_data_id ( mst_tx_data_id ), + .tx_word_count ( mst_tx_word_count ), + .tx_app_data ( mst_tx_app_data ), + .tx_advance ( mst_tx_advance ), + .rx_sop ( mst_rx_sop ), + .rx_data_id ( mst_rx_data_id ), + .rx_word_count ( mst_rx_word_count ), + .rx_app_data ( mst_rx_app_data ), + .rx_valid ( mst_rx_valid ), + .rx_crc_corrupted ( mst_rx_crc_corrupted )); + + +slink_apb_ini #( + //parameters + .TX_APP_DATA_WIDTH ( 128 ), + .RX_APP_DATA_WIDTH ( 128 ), + .APB_WRITE_RSP_DT ( 8'h33 ), + .APB_WRITE_DT ( 8'h32 ), + .APB_READ_RSP_DT ( 8'h31 ), + .APB_READ_DT ( 8'h30 ) +) u_slink_apb_ini ( + .apb_clk ( app_apb_clk ), //input - 1 + .apb_reset ( app_apb_reset ), //input - 1 + .apb_paddr ( ), //output - reg [31:0] + .apb_pwrite ( ), //output - reg + .apb_psel ( ), //output - reg + .apb_penable ( ), //output - reg + .apb_pwdata ( ), //output - reg [31:0] + .apb_prdata ( 32'hdeadbeef ), //input - [31:0] + .apb_pready ( 1'b1 ), //input - 1 + .apb_pslverr ( 1'b0 ), //input - 1 + .enable ( ~main_reset ), //input - 1 + .link_clk ( slv_link_clk ), //input - 1 + .link_reset ( slv_link_reset ), //input - 1 + .tx_sop ( slv_tx_sop ), //output - 1 + .tx_data_id ( slv_tx_data_id ), //output - [7:0] + .tx_word_count ( slv_tx_word_count ), //output - [15:0] + .tx_app_data ( slv_tx_app_data ), //output - [TX_APP_DATA_WIDTH-1:0] + .tx_advance ( slv_tx_advance ), //input - 1 + .rx_sop ( slv_rx_sop ), //input - 1 + .rx_data_id ( slv_rx_data_id ), //input - [7:0] + .rx_word_count ( slv_rx_word_count ), //input - [15:0] + .rx_app_data ( slv_rx_app_data ), //input - [RX_APP_DATA_WIDTH-1:0] + .rx_valid ( slv_rx_valid ), //input - 1 + .rx_crc_corrupted ( slv_rx_crc_corrupted )); //input - 1 + + +reg serial_clk = 0; +always #1ns serial_clk <= ~serial_clk; +reg tx_en = 0; +reg [7:0] tx_par_data = 8'h12; +reg serial_load_sel = 0; + +initial begin + #10ns; + tx_en = 1; + + #10ns; + repeat(10) begin + tx_par_data = $random; + serial_load_sel = 0; + repeat(14) begin + @(posedge serial_clk); + end + @(posedge serial_clk); + serial_load_sel = 1; + @(posedge serial_clk); + end + +end + +slink_gpio_serializer #( + //parameters + .PAR_DATA_WIDTH ( 8 ), + .IO_DATA_WIDTH ( 2 ) +) u_slink_gpio_serializer ( + .serial_clk ( serial_clk ), //input - 1 + .serial_reset ( main_reset ), //input - 1 + .serial_load_sel(serial_load_sel), + .tx_en ( tx_en ), //input - 1 + .tx_ready ( ), //output - 1 + .tx_par_data ( tx_par_data ), //input - [PAR_DATA_WIDTH-1:0] + .tx_ser_io_en ( ), //output - 1 + .tx_ser_data ( )); //output - [IO_DATA_WIDTH-1:0] + + +bit [31:0] val; +initial begin + #1ps; + main_reset = 1; + #30ns; + + main_reset = 0; + + #20ns; + //slink_test_select; + u_slink_apb_app_driver_monitor_mst.link_driver.clr_swreset; + u_slink_apb_app_driver_monitor_slv.link_driver.clr_swreset; + u_slink_apb_app_driver_monitor_mst.link_driver.en_slink; + u_slink_apb_app_driver_monitor_slv.link_driver.en_slink; + + #5us; + + u_slink_apb_app_driver_monitor_mst.send_apb_write(32'h1234_5678, 32'h4552_abef); + + u_slink_apb_app_driver_monitor_mst.send_apb_read(32'hbaba_cdcd, val); + + #100ns; + + $finish(); +end + + +initial begin + if($test$plusargs("NO_WAVES")) begin + `sim_info($display("No waveform saving this sim")) + end else begin + $dumpvars(0); + + end + #1ms; + `sim_fatal($display("sim timeout")); + $finish(); +end + + + +endmodule