1 ------------------------------------------------------------------------------- 2 -- File : SrpV3AxiLite.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2016-03-22 5 -- Last update: 2017-06-18 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;
35 --! @ingroup protocols_srp 50 -- AXIS Slave Interface (sAxisClk domain) 56 -- AXIS Master Interface (mAxisClk domain) 61 -- Master AXI-Lite Interface (axilClk domain) 72 constant AXIS_CONFIG_C : AxiStreamConfigType := ssiAxiStreamConfig(4, TKEEP_COMP_C, TUSER_FIRST_LAST_C, 8);
73 constant TIMEOUT_C : := (getTimeRatio(AXIL_CLK_FREQ_G, 10.
0) - 1);
-- 100 ms timeout 75 constant SRP_VERSION_C : slv(7 downto 0) := x"03";
76 constant NON_POSTED_READ_C : slv(1 downto 0) := "00";
77 constant NON_POSTED_WRITE_C : slv(1 downto 0) := "01";
78 constant POSTED_WRITE_C : slv(1 downto 0) := "10";
79 constant NULL_C : slv(1 downto 0) := "11";
94 type RegType is record 95 timer : range 0 to TIMEOUT_C;
96 hdrCnt : slv(3 downto 0);
97 remVer : slv(7 downto 0);
98 opCode : slv(1 downto 0);
99 timeoutSize : slv(7 downto 0);
100 timeoutCnt : slv(7 downto 0);
101 tid : slv(31 downto 0);
102 tidDly : slv(31 downto 0);
-- simulation debug only 103 addr : slv(63 downto 0);
104 reqSize : slv(31 downto 0);
105 cnt : slv(29 downto 0);
106 cntSize : slv(29 downto 0);
107 memResp : slv(7 downto 0);
116 skip : sl;
-- simulation debug only 123 constant REG_INIT_C : RegType := ( 125 hdrCnt => (others => '0'), 126 remVer => (others => '0'), 127 opCode => (others => '0'), 128 timeoutSize => (others => '0'), 129 timeoutCnt => (others => '0'), 130 tid => (others => '0'), 131 tidDly => (others => '1'), 132 addr => (others => '0'), 133 reqSize => (others => '0'), 134 cnt => (others => '0'), 135 cntSize => (others => '0'), 136 memResp => (others => '0'), 142 ignoreMemResp => '0', 152 signal r : RegType := REG_INIT_C;
153 signal rin : RegType;
163 signal rxTLastTUser : slv(7 downto 0);
169 -- attribute dont_touch : string; 170 -- attribute dont_touch of r : signal is "TRUE"; 171 -- attribute dont_touch of axisMaster : signal is "TRUE"; 172 -- attribute dont_touch of axisSlave : signal is "TRUE"; 173 -- attribute dont_touch of sCtrl : signal is "TRUE"; 174 -- attribute dont_touch of rxMaster : signal is "TRUE"; 175 -- attribute dont_touch of rxSlave : signal is "TRUE"; 176 -- attribute dont_touch of rxCtrl : signal is "TRUE"; 177 -- attribute dont_touch of rxTLastTUser : signal is "TRUE"; 178 -- attribute dont_touch of txSlave : signal is "TRUE"; 179 -- attribute dont_touch of rst : signal is "TRUE"; 180 -- attribute dont_touch of sRst : signal is "TRUE"; 181 -- attribute dont_touch of rxRst : signal is "TRUE"; 213 -- General Configurations 219 -- FIFO configurations 231 -- AXI Stream Port Configurations 262 dataIn
(0) => sCtrl.pause,
263 dataIn
(1) => sCtrl.idle,
264 dataOut
(0) => rxCtrl.pause,
265 dataOut
(1) => rxCtrl.idle
);
284 rxMaster, rxTLastTUser, txSlave)
is 285 variable v : RegType;
287 -- Latch the current value 294 if txSlave.tReady = '1' then 296 v.txMaster.tLast := '0';
297 v.txMaster.tUser := (others => '0');
301 if r.timer = TIMEOUT_C then 305 -- Increment the timer 306 v.timer := r.timer + 1;
309 -- Check for overflow 310 if (rxCtrl.overflow = '1') and (r.rxRst = '0') then 312 v.overflowDet := '1';
317 ---------------------------------------------------------------------- 320 v.memResp := (others => '0');
324 v.verMismatch := '0';
325 v.reqSizeError := '0';
326 -- Reset all AXI-Lite flags 332 v.cnt := (others => '0');
333 -- Check for overflow 334 if r.overflowDet = '1' then 336 v.overflowDet := '0';
339 -- Check for valid data 340 elsif (rxMaster.tValid = '1') and (r.rxRst = '0') then 343 -- Check for SOF and no EOFE 344 if (ssiGetUserSof(AXIS_CONFIG_C, rxMaster) = '1') and (rxTLastTUser(SSI_EOFE_C) = '0') then 345 -- Latch the AXIS TDEST 347 -- Latch the header information 348 v.remVer := rxMaster.tData(7 downto 0);
349 v.opCode := rxMaster.tData(9 downto 8);
350 v.ignoreMemResp := rxMaster.tData(14);
351 v.timeoutSize := rxMaster.tData(31 downto 24);
352 -- Reset other header fields 353 v.tid := (others => '0');
354 v.addr := (others => '0');
355 v.reqSize := (others => '0');
357 if (rxMaster.tLast = '1') then 361 v.state := HDR_RESP_S;
364 v.state := HDR_REQ0_S;
368 ---------------------------------------------------------------------- 370 -- Check for valid data 371 if rxMaster.tValid = '1' then 374 -- Latch the request header field 375 v.tid(31 downto 0) := rxMaster.tData(31 downto 0);
377 if rxMaster.tLast = '1' then 381 v.state := HDR_RESP_S;
384 v.state := HDR_REQ1_S;
387 ---------------------------------------------------------------------- 389 -- Check for valid data 390 if rxMaster.tValid = '1' then 393 -- Latch the request header field 394 v.addr(31 downto 0) := rxMaster.tData(31 downto 0);
396 if rxMaster.tLast = '1' then 400 v.state := HDR_RESP_S;
403 v.state := HDR_REQ2_S;
406 ---------------------------------------------------------------------- 408 -- Check for valid data 409 if rxMaster.tValid = '1' then 412 -- Latch the request header field 413 v.addr(63 downto 32) := rxMaster.tData(31 downto 0);
415 if rxMaster.tLast = '1' then 419 v.state := HDR_RESP_S;
422 v.state := HDR_REQ3_S;
425 ---------------------------------------------------------------------- 427 -- Check for valid data 428 if rxMaster.tValid = '1' then 431 -- Latch the request header field 432 v.reqSize(31 downto 0) := rxMaster.tData(31 downto 0);
433 -- Check for no tLast 434 if (rxMaster.tLast = '0') then 435 -- Check for OP-codes that should have tLast 436 if (r.opCode = NULL_C) or (r.opCode = NON_POSTED_READ_C) then 441 -- Check for OP-codes that should NOT have tLast 442 if (r.opCode = POSTED_WRITE_C) or (r.opCode = NON_POSTED_WRITE_C) then 448 v.state := HDR_RESP_S;
450 ---------------------------------------------------------------------- 452 -- Check if ready to move data 453 if (v.txMaster.tValid = '0') then 454 -- Check for posted write 455 if r.opCode /= POSTED_WRITE_C then 459 -- Increment the counter 460 v.hdrCnt := r.hdrCnt + 1;
465 ssiSetUserSof(AXIS_CONFIG_C, v.txMaster, '1');
467 v.txMaster.tData(7 downto 0) := SRP_VERSION_C;
468 v.txMaster.tData(9 downto 8) := r.opCode;
469 v.txMaster.tData(10) := '0';
-- UnalignedAccess: 0 = not supported (only 32-bit alignment) 470 v.txMaster.tData(11) := '0';
-- MinAccessSize: 0 = 32-bit (4 byte) transactions only 471 v.txMaster.tData(12) := '0';
-- WriteEn: 0 = write operations are not supported 472 v.txMaster.tData(13) := '0';
-- ReadEn: 0 = read operations are not supported 473 v.txMaster.tData(14) := r.ignoreMemResp;
474 v.txMaster.tData(23 downto 15) := (others => '0');
-- Reserved 475 v.txMaster.tData(31 downto 24) := r.timeoutSize;
476 when x"1" => v.txMaster.tData(31 downto 0) := r.tid(31 downto 0);
477 when x"2" => v.txMaster.tData(31 downto 0) := r.addr(31 downto 0);
478 when x"3" => v.txMaster.tData(31 downto 0) := r.addr(63 downto 32);
480 v.txMaster.tData(31 downto 0) := r.reqSize(31 downto 0);
484 if r.opCode = NULL_C then 488 -- Check for framing error or EOFE 489 if (r.frameError = '1') or (r.eofe = '1') then 493 -- Check for version mismatch 494 if r.remVer /= SRP_VERSION_C then 496 v.verMismatch := '1';
500 -- Check for invalid reqSize with respect to writes 501 if ((r.opCode = NON_POSTED_WRITE_C) or (r.opCode = POSTED_WRITE_C)) and (r.reqSize(31 downto 12) /= 0) then 503 v.reqSizeError := '1';
507 -- Check for invalid address size (AXI-Lite only support 32-bit address space) 508 if (r.addr(63 downto 32) /= 0) then 514 -- Check for non 32-bit address alignment 515 if r.addr(1 downto 0) /= 0 then 521 -- Check for non 32-bit transaction request 522 if r.reqSize(1 downto 0) /= "11" then 528 -- If no error or NULL found above, then proceed with read or write request 529 if (v.state /= FOOTER_S) then 530 -- Set the counter size 531 v.cntSize := r.reqSize(31 downto 2);
533 if r.opCode = NON_POSTED_READ_C then 535 v.state := AXIL_RD_REQ_S;
536 -- Else it is a write 539 v.state := AXIL_WR_REQ_S;
544 ---------------------------------------------------------------------- 546 -- Check if ready to move data 547 if (v.txMaster.tValid = '0') then 548 -- Check for posted write 549 if r.opCode /= POSTED_WRITE_C then 553 -- Set the footer data 554 v.txMaster.tLast := '1';
555 v.txMaster.tData(7 downto 0) := r.memResp;
556 v.txMaster.tData(8) := r.timeout;
558 v.txMaster.tData(10) := r.frameError;
559 v.txMaster.tData(11) := r.verMismatch;
560 v.txMaster.tData(12) := r.reqSizeError;
561 v.txMaster.tData(31 downto 13) := (others => '0');
562 -- Debugging code for chipscope 564 if ((r.tidDly + 1) /= r.tid) then 570 ---------------------------------------------------------------------- 571 when AXIL_RD_REQ_S => 572 -- Check if ready to move data 573 if (v.txMaster.tValid = '0') then 574 -- Set the read address buses 576 -- Start AXI-Lite transaction 581 v.timeoutCnt := (others => '0');
583 v.state := AXIL_RD_RESP_S;
585 ---------------------------------------------------------------------- 586 when AXIL_RD_RESP_S => 587 -- Check if ready to move data 588 if (v.txMaster.tValid = '0') then 589 -- Check slave.arready flag 594 -- Check slave.rvalid flag 598 -- Latch the memory bus responds 599 if (r.ignoreMemResp = '0') then 602 -- Check for a valid responds 607 elsif (r.ignoreMemResp = '1') then 610 v.txMaster.tData(31 downto 0) := (others => '1');
613 -- Check if transaction is done 615 -- Check for memory bus error 616 if v.memResp /= 0 then 620 -- Increment the counter 623 if r.cnt = r.cntSize then 627 -- Increment the address 628 v.addr(31 downto 2) := r.addr(31 downto 2) + 1;
630 v.state := AXIL_RD_REQ_S;
635 -- Check if timer enabled 636 if r.timeoutSize /= 0 then 637 -- Check 100 ms timer 638 if r.timer = TIMEOUT_C then 640 v.timeoutCnt := r.timeoutCnt + 1;
642 if v.timeoutCnt = r.timeoutSize then 650 ---------------------------------------------------------------------- 651 when AXIL_WR_REQ_S => 652 -- Check for valid data and ready to move data 653 if (rxMaster.tValid = '1') and (v.txMaster.tValid = '0') then 656 -- Check for framing error 657 if (rxMaster.tLast = '1') and (r.cnt /= r.cntSize) then 662 -- Check for framing error 663 elsif (rxMaster.tLast = '0') and (r.cnt = r.cntSize) then 669 -- Check for posted write 670 if r.opCode /= POSTED_WRITE_C then 674 -- Echo the write data back 675 v.txMaster.tData(31 downto 0) := rxMaster.tData(31 downto 0);
676 -- Set the write address buses 678 -- Set the write data bus 680 -- Start AXI-Lite transaction 686 v.timeoutCnt := (others => '0');
688 v.state := AXIL_WR_RESP_S;
691 ---------------------------------------------------------------------- 692 when AXIL_WR_RESP_S => 693 -- Check the slave.awready flag 698 -- Check the slave.wready flag 703 -- Check the slave.bvalid flag 707 -- Latch the memory bus responds 708 if (r.ignoreMemResp = '0') then 712 -- Check if transaction is done 714 -- Check for memory bus error 715 if v.memResp /= 0 then 719 -- Increment the counter 722 if r.cnt = r.cntSize then 726 -- Increment the address 727 v.addr(31 downto 2) := r.addr(31 downto 2) + 1;
729 v.state := AXIL_WR_REQ_S;
733 -- Check if timer enabled 734 if r.timeoutSize /= 0 then 735 -- Check 100 ms timer 736 if r.timer = TIMEOUT_C then 738 v.timeoutCnt := r.timeoutCnt + 1;
740 if v.timeoutCnt = r.timeoutSize then 748 ---------------------------------------------------------------------- 751 -- Update the EOFE flag 752 if (rxMaster.tLast = '1') and (v.rxSlave.tReady = '1') then 753 v.eofe := ssiGetUserEofe(AXIS_CONFIG_C, rxMaster);
761 -- Register the variable for next clock cycle 765 rxSlave <= v.rxSlave;
775 r <= rin after TPD_G;
781 -- General Configurations 787 -- FIFO configurations 796 -- AXI Stream Port Configurations
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
FRAME_LIMIT_Gpositive := 1024
GEN_SYNC_FIFO_Gboolean := false
out sAxisCtrlAxiStreamCtrlType
in mAxisSlaveAxiStreamSlaveType
ALTERA_RAM_Gstring := "M9K"
AXI_STREAM_CONFIG_GAxiStreamConfigType := ssiAxiStreamConfig( 2)
SLAVE_FIFO_Gboolean := false
INT_PIPE_STAGES_Gnatural range 0 to 16:= 1
out mAxisMasterAxiStreamMasterType
PIPE_STAGES_Gnatural range 0 to 16:= 1
out sAxisSlaveAxiStreamSlaveType
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
AxiStreamMasterType :=(tValid => '0',tData =>( others => '0'),tStrb =>( others => '1'),tKeep =>( others => '1'),tLast => '0',tDest =>( others => '0'),tId =>( others => '0'),tUser =>( others => '0')) AXI_STREAM_MASTER_INIT_C
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
AXIL_CLK_FREQ_Greal := 156.25E+6
SLAVE_READY_EN_Gboolean := true
FIFO_FIXED_THRESH_Gboolean := true
FIFO_PAUSE_THRESH_Gpositive range 1 to 511:= 256
COMMON_CLK_Gboolean := false
natural range 1 to 16 TDATA_BYTES_C
out mAxisMasterAxiStreamMasterType
INT_DATA_WIDTH_Gnatural range 1 to 16:= 16
GEN_SYNC_FIFO_Gboolean := false
in mAxisSlaveAxiStreamSlaveType
out mAxilReadMasterAxiLiteReadMasterType
XIL_DEVICE_Gstring := "7SERIES"
PIPE_STAGES_Gnatural range 0 to 16:= 1
in rstsl :=not RST_POLARITY_G
INT_WIDTH_SELECT_Gstring := "WIDE"
INT_PIPE_STAGES_Gnatural range 0 to 16:= 0
in sAxisMasterAxiStreamMasterType
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
SLAVE_READY_EN_Gboolean := true
ALTERA_SYN_Gboolean := false
in mAxilReadSlaveAxiLiteReadSlaveType
out sAxisSlaveAxiStreamSlaveType
out sAxisSlaveAxiStreamSlaveType
ALTERA_SYN_Gboolean := false
in sAxisMasterAxiStreamMasterType
AxiLiteReadMasterType :=(araddr =>( others => '0'),arprot =>( others => '0'),arvalid => '0',rready => '1') AXI_LITE_READ_MASTER_INIT_C
ALTERA_RAM_Gstring := "M9K"
out mTLastTUserslv( 7 downto 0)
AxiLiteWriteMasterType :=(awaddr =>( others => '0'),awprot =>( others => '0'),awvalid => '0',wdata =>( others => '0'),wstrb =>( others => '1'),wvalid => '0',bready => '1') AXI_LITE_WRITE_MASTER_INIT_C
in sAxisMasterAxiStreamMasterType
out mAxisMasterAxiStreamMasterType
slv( 1 downto 0) := "00" AXI_RESP_OK_C
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
TX_VALID_THOLD_Gpositive := 1
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
USE_BUILT_IN_Gboolean := false
in rstsl :=not RST_POLARITY_G
EN_TIMEOUT_Gboolean := true
FIFO_PAUSE_THRESH_Ginteger range 1 to ( 2** 24):= 1
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
out mAxilWriteMasterAxiLiteWriteMasterType
MASTER_FIFO_Gboolean := false
in mAxilWriteSlaveAxiLiteWriteSlaveType
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
out sAxisCtrlAxiStreamCtrlType
SLAVE_READY_EN_Gboolean := false