1 ------------------------------------------------------------------------------- 2 -- File : SrpV3Core.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2016-03-22 5 -- Last update: 2016-11-07 6 ------------------------------------------------------------------------------- 7 -- Description: SLAC Register Protocol Version 3, AXI-Lite Interface 9 -- Documentation: https://confluence.slac.stanford.edu/x/cRmVD 11 -- Note: This module only supports 32-bit aligned addresses and 32-bit transactions. 12 -- For non 32-bit aligned addresses or non 32-bit transactions, use 13 -- the SrpV3Axi.vhd module with the AxiToAxiLite.vhd bridge 14 ------------------------------------------------------------------------------- 15 -- This file is part of 'SLAC Firmware Standard Library'. 16 -- It is subject to the license terms in the LICENSE.txt file found in the 17 -- top-level directory of this distribution and at: 18 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 19 -- No part of 'SLAC Firmware Standard Library', including this file, 20 -- may be copied, modified, propagated, or distributed except according to 21 -- the terms contained in the LICENSE.txt file. 22 ------------------------------------------------------------------------------- 25 use ieee.std_logic_1164.
all;
26 use ieee.std_logic_arith.
all;
27 use ieee.std_logic_unsigned.
all;
36 --! @ingroup protocols_srp 55 -- AXIS Slave Interface (sAxisClk domain) 61 -- AXIS Master Interface (mAxisClk domain) 66 -- Master AXI-Lite Interface (axilClk domain) 79 constant TIMEOUT_C : := (getTimeRatio(SRP_CLK_FREQ_G, 10.
0) - 1);
-- 100 ms timeout 101 type RegType is record 102 timer : range 0 to TIMEOUT_C;
103 hdrCnt : slv(3 downto 0);
105 timeoutSize : slv(7 downto 0);
106 timeoutCnt : slv(7 downto 0);
107 txnCnt : slv(29 downto 0);
108 memResp : slv(7 downto 0);
121 constant REG_INIT_C : RegType := ( 123 hdrCnt => (others => '0'), 124 remVer => (others => '0'), 125 timeoutSize => (others => '0'), 126 timeoutCnt => (others => '0'), 127 txnCnt => (others => '0'), 128 memResp => (others => '0'), 135 txMaster => axiStreamMasterInit(SRP_AXIS_CONFIG_C), 138 srpWrMaster => axiStreamMasterInit(SRP_AXIS_CONFIG_C), 141 signal r : RegType := REG_INIT_C;
142 signal rin : RegType;
154 -- attribute dont_touch : string; 155 -- attribute dont_touch of r : signal is "TRUE"; 163 -- General Configurations 169 -- FIFO configurations 181 -- AXI Stream Port Configurations 210 dataIn
(0) => sCtrl.pause,
211 dataIn
(1) => sCtrl.idle,
212 dataOut
(0) => rxCtrl.pause,
213 dataOut
(1) => rxCtrl.idle
);
224 comb :
process (r, rxCtrl, rxMaster,
srpAck, srpRdMasterInt,
srpRst, srpWrSlaveInt, txSlave)
is 225 variable v : RegType;
227 -- Latch the current value 230 -- Set AxiStream defaults 233 if txSlave.tReady = '1' then 235 v.txMaster.tLast := '0';
236 v.txMaster.tUser := (others => '0');
241 if (srpWrSlaveInt.tReady = '1') then 243 v.txMaster.tLast := '0';
244 v.txMaster.tUser := (others => '0');
247 -- Timer is freerunning 248 -- Reset to 0 when TIMEOUT_C reached 249 if r.timer = TIMEOUT_C then 252 v.timer := r.timer + 1;
257 ---------------------------------------------------------------------- 260 v.memResp := (others => '0');
264 v.verMismatch := '0';
270 -- Reset other state registers 271 v.timeoutSize := (others => '0');
272 v.txnCnt := (others => '0');
273 v.hdrCnt := (others => '0');
275 -- Check for overflow 277 v.state := BLOWOFF_RX_S;
279 -- Check for extra read data (possibly from previous interrupted txn) 280 elsif (srpRdMasterInt.tValid = '1') then 281 v.state := BLOWOFF_READ_DATA_S;
283 -- Check for valid data 284 elsif rxMaster.tValid = '1' then 286 if (ssiGetUserSof(SRP_AXIS_CONFIG_C, rxMaster) = '1') then 287 -- Ok to start processing the header 288 v.state := HDR_REQ_S;
290 -- Blowoff any RX data if no SOF 291 v.state := BLOWOFF_RX_S;
295 ---------------------------------------------------------------------- 297 -- Dump rx data until tLast seen 299 if rxMaster.tValid = '1' and rxMaster.tLast = '1' then 303 ---------------------------------------------------------------------- 304 when BLOWOFF_READ_DATA_S => 305 -- Dump read data until tLast seen 307 if srpRdMasterInt.tValid = '1' and srpRdMasterInt.tLast = '1' then 311 ---------------------------------------------------------------------- 313 -- Check for valid data 314 if rxMaster.tValid = '1' then 318 -- Increment the header count 319 v.hdrCnt := r.hdrCnt + 1;
322 -- Check for tLast or EOFE 323 if rxMaster.tLast = '1' then 327 v.state := HDR_RESP_S;
330 -- Latch the request header fields based on which header word we're on 337 v.timeoutSize := rxMaster.tData(31 downto 24);
347 -- Reset frame error that might have been assigned above due to tLast 348 -- We expect tLast here 350 -- Check for no tLast 351 if (rxMaster.tLast = '0') then 352 -- Check for OP-codes that should have tLast 358 -- Check for OP-codes that should NOT have tLast 365 v.hdrCnt := (others => '0');
366 v.state := HDR_RESP_S;
373 ---------------------------------------------------------------------- 375 -- Check if ready to move data 376 if (v.txMaster.tValid = '0') then 377 -- Check for posted write 382 -- Increment the counter 383 v.hdrCnt := r.hdrCnt + 1;
388 ssiSetUserSof(SRP_AXIS_CONFIG_C, v.txMaster, '1');
393 v.txMaster.tData(31 downto 24) := r.timeoutSize;
410 -- Check for framing error or EOFE 411 if (r.frameError = '1') or (r.eofe = '1') then 415 -- Check for version mismatch 418 v.verMismatch := '1';
422 -- Check for invalid reqSize with respect to writes 431 -- Need to double check all the cases here 432 -- Check for non 32-bit transaction request 439 -- Check for non 32-bit address alignment 445 -- Check that request op is enabled 457 ------------------------------------------------------------------------------- 459 -- If no error found above, procede with read or write request 460 if (v.state /= FOOTER_S) then 461 -- Issue an SRP request 466 v.timeoutCnt := (others => '0');
477 -- Redundant null check but more opcodes could be added later 485 ---------------------------------------------------------------------- 487 -- Send read data through to txMaster 488 if (srpRdMasterInt.tValid = '1' and v.txMaster.tValid = '0') then 492 -- Zero out data segments where tkeep not set 493 -- There must be a more elegant way to do this 494 for i in 3 downto 0 loop 495 if (srpRdMasterInt.tKeep(i) = '1') then 496 v.txMaster.tData((i+1)*8-1 downto i*8) := srpRdMasterInt.tData((i+1)*8-1 downto i*8);
498 v.txMaster.tData((i+1)*8-1 downto i*8) := (others => '0');
504 -- If tLast before cntSize, eofe 505 -- if cntSize reached and no tlast, blead read data, eofe 506 v.txnCnt := r.txnCnt + 1;
508 -- Done when reqSize and tlast 509 v.state := WAIT_ACK_S;
510 elsif (srpRdMasterInt.tLast = '1') then 512 v.state := WAIT_ACK_S;
513 v.eofe := '1';
-- Should assign a memResp bit 515 -- No tLast when expected 517 v.eofe := '1';
-- Should assign a memResp bit 522 -- Check if timer enabled 523 if r.timeoutSize /= 0 then 524 -- Check 100 ms timer 525 if r.timer = TIMEOUT_C then 527 v.timeoutCnt := r.timeoutCnt + 1;
529 if v.timeoutCnt = r.timeoutSize then 538 ---------------------------------------------------------------------- 540 -- Check for valid data and both tx and srpWr ready 545 -- Echo the write data back, but not if posted write 547 v.txMaster.tData(31 downto 0) := rxMaster.tData(31 downto 0);
549 -- Set the write data bus 554 -- Set tkeep for last data word as it may not be a full word 555 if (rxMaster.tLast = '1') then 562 -- If tLast before cntSize, frameError 563 -- if cntSize reached and no tlast, blead write data, frame error 564 v.txnCnt := r.txnCnt + 1;
566 -- Done when reqSize reached and tlast 567 v.state := WAIT_ACK_S;
569 -- tLast too early or too late 570 -- Extra rxData will get blown off once IDLE_S state is reached 571 -- Due to missing SOF 572 v.state := WAIT_ACK_S;
578 -- Check if timer enabled 579 if r.timeoutSize /= 0 then 580 -- Check 100 ms timer 581 if r.timer = TIMEOUT_C then 583 v.timeoutCnt := r.timeoutCnt + 1;
585 if v.timeoutCnt = r.timeoutSize then 595 ---------------------------------------------------------------------- 597 -- Wait for final ack from downstream 603 -- Wait until both request and ack.done release before proceeding to footer 608 -- Check if timer enabled 609 if r.timeoutSize /= 0 then 610 -- Check 100 ms timer 611 if r.timer = TIMEOUT_C then 613 v.timeoutCnt := r.timeoutCnt + 1;
615 if v.timeoutCnt = r.timeoutSize then 624 ---------------------------------------------------------------------- 626 -- Might have arrived here after timeout with request still pending 630 -- Check if ready to move data 631 if (v.txMaster.tValid = '0') then 632 -- Check for posted write 637 -- Set the footer data 638 v.txMaster.tLast := '1';
639 v.txMaster.tData(7 downto 0) := r.memResp;
640 v.txMaster.tData(8) := r.timeout;
642 v.txMaster.tData(10) := r.frameError;
643 v.txMaster.tData(11) := r.verMismatch;
644 v.txMaster.tData(12) := r.reqError;
645 v.txMaster.tData(31 downto 13) := (others => '0');
652 -- Update the EOFE flag 653 if (rxMaster.tLast = '1') and (v.rxSlave.tReady = '1') then 654 v.eofe := ssiGetUserEofe(SRP_AXIS_CONFIG_C, rxMaster);
662 -- Register the variable for next clock cycle 666 rxSlave <= v.rxSlave;
675 if (rising_edge(srpClk)) then 676 r <= rin after TPD_G;
682 -- General Configurations 687 -- FIFO configurations 696 -- AXI Stream Port Configurations 711 -- Pipeline the rdData and wrData streams
TX_VALID_THOLD_Gpositive := 1
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
PIPE_STAGES_Gnatural range 0 to 16:= 0
natural range 0 to 8 TDEST_BITS_C
ALTERA_RAM_Gstring := "M9K"
SLAVE_READY_EN_Gboolean := true
ALTERA_RAM_Gstring := "M9K"
PIPE_STAGES_Gnatural range 0 to 16:= 1
slv( 31 downto 0) reqSize
GEN_SYNC_FIFO_Gboolean := false
out mAxisMasterAxiStreamMasterType
FIFO_PAUSE_THRESH_Gpositive := 1
BYTE_ACCESS_Gboolean := false
SLAVE_READY_EN_Gboolean := false
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
out sAxisSlaveAxiStreamSlaveType
in srpRdMasterAxiStreamMasterType
SLAVE_READY_EN_Gboolean := true
slv( 1 downto 0) := "00" SRP_READ_C
natural range 1 to 16 TDATA_BYTES_C
SrpV3ReqType :=(request => '0',remVer =>( others => '0'),opCode =>( others => '0'),spare =>( others => '0'),tid =>( others => '0'),addr =>( others => '0'),reqSize =>( others => '0')) SRPV3_REQ_INIT_C
in mAxisSlaveAxiStreamSlaveType
GEN_SYNC_FIFO_Gboolean := false
ALTERA_SYN_Gboolean := false
PIPE_STAGES_Gnatural range 0 to 16:= 1
in mAxisSlaveAxiStreamSlaveType
UNALIGNED_ACCESS_Gboolean := false
TkeepModeType TKEEP_MODE_C
GEN_SYNC_FIFO_Gboolean := false
XIL_DEVICE_Gstring := "7SERIES"
XIL_DEVICE_Gstring := "7SERIES"
ALTERA_SYN_Gboolean := false
VALID_THOLD_Gnatural := 1
natural range 0 to 8 TID_BITS_C
out srpRdSlaveAxiStreamSlaveType
in rstsl :=not RST_POLARITY_G
FIFO_FIXED_THRESH_Gboolean := true
in sAxisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
slv( 7 downto 0) respCode
slv( 7 downto 0) := x"03" SRP_VERSION_C
in sAxisMasterAxiStreamMasterType
USE_BUILT_IN_Gboolean := false
in srpWrSlaveAxiStreamSlaveType
out sAxisCtrlAxiStreamCtrlType
TUserModeType TUSER_MODE_C
natural range 0 to 8 TUSER_BITS_C
out mAxisMasterAxiStreamMasterType
out sAxisSlaveAxiStreamSlaveType
ALTERA_SYN_Gboolean := false
in mAxisSlaveAxiStreamSlaveType
AXI_STREAM_CONFIG_GAxiStreamConfigType := ssiAxiStreamConfig( 2)
FIFO_PAUSE_THRESH_Gpositive range 1 to 511:= 256
EN_FRAME_FILTER_Gboolean := true
in sAxisMasterAxiStreamMasterType
out mAxisMasterAxiStreamMasterType
out srpWrMasterAxiStreamMasterType
SLAVE_AXI_CONFIG_GAxiStreamConfigType := SSI_CONFIG_INIT_C
CASCADE_SIZE_Gpositive := 1
slv( 1 downto 0) := "01" SRP_WRITE_C
out sAxisCtrlAxiStreamCtrlType
ALTERA_RAM_Gstring := "M9K"
out sAxisSlaveAxiStreamSlaveType
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
USE_BUILT_IN_Gboolean := false
in rstsl :=not RST_POLARITY_G
out mAxisMasterAxiStreamMasterType
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
slv( 1 downto 0) := "11" SRP_NULL_C
CASCADE_PAUSE_SEL_Gnatural := 0
PIPE_STAGES_Gnatural := 1
MASTER_AXI_CONFIG_GAxiStreamConfigType := SSI_CONFIG_INIT_C
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
WRITE_EN_Gboolean := true
SRP_CLK_FREQ_Greal := 156.25E+6
slv( 1 downto 0) := "10" SRP_POSTED_WRITE_C
out sAxisSlaveAxiStreamSlaveType
in sAxisMasterAxiStreamMasterType