diff --git a/axi/axi-stream/rtl/AxiStreamCompact.vhd b/axi/axi-stream/rtl/AxiStreamCompact.vhd new file mode 100644 index 0000000000..c1b020e8c7 --- /dev/null +++ b/axi/axi-stream/rtl/AxiStreamCompact.vhd @@ -0,0 +1,266 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: +-- Block to compact AXI-Streams if tKeep bits are not contiguous +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +-- use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiStreamPkg.all; + +entity AxiStreamCompact is + + generic ( + TPD_G : time := 1 ns; + RST_ASYNC_G : boolean := false; + PIPE_STAGES_G : natural := 0; + SLAVE_AXI_CONFIG_G : AxiStreamConfigType; + MASTER_AXI_CONFIG_G : AxiStreamConfigType); + port ( + -- Clock and Reset + axisClk : in sl; + axisRst : in sl; + -- Slave Port + sAxisMaster : in AxiStreamMasterType; + sAxisSlave : out AxiStreamSlaveType; + -- Master Port + mAxisMaster : out AxiStreamMasterType; + mAxisSlave : in AxiStreamSlaveType); +end entity AxiStreamCompact; + +architecture rtl of AxiStreamCompact is + + function getTKeepMin ( + tKeep : slv; + axisConfig : AxiStreamConfigType + ) + return natural is + variable tKeepFull : slv(AXI_STREAM_MAX_TKEEP_WIDTH_C-1 downto 0); + variable i : natural; + begin -- function getTKeepRange + tKeepFull := resize(tKeep, AXI_STREAM_MAX_TKEEP_WIDTH_C); + for i in 0 to axisConfig.TDATA_BYTES_C-1 loop + if tKeepFull(i) = '1' then + return i; + end if; + end loop; -- i + end function getTKeepMin; + + function getTKeepMax ( + tKeep : slv; + axisConfig : AxiStreamConfigType + ) + return natural is + variable tKeepFull : slv(AXI_STREAM_MAX_TKEEP_WIDTH_C-1 downto 0); + variable i : natural; + begin -- function getTKeepRange + tKeepFull := resize(tKeep, AXI_STREAM_MAX_TKEEP_WIDTH_C); + for i in axisConfig.TDATA_BYTES_C-1 downto 0 loop + if tKeepFull(i) = '1' then + return i; + end if; + end loop; -- i + end function getTKeepMax; + + constant SLV_BYTES_C : positive := SLAVE_AXI_CONFIG_G.TDATA_BYTES_C; + constant MST_BYTES_C : positive := MASTER_AXI_CONFIG_G.TDATA_BYTES_C; + + type RegType is record + count : natural; + obMaster : AxiStreamMasterType; + ibSlave : AxiStreamSlaveType; + tLastDet : boolean; + tLastOnNext : boolean; + tUserSet : boolean; + fullBus : boolean; + end record RegType; + + constant REG_INIT_C : RegType := ( + count => 0, + obMaster => axiStreamMasterInit(MASTER_AXI_CONFIG_G), + ibSlave => AXI_STREAM_SLAVE_INIT_C, + tLastDet => false, + tLastOnNext => false, + tUserSet => false, + fullBus => false + ); + + signal r : RegType := REG_INIT_C; + signal rin : RegType; + + signal pipeAxisMaster : AxiStreamMasterType; + signal pipeAxisSlave : AxiStreamSlaveType; + +begin -- architecture rtl + + -- Make sure data widths are the same + assert (MST_BYTES_C >= SLV_BYTES_C) + report "Master data widths must be greater or equal than slave" severity failure; + + comb : process (axisRst, pipeAxisSlave, r, sAxisMaster) is + variable v : RegType; + variable tKeepMin : natural; + variable tKeepWidth : natural; + variable tDataWidth : natural; + variable tDataMin : natural; + variable tDataCount : natural; + variable tDataVar : slv(sAxisMaster.tData'range); + begin -- process + -- Latch current value + v := r; + + -- Init ready + v.ibSlave.tReady := '0'; + v.tLastDet := false; + v.tLastOnNext := false; + + -- Choose ready source and clear valid + if (pipeAxisSlave.tReady = '1') then + v.obMaster.tValid := '0'; + end if; + + -- Accept input data + if v.obMaster.tValid = '0' and not r.tLastOnNext then + + -- Ready to accept + v.ibSlave.tReady := '1'; + + -- Input data is valid + if sAxisMaster.tValid = '1' then + + -- Reset full flags + v.fullBus := false; + + -- get tKeet boundaries + tKeepMin := getTKeepMin(sAxisMaster.tKeep, SLAVE_AXI_CONFIG_G); + tKeepWidth := getTKeep(sAxisMaster.tKeep, SLAVE_AXI_CONFIG_G); + tDataWidth := to_integer(shift_left(to_unsigned(tKeepWidth, SLV_BYTES_C), 3)); + tDataCount := to_integer(shift_left(to_unsigned(r.count, SLV_BYTES_C), 3)); + tDataMin := to_integer(shift_left(to_unsigned(tKeepMin, SLV_BYTES_C), 3)); + + -- Checks + -- -- Overflow + if tKeepWidth + r.count >= MASTER_AXI_CONFIG_G.TDATA_BYTES_C then + v.fullBus := true; + end if; + -- -- tLast + v.tLastDet := false; + if sAxisMaster.tLast = '1' then + v.tLastDet := true; + if tKeepWidth + r.count > MST_BYTES_C then + v.tLastDet := false; + v.tLastOnNext := true; + end if; + end if; + + -- Gen bus + -- Shift if bus was full + if r.fullBus and not r.tLastOnNext then + v.obMaster.tData := std_logic_vector(shift_right(unsigned(r.obMaster.tData), MST_BYTES_C*8)); + end if; + ---- Remove initial bits + tDataVar := std_logic_vector(shift_right(unsigned(sAxisMaster.tData), tDataMin)); + v.obMaster.tData(v.obMaster.tData'length-1 downto tDataCount+tDataWidth) := (others => '0'); + v.obMaster.tData(tDataCount+tDataWidth-1 downto tDataCount) := tDataVar(tDataWidth-1 downto 0); + v.obMaster.tKeep := (others => '0'); + v.obMaster.tKeep(r.count+tKeepWidth-1 downto 0) := (others => '1'); + if not r.tUserSet then + v.obMaster.tUser := sAxisMaster.tUser; + v.tUserSet := true; + end if; + + -- Update counter + v.count := r.count + tKeepWidth; + + -- Bus is full + if v.fullBus or v.tLastDet or r.tLastOnNext then + -- Set tValid + v.obMaster.tValid := '1'; + -- Update bit counter and shift data + if v.fullBus then + v.count := r.count + tKeepWidth - MST_BYTES_C; + else + v.count := 0; + end if; + -- Set tLast + if v.tLastDet and not v.tLastOnNext then + v.obMaster.tLast := '1'; + else + v.obMaster.tLast := '0'; + end if; + -- Set tData in case of forced tLast + if r.tLastOnNext then + v.obMaster.tData := std_logic_vector(shift_right(unsigned(r.obMaster.tData), MST_BYTES_C*8)); + v.obMaster.tKeep := std_logic_vector(shift_right(unsigned(r.obMaster.tKeep), MST_BYTES_C)); + v.obMaster.tLast := '1'; + end if; + v.tUserSet := false; + end if; + + end if; + end if; + + + sAxisSlave <= v.ibSlave; + pipeAxisMaster.tData(pipeAxisMaster.tData'length-1 downto MST_BYTES_C*8) <= (others => '0'); + pipeAxisMaster.tData((MST_BYTES_C*8)-1 downto 0) <= r.obMaster.tData((MST_BYTES_C*8)-1 downto 0); + pipeAxisMaster.tKeep(pipeAxisMaster.tKeep'length-1 downto MST_BYTES_C) <= (others => '0'); + pipeAxisMaster.tKeep((MST_BYTES_C)-1 downto 0) <= r.obMaster.tKeep((MST_BYTES_C)-1 downto 0); + pipeAxisMaster.tValid <= r.obMaster.tValid; + pipeAxisMaster.tUser <= r.obMaster.tUser; + pipeAxisMaster.tLast <= r.obMaster.tLast; + + -- Reset + if (RST_ASYNC_G = false and axisRst = '1') then + v := REG_INIT_C; + end if; + + -- Register the variable for next clock cycle + rin <= v; + + + end process comb; + + seq : process (axisClk, axisRst) is + begin + if (RST_ASYNC_G) and (axisRst = '1') then + r <= REG_INIT_C after TPD_G; + elsif rising_edge(axisClk) then + r <= rin after TPD_G; + end if; + end process seq; + + -- Optional output pipeline registers to ease timing + AxiStreamPipeline_1 : entity surf.AxiStreamPipeline + generic map ( + TPD_G => TPD_G, + RST_ASYNC_G => RST_ASYNC_G, + -- SIDE_BAND_WIDTH_G => SIDE_BAND_WIDTH_G, + PIPE_STAGES_G => PIPE_STAGES_G) + port map ( + axisClk => axisClk, + axisRst => axisRst, + sAxisMaster => pipeAxisMaster, + -- sSideBand => pipeSideBand, + sAxisSlave => pipeAxisSlave, + mAxisMaster => mAxisMaster, + -- mSideBand => mSideBand, + mAxisSlave => mAxisSlave); + + +end architecture rtl; diff --git a/axi/axi-stream/rtl/AxiStreamDeMux.vhd b/axi/axi-stream/rtl/AxiStreamDeMux.vhd index 5dd0cd8767..f1e798b3db 100644 --- a/axi/axi-stream/rtl/AxiStreamDeMux.vhd +++ b/axi/axi-stream/rtl/AxiStreamDeMux.vhd @@ -26,6 +26,7 @@ use surf.AxiStreamPkg.all; entity AxiStreamDeMux is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; NUM_MASTERS_G : integer range 1 to 256 := 12; MODE_G : string := "INDEXED"; -- Or "ROUTED" Or "DYNAMIC" @@ -39,7 +40,7 @@ entity AxiStreamDeMux is axisRst : in sl; -- Dynamic Route Table (only used when MODE_G = "DYNAMIC") dynamicRouteMasks : in slv8Array(NUM_MASTERS_G-1 downto 0) := (others => "00000000"); - dynamicRouteDests : in slv8Array(NUM_MASTERS_G-1 downto 0) := (others => "00000000"); + dynamicRouteDests : in slv8Array(NUM_MASTERS_G-1 downto 0) := (others => "00000000"); -- Slave sAxisMaster : in AxiStreamMasterType; sAxisSlave : out AxiStreamSlaveType; @@ -139,7 +140,7 @@ begin sAxisSlave <= v.slave; -- Reset - if (RST_ASYNC_G = false and axisRst = '1') then + if (RST_ASYNC_G = false and axisRst = RST_POLARITY_G) then v := REG_INIT_C; end if; @@ -151,14 +152,14 @@ begin end process comb; - GEN_VEC : - for i in (NUM_MASTERS_G-1) downto 0 generate + GEN_VEC : for i in (NUM_MASTERS_G-1) downto 0 generate U_Pipeline : entity surf.AxiStreamPipeline generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - PIPE_STAGES_G => PIPE_STAGES_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + PIPE_STAGES_G => PIPE_STAGES_G) port map ( axisClk => axisClk, axisRst => axisRst, @@ -171,7 +172,7 @@ begin seq : process (axisClk, axisRst) is begin - if (RST_ASYNC_G and axisRst = '1') then + if (RST_ASYNC_G and axisRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif rising_edge(axisClk) then r <= rin after TPD_G; diff --git a/axi/axi-stream/rtl/AxiStreamMux.vhd b/axi/axi-stream/rtl/AxiStreamMux.vhd index 7a12f90d5a..0b49679101 100644 --- a/axi/axi-stream/rtl/AxiStreamMux.vhd +++ b/axi/axi-stream/rtl/AxiStreamMux.vhd @@ -27,6 +27,7 @@ use surf.AxiStreamPkg.all; entity AxiStreamMux is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; PIPE_STAGES_G : integer range 0 to 16 := 0; NUM_SLAVES_G : integer range 1 to 256 := 4; @@ -308,7 +309,7 @@ begin sAxisSlaves <= v.slaves; -- Reset - if (RST_ASYNC_G = false and axisRst = '1') then + if (RST_ASYNC_G = false and axisRst = RST_POLARITY_G) then v := REG_INIT_C; end if; @@ -322,7 +323,7 @@ begin seq : process (axisClk, axisRst) is begin - if (RST_ASYNC_G) and (axisRst = '1') then + if (RST_ASYNC_G) and (axisRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif rising_edge(axisClk) then r <= rin after TPD_G; @@ -332,9 +333,10 @@ begin -- Optional output pipeline registers to ease timing AxiStreamPipeline_1 : entity surf.AxiStreamPipeline generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - PIPE_STAGES_G => PIPE_STAGES_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + PIPE_STAGES_G => PIPE_STAGES_G) port map ( axisClk => axisClk, axisRst => axisRst, diff --git a/axi/axi-stream/rtl/AxiStreamPipeline.vhd b/axi/axi-stream/rtl/AxiStreamPipeline.vhd index 8d706f866b..1a0cd2dcae 100644 --- a/axi/axi-stream/rtl/AxiStreamPipeline.vhd +++ b/axi/axi-stream/rtl/AxiStreamPipeline.vhd @@ -23,6 +23,7 @@ use surf.AxiStreamPkg.all; entity AxiStreamPipeline is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; SIDE_BAND_WIDTH_G : positive := 1; -- General purpose sideband PIPE_STAGES_G : natural := 0); @@ -148,7 +149,7 @@ begin mSideBand <= r.mSideBand(PIPE_STAGES_C); -- Synchronous Reset - if (RST_ASYNC_G = false and axisRst = '1') then + if (RST_ASYNC_G = false and axisRst = RST_POLARITY_G) then v := REG_INIT_C; end if; @@ -159,7 +160,7 @@ begin seq : process (axisClk, axisRst) is begin - if (RST_ASYNC_G and axisRst = '1') then + if (RST_ASYNC_G and axisRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif rising_edge(axisClk) then r <= rin after TPD_G; diff --git a/axi/axi-stream/rtl/AxiStreamTrailerAppend.vhd b/axi/axi-stream/rtl/AxiStreamTrailerAppend.vhd new file mode 100644 index 0000000000..6f7c26f401 --- /dev/null +++ b/axi/axi-stream/rtl/AxiStreamTrailerAppend.vhd @@ -0,0 +1,159 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: +-- Append transactions from a stream to transactions from another. +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.std_logic_arith.all; + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiStreamPkg.all; + +entity AxiStreamTrailerAppend is + generic ( + TPD_G : time := 1 ns; + RST_ASYNC_G : boolean := false; + PIPE_STAGES_G : natural := 0; + TRAILER_AXI_CONFIG_G : AxiStreamConfigType; + MASTER_SLAVE_AXI_CONFIG_G : AxiStreamConfigType); + port ( + -- Clock and Reset + axisClk : in sl; + axisRst : in sl; + -- Slave port + sAxisMaster : in AxiStreamMasterType; + sAxisSlave : out AxiStreamSlaveType; + -- Trailer data + sAxisTrailerMaster : in AxiStreamMasterType; + sAxisTrailerSlave : out AxiStreamSlaveType; + -- Master port + mAxisMaster : out AxiStreamMasterType; + mAxisSlave : in AxiStreamSlaveType); +end entity AxiStreamTrailerAppend; + +architecture rtl of AxiStreamTrailerAppend is + + type RegType is record + obMaster : AxiStreamMasterType; + ibSlaves : AxiStreamSlaveArray(1 downto 0); + sel : sl; + end record RegType; + + constant REG_INIT_C : RegType := ( + obMaster => axiStreamMasterInit(MASTER_SLAVE_AXI_CONFIG_G), + ibSlaves => (others => AXI_STREAM_SLAVE_INIT_C), + sel => '0' + ); + + signal r : RegType := REG_INIT_C; + signal rin : RegType; + + signal pipeAxisMaster : AxiStreamMasterType; + signal pipeAxisSlave : AxiStreamSlaveType; + +begin -- architecture rtl + + -- Make sure data widths are appropriate + assert (MASTER_SLAVE_AXI_CONFIG_G.TDATA_BYTES_C >= TRAILER_AXI_CONFIG_G.TDATA_BYTES_C) + report "Trailer data widths must be less or equal than axi-stream" severity failure; + + comb : process (axisRst, pipeAxisSlave, r, sAxisMaster, sAxisTrailerMaster) is + variable v : RegType; + variable ibM : AxiStreamMasterType; + begin -- process comb + v := r; + + -- Init ready + for i in 0 to 1 loop + v.ibSlaves(i).tReady := '0'; + end loop; -- i + + -- Choose ready source and clear valid + if (pipeAxisSlave.tReady = '1') then + v.obMaster.tValid := '0'; + end if; + + if v.obMaster.tValid = '0' then + -- Get inbound data + if r.sel = '0' then + ibM := sAxisMaster; + v.ibSlaves(0).tReady := '1'; + v.ibSlaves(1).tReady := '0'; + else + ibM := sAxisTrailerMaster; + v.ibSlaves(1).tReady := '1'; + v.ibSlaves(0).tReady := '0'; + end if; + + -- Mirror data until tLast + if ibM.tValid = '1' then + v.obMaster := ibM; + if ibM.tLast = '1' then + v.sel := not r.sel; + if r.sel = '0' then + v.obMaster.tLast := '0'; + else + -- tKeep workaround + v.obMaster.tKeep(v.obMaster.tKeep'length-1 downto 0) := (others => '0'); + v.obMaster.tKeep(TRAILER_AXI_CONFIG_G.TDATA_BYTES_C-1 downto 0) := (others => '1'); + end if; + end if; + end if; + + end if; + + -- Outputs + sAxisSlave <= v.ibSlaves(0); + sAxisTrailerSlave <= v.ibSlaves(1); + pipeAxisMaster <= r.obMaster; + + -- Reset + if (RST_ASYNC_G = false and axisRst = '1') then + v := REG_INIT_C; + end if; + + -- Register the variable for next clock cycle + rin <= v; + + end process comb; + + seq : process (axisClk, axisRst) is + begin + if (RST_ASYNC_G) and (axisRst = '1') then + r <= REG_INIT_C after TPD_G; + elsif rising_edge(axisClk) then + r <= rin after TPD_G; + end if; + end process seq; + + -- Optional output pipeline registers to ease timing + AxiStreamPipeline_1 : entity surf.AxiStreamPipeline + generic map ( + TPD_G => TPD_G, + RST_ASYNC_G => RST_ASYNC_G, + -- SIDE_BAND_WIDTH_G => SIDE_BAND_WIDTH_G, + PIPE_STAGES_G => PIPE_STAGES_G) + port map ( + axisClk => axisClk, + axisRst => axisRst, + sAxisMaster => pipeAxisMaster, + -- sSideBand => pipeSideBand, + sAxisSlave => pipeAxisSlave, + mAxisMaster => mAxisMaster, + -- mSideBand => mSideBand, + mAxisSlave => mAxisSlave); + +end architecture rtl; diff --git a/axi/axi-stream/rtl/AxiStreamTrailerRemove.vhd b/axi/axi-stream/rtl/AxiStreamTrailerRemove.vhd new file mode 100644 index 0000000000..f6c29e6595 --- /dev/null +++ b/axi/axi-stream/rtl/AxiStreamTrailerRemove.vhd @@ -0,0 +1,177 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: +-- Removes bytes from end of a AXI stream frame +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.std_logic_arith.all; + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiStreamPkg.all; + +entity AxiStreamTrailerRemove is + generic ( + TPD_G : time := 1 ns; + RST_ASYNC_G : boolean := false; + PIPE_STAGES_G : natural := 0; + BYTES_TO_RM_G : integer := 4; + AXI_CONFIG_G : AxiStreamConfigType); + port ( + -- Clock and Reset + axisClk : in sl; + axisRst : in sl; + -- Inbound AXI Stream + sAxisMaster : in AxiStreamMasterType; + sAxisSlave : out AxiStreamSlaveType; + -- Inbound AXI Stream + mAxisMaster : out AxiStreamMasterType; + mAxisSlave : in AxiStreamSlaveType); +end entity AxiStreamTrailerRemove; + +architecture rtl of AxiStreamTrailerRemove is + + constant BYTES_C : positive := AXI_CONFIG_G.TDATA_BYTES_C; + + type RegType is record + obMaster : AxiStreamMasterType; + ibSlave : AxiStreamSlaveType; + regularTLast : boolean; + end record RegType; + + constant REG_INIT_C : RegType := ( + obMaster => axiStreamMasterInit(AXI_CONFIG_G), + ibSlave => AXI_STREAM_SLAVE_INIT_C, + regularTLast => true); + + signal r : RegType := REG_INIT_C; + signal rin : RegType; + + signal pipeAxisMaster : AxiStreamMasterType; + signal pipeAxisSlave : AxiStreamSlaveType; + signal axisMasterToPipe : AxiStreamMasterType; + signal axisSlaveToPipe : AxiStreamSlaveType; + signal axisMasterPipe : AxiStreamMasterType; + signal axisSlavePipe : AxiStreamSlaveType; + +begin + + -- Make sure data widths are appropriate + assert (BYTES_C >= BYTES_TO_RM_G) + report "Axi-Stream data widths must be greater or equal than trailer" severity failure; + + -- Connect Pipe + axisMasterToPipe <= sAxisMaster; + + -- Generate a delayed copy of incoming stream + AxiStreamPipeline_2 : entity surf.AxiStreamPipeline + generic map ( + TPD_G => TPD_G, + RST_ASYNC_G => RST_ASYNC_G, + -- SIDE_BAND_WIDTH_G => SIDE_BAND_WIDTH_G, + PIPE_STAGES_G => 1) + port map ( + axisClk => axisClk, + axisRst => axisRst, + sAxisMaster => axisMasterToPipe, + -- sSideBand => sSideBand, + sAxisSlave => axisSlaveToPipe, + mAxisMaster => axisMasterPipe, + -- mSideBand => mSideBand, + mAxisSlave => axisSlavePipe); + + comb : process (axisMasterPipe, axisRst, axisSlaveToPipe, pipeAxisSlave, r, + sAxisMaster) is + variable v : RegType; + variable ibM : AxiStreamMasterType; + variable count : integer range 0 to AXI_CONFIG_G.TDATA_BYTES_C; + variable toRm : integer range 0 to BYTES_TO_RM_G; + begin -- process comb + v := r; + + -- Init ready + v.ibSlave.tReady := '0'; + + -- Choose ready source and clear valid + if (pipeAxisSlave.tReady = '1') then + v.obMaster.tValid := '0'; + end if; + + -- Accept input data + if v.obMaster.tValid = '0' and axisSlaveToPipe.tReady = '1' then + -- Get inbound data + ibM := axisMasterPipe; + v.ibSlave.tReady := '1'; + + if ibM.tValid = '1' and r.regularTLast then + v.obMaster := ibM; + if sAxisMaster.tLast = '1' then + count := getTKeep(sAxisMaster.tKeep, AXI_CONFIG_G); + if count <= BYTES_TO_RM_G then + v.regularTLast := false; + toRm := BYTES_TO_RM_G - count; + v.obMaster.tLast := '1'; + count := getTKeep(ibM.tKeep, AXI_CONFIG_G); + v.obMaster.tKeep := (others => '0'); + v.obMaster.tKeep((count - toRm)-1 downto 0) := (others => '1'); + end if; + end if; + if ibM.tLast = '1' then + count := getTKeep(ibM.tKeep, AXI_CONFIG_G); + v.obMaster.tKeep := (others => '0'); + v.obMaster.tKeep((count - BYTES_TO_RM_G)-1 downto 0) := (others => '1'); + end if; + end if; + end if; + + -- Outputs + sAxisSlave <= v.ibSlave; + axisSlavePipe <= pipeAxisSlave; + pipeAxisMaster <= r.obMaster; + + -- Reset + if (RST_ASYNC_G = false and axisRst = '1') then + v := REG_INIT_C; + end if; + + -- Register the variable for next clock cycle + rin <= v; + + end process comb; + + seq : process (axisClk, axisRst) is + begin + if (RST_ASYNC_G) and (axisRst = '1') then + r <= REG_INIT_C after TPD_G; + elsif rising_edge(axisClk) then + r <= rin after TPD_G; + end if; + end process seq; + + -- Optional output pipeline registers to ease timing + AxiStreamPipeline_1 : entity surf.AxiStreamPipeline + generic map ( + TPD_G => TPD_G, + RST_ASYNC_G => RST_ASYNC_G, + PIPE_STAGES_G => PIPE_STAGES_G) + port map ( + axisClk => axisClk, + axisRst => axisRst, + sAxisMaster => pipeAxisMaster, + sAxisSlave => pipeAxisSlave, + mAxisMaster => mAxisMaster, + mAxisSlave => mAxisSlave); + +end architecture rtl; diff --git a/base/crc/rtl/Crc32.vhd b/base/crc/rtl/Crc32.vhd index 5293cd6ba3..1b3582de6a 100644 --- a/base/crc/rtl/Crc32.vhd +++ b/base/crc/rtl/Crc32.vhd @@ -34,15 +34,16 @@ use surf.CrcPkg.all; entity Crc32 is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; BYTE_WIDTH_G : positive := 4; INPUT_REGISTER_G : boolean := true; CRC_INIT_G : slv(31 downto 0) := x"FFFFFFFF"; CRC_POLY_G : slv(31 downto 0) := x"04C11DB7"); port ( - crcPwrOnRst : in sl := '0'; - crcOut : out slv(31 downto 0); -- CRC output - crcRem : out slv(31 downto 0); -- CRC interim remainder + crcPwrOnRst : in sl := not RST_POLARITY_G; + crcOut : out slv(31 downto 0); -- CRC output + crcRem : out slv(31 downto 0); -- CRC interim remainder crcClk : in sl; -- system clock crcDataValid : in sl; -- indicate that new data arrived and CRC can be computed crcDataWidth : in slv(2 downto 0); -- indicate width in bytes minus 1, 0 - 1 byte, 1 - 2 bytes ... , 7 - 8 bytes @@ -146,10 +147,10 @@ begin seq : process (crcClk, crcPwrOnRst) is begin - if (RST_ASYNC_G and crcPwrOnRst = '1') then + if (RST_ASYNC_G and crcPwrOnRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; - elsif (rising_edge(crcClk)) then - if (RST_ASYNC_G = false and crcPwrOnRst = '1') then + elsif (rising_edge(crcClk)) then + if (RST_ASYNC_G = false and crcPwrOnRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; else r <= rin after TPD_G; diff --git a/base/crc/rtl/Crc32Parallel.vhd b/base/crc/rtl/Crc32Parallel.vhd old mode 100755 new mode 100644 index 7222680894..aee2bededa --- a/base/crc/rtl/Crc32Parallel.vhd +++ b/base/crc/rtl/Crc32Parallel.vhd @@ -40,20 +40,21 @@ use surf.CrcPkg.all; entity Crc32Parallel is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; BYTE_WIDTH_G : positive := 4; INPUT_REGISTER_G : boolean := true; CRC_INIT_G : slv(31 downto 0) := x"FFFFFFFF"); port ( - crcPwrOnRst : in sl := '0'; - crcOut : out slv(31 downto 0); -- CRC output - crcRem : out slv(31 downto 0); -- CRC interim remainder + crcPwrOnRst : in sl := not RST_POLARITY_G; + crcOut : out slv(31 downto 0); -- CRC output + crcRem : out slv(31 downto 0); -- CRC interim remainder crcClk : in sl; -- system clock crcDataValid : in sl; -- indicate that new data arrived and CRC can be computed crcDataWidth : in slv(2 downto 0); -- indicate width in bytes minus 1, 0 - 1 byte, 1 - 2 bytes ... , 7 - 8 bytes crcIn : in slv((BYTE_WIDTH_G*8-1) downto 0); -- input data for CRC calculation crcInit : in slv(31 downto 0) := CRC_INIT_G; -- optional override of CRC_INIT_G - crcReset : in sl); -- initializes CRC logic to crcInit + crcReset : in sl); -- initializes CRC logic to crcInit end Crc32Parallel; architecture rtl of Crc32Parallel is @@ -188,10 +189,10 @@ begin seq : process (crcClk, crcPwrOnRst) is begin - if (RST_ASYNC_G and crcPwrOnRst = '1') then + if (RST_ASYNC_G and crcPwrOnRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; - elsif (rising_edge(crcClk)) then - if (RST_ASYNC_G = false and crcPwrOnRst = '1') then + elsif (rising_edge(crcClk)) then + if (RST_ASYNC_G = false and crcPwrOnRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; else r <= rin after TPD_G; diff --git a/base/general/rtl/Scrambler.vhd b/base/general/rtl/Scrambler.vhd index 614239cb64..c6a9948f69 100644 --- a/base/general/rtl/Scrambler.vhd +++ b/base/general/rtl/Scrambler.vhd @@ -25,6 +25,7 @@ use surf.StdRtlPkg.all; entity Scrambler is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; DIRECTION_G : string := "SCRAMBLER"; -- or DESCRAMBLER DATA_WIDTH_G : integer := 64; @@ -129,7 +130,7 @@ begin inputReady <= v.inputReady; -- Reset - if (RST_ASYNC_G = false and rst = '1') then + if (RST_ASYNC_G = false and rst = RST_POLARITY_G) then v := REG_INIT_C; end if; @@ -150,7 +151,7 @@ begin seq : process (clk, rst) is begin - if (RST_ASYNC_G and rst = '1') then + if (RST_ASYNC_G and rst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif rising_edge(clk) then r <= rin after TPD_G; diff --git a/base/sync/rtl/RstSync.vhd b/base/sync/rtl/RstSync.vhd index 0da4f2a68d..cca8ab948b 100644 --- a/base/sync/rtl/RstSync.vhd +++ b/base/sync/rtl/RstSync.vhd @@ -4,6 +4,9 @@ -- Description: Synchronizes the trailing edge of an asynchronous reset to a -- given clock. ------------------------------------------------------------------------------- +-- Note: Using "std_logic" instead of "sl" for generics due to issues with +-- SystemVerilog handling VHDL subtype on generics properly +------------------------------------------------------------------------------- -- This file is part of 'SLAC Firmware Standard Library'. -- It is subject to the license terms in the LICENSE.txt file found in the -- top-level directory of this distribution and at: @@ -21,9 +24,9 @@ use surf.StdRtlPkg.all; entity RstSync is generic ( - TPD_G : time := 1 ns; -- Simulation FF output delay - IN_POLARITY_G : sl := '1'; -- 0 for active low rst, 1 for high - OUT_POLARITY_G : sl := '1'; + TPD_G : time := 1 ns; -- Simulation FF output delay + IN_POLARITY_G : std_logic := '1'; -- 0 for active low rst, 1 for high + OUT_POLARITY_G : std_logic := '1'; BYPASS_SYNC_G : boolean := false; -- Bypass Synchronizer module for synchronous data configuration RELEASE_DELAY_G : integer range 3 to positive'high := 3; -- Delay between deassertion of async and sync resets OUT_REG_RST_G : boolean := true); -- Apply async reset to final reg stage @@ -57,7 +60,7 @@ begin dataOut => syncInt); -- Final stage does not have async constraints applied, can be duplicated to ease timing - OUT_REG : process (clk, asyncRst) is + OUT_REG : process (asyncRst, clk) is begin if (asyncRst = IN_POLARITY_G and OUT_REG_RST_G) then syncRst <= OUT_POLARITY_G after TPD_G; diff --git a/base/sync/rtl/SynchronizerFifo.vhd b/base/sync/rtl/SynchronizerFifo.vhd index 7b50cff926..4233d12fd6 100644 --- a/base/sync/rtl/SynchronizerFifo.vhd +++ b/base/sync/rtl/SynchronizerFifo.vhd @@ -22,18 +22,19 @@ use surf.StdRtlPkg.all; entity SynchronizerFifo is generic ( - TPD_G : time := 1 ns; - RST_ASYNC_G : boolean := false; - COMMON_CLK_G : boolean := false; -- Bypass FifoAsync module for synchronous data configuration - MEMORY_TYPE_G : string := "distributed"; - SYNC_STAGES_G : integer range 3 to (2**24) := 3; - PIPE_STAGES_G : natural range 0 to 16 := 0; - DATA_WIDTH_G : integer range 1 to (2**24) := 16; - ADDR_WIDTH_G : integer range 2 to 48 := 4; - INIT_G : slv := "0"); + TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset + RST_ASYNC_G : boolean := false; + COMMON_CLK_G : boolean := false; -- Bypass FifoAsync module for synchronous data configuration + MEMORY_TYPE_G : string := "distributed"; + SYNC_STAGES_G : integer range 3 to (2**24) := 3; + PIPE_STAGES_G : natural range 0 to 16 := 0; + DATA_WIDTH_G : integer range 1 to (2**24) := 16; + ADDR_WIDTH_G : integer range 2 to 48 := 4; + INIT_G : slv := "0"); port ( -- Asynchronous Reset - rst : in sl := '0'; + rst : in sl := not RST_POLARITY_G; -- Write Ports (wr_clk domain) wr_clk : in sl; wr_en : in sl := '1'; @@ -58,15 +59,16 @@ begin FifoAsync_1 : entity surf.FifoAsync generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - MEMORY_TYPE_G => MEMORY_TYPE_G, - FWFT_EN_G => true, - SYNC_STAGES_G => SYNC_STAGES_G, - PIPE_STAGES_G => PIPE_STAGES_G, - DATA_WIDTH_G => DATA_WIDTH_G, - ADDR_WIDTH_G => ADDR_WIDTH_G, - INIT_G => INIT_C) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + MEMORY_TYPE_G => MEMORY_TYPE_G, + FWFT_EN_G => true, + SYNC_STAGES_G => SYNC_STAGES_G, + PIPE_STAGES_G => PIPE_STAGES_G, + DATA_WIDTH_G => DATA_WIDTH_G, + ADDR_WIDTH_G => ADDR_WIDTH_G, + INIT_G => INIT_C) port map ( rst => rst, wr_clk => wr_clk, diff --git a/ethernet/UdpEngine/rtl/UdpEngineRx.vhd b/ethernet/UdpEngine/rtl/UdpEngineRx.vhd index 5bb594e4b8..fc5269c60b 100644 --- a/ethernet/UdpEngine/rtl/UdpEngineRx.vhd +++ b/ethernet/UdpEngine/rtl/UdpEngineRx.vhd @@ -263,6 +263,10 @@ begin v.byteCnt(7 downto 0) := rxMaster.tData(79 downto 72); -- Remove the 8 byte UDP header v.byteCnt := v.byteCnt - 8; + -- Remove the RoCEv2 iCRC + if rxMaster.tData(63 downto 48) = x"B712" then + v.byteCnt := v.byteCnt - 4; + end if; -- Track the leftovers v.tData(31 downto 0) := rxMaster.tData(127 downto 96); -- Set the flag diff --git a/protocols/packetizer/rtl/AxiStreamDepacketizer2.vhd b/protocols/packetizer/rtl/AxiStreamDepacketizer2.vhd index 8f7912faa6..4571eb9c35 100644 --- a/protocols/packetizer/rtl/AxiStreamDepacketizer2.vhd +++ b/protocols/packetizer/rtl/AxiStreamDepacketizer2.vhd @@ -30,6 +30,7 @@ use surf.AxiStreamPacketizer2Pkg.all; entity AxiStreamDepacketizer2 is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; MEMORY_TYPE_G : string := "distributed"; REG_EN_G : boolean := false; @@ -159,9 +160,10 @@ begin ----------------- U_Input : entity surf.AxiStreamPipeline generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - PIPE_STAGES_G => INPUT_PIPE_STAGES_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + PIPE_STAGES_G => INPUT_PIPE_STAGES_G) port map ( axisClk => axisClk, axisRst => axisRst, @@ -186,15 +188,16 @@ begin GEN_SEQ : if (SEQ_CNT_SIZE_G > 0) generate U_DualPortRam_1 : entity surf.DualPortRam generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - MEMORY_TYPE_G => MEMORY_TYPE_G, - REG_EN_G => REG_EN_G, - DOA_REG_G => REG_EN_G, - DOB_REG_G => REG_EN_G, - BYTE_WR_EN_G => false, - DATA_WIDTH_G => RAM_DATA_WIDTH_C, - ADDR_WIDTH_G => ADDR_WIDTH_C) + TPD_G => TPD_G, + RST_ASYNC_G => RST_ASYNC_G, + RST_POLARITY_G => RST_POLARITY_G, + MEMORY_TYPE_G => MEMORY_TYPE_G, + REG_EN_G => REG_EN_G, + DOA_REG_G => REG_EN_G, + DOB_REG_G => REG_EN_G, + BYTE_WR_EN_G => false, + DATA_WIDTH_G => RAM_DATA_WIDTH_C, + ADDR_WIDTH_G => ADDR_WIDTH_C) port map ( clka => axisClk, rsta => axisRst, @@ -207,10 +210,10 @@ begin NO_SEQ : if (SEQ_CNT_SIZE_G = 0) generate process (axisClk, axisRst) is begin - if (RST_ASYNC_G and axisRst = '1') then + if (RST_ASYNC_G and axisRst = RST_POLARITY_G) then ramDout <= (others => '0') after TPD_G; elsif (rising_edge(axisClk)) then - if (RST_ASYNC_G = false and axisRst = '1') then + if (RST_ASYNC_G = false and axisRst = RST_POLARITY_G) then ramDout <= (others => '0') after TPD_G; else ramDout <= ramDin after TPD_G; @@ -228,6 +231,7 @@ begin U_Crc32 : entity surf.Crc32Parallel generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, INPUT_REGISTER_G => false, BYTE_WIDTH_G => 8, @@ -248,6 +252,7 @@ begin U_Crc32 : entity surf.Crc32 generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, INPUT_REGISTER_G => false, BYTE_WIDTH_G => 8, @@ -649,10 +654,10 @@ begin seq : process (axisClk, axisRst) is begin - if (RST_ASYNC_G and axisRst = '1') then + if (RST_ASYNC_G and axisRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif (rising_edge(axisClk)) then - if (RST_ASYNC_G = false and axisRst = '1') then + if (RST_ASYNC_G = false and axisRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; else r <= rin after TPD_G; @@ -665,9 +670,10 @@ begin ------------------ U_Output : entity surf.AxiStreamPipeline generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - PIPE_STAGES_G => OUTPUT_PIPE_STAGES_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + PIPE_STAGES_G => OUTPUT_PIPE_STAGES_G) port map ( axisClk => axisClk, axisRst => axisRst, diff --git a/protocols/pgp/pgp3/core/rtl/Pgp3RxGearboxAligner.vhd b/protocols/pgp/pgp3/core/rtl/Pgp3RxGearboxAligner.vhd index 73afb8b48d..0b175365e0 100644 --- a/protocols/pgp/pgp3/core/rtl/Pgp3RxGearboxAligner.vhd +++ b/protocols/pgp/pgp3/core/rtl/Pgp3RxGearboxAligner.vhd @@ -27,9 +27,10 @@ use surf.StdRtlPkg.all; entity Pgp3RxGearboxAligner is generic ( - TPD_G : time := 1 ns; - RST_ASYNC_G : boolean := false; - SLIP_WAIT_G : integer := 32); + TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset + RST_ASYNC_G : boolean := false; + SLIP_WAIT_G : integer := 32); port ( clk : in sl; rst : in sl; @@ -119,7 +120,7 @@ begin when others => null; end case; - if (RST_ASYNC_G = false and rst = '1') then + if (RST_ASYNC_G = false and rst = RST_POLARITY_G) then v := REG_INIT_C; end if; @@ -132,7 +133,7 @@ begin seq : process (clk, rst) is begin - if (RST_ASYNC_G) and (rst = '1') then + if (RST_ASYNC_G) and (rst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif rising_edge(clk) then r <= rin after TPD_G; diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4Rx.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4Rx.vhd index 8a61df5ebd..4460018892 100644 --- a/protocols/pgp/pgp4/core/rtl/Pgp4Rx.vhd +++ b/protocols/pgp/pgp4/core/rtl/Pgp4Rx.vhd @@ -29,6 +29,7 @@ use surf.AxiStreamPacketizer2Pkg.all; entity Pgp4Rx is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; NUM_VC_G : integer range 1 to 16 := 4; SKIP_EN_G : boolean := true; -- TRUE for Elastic Buffer @@ -99,9 +100,10 @@ begin -- Gearbox aligner U_Pgp3RxGearboxAligner_1 : entity surf.Pgp3RxGearboxAligner -- Same RX gearbox aligner as PGPv3 generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - SLIP_WAIT_G => ALIGN_SLIP_WAIT_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + SLIP_WAIT_G => ALIGN_SLIP_WAIT_G) port map ( clk => phyRxClk, -- [in] rst => phyRxRst, -- [in] @@ -115,6 +117,7 @@ begin U_Scrambler_1 : entity surf.Scrambler generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, DIRECTION_G => "DESCRAMBLER", DATA_WIDTH_G => 64, @@ -134,8 +137,9 @@ begin -- Elastic Buffer U_Pgp4RxEb_1 : entity surf.Pgp4RxEb generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G) port map ( phyRxClk => phyRxClk, -- [in] phyRxRst => phyRxRst, -- [in] @@ -161,9 +165,10 @@ begin -- Main RX protocol logic U_Pgp4RxProtocol_1 : entity surf.Pgp4RxProtocol generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - NUM_VC_G => NUM_VC_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + NUM_VC_G => NUM_VC_G) port map ( pgpRxClk => pgpRxClk, -- [in] pgpRxRst => pgpRxRst, -- [in] @@ -185,6 +190,7 @@ begin U_AxiStreamDepacketizer2_1 : entity surf.AxiStreamDepacketizer2 generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, MEMORY_TYPE_G => "distributed", CRC_MODE_G => "DATA", @@ -206,13 +212,14 @@ begin -- Demultiplex the depacketized streams U_AxiStreamDeMux_1 : entity surf.AxiStreamDeMux generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - NUM_MASTERS_G => NUM_VC_G, - MODE_G => "INDEXED", - PIPE_STAGES_G => 0, - TDEST_HIGH_G => 7, - TDEST_LOW_G => 0) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + NUM_MASTERS_G => NUM_VC_G, + MODE_G => "INDEXED", + PIPE_STAGES_G => 0, + TDEST_HIGH_G => 7, + TDEST_LOW_G => 0) port map ( axisClk => pgpRxClk, -- [in] axisRst => pgpRxRst, -- [in] diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4RxEb.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4RxEb.vhd index 71164c686b..78a66cab2c 100644 --- a/protocols/pgp/pgp4/core/rtl/Pgp4RxEb.vhd +++ b/protocols/pgp/pgp4/core/rtl/Pgp4RxEb.vhd @@ -25,8 +25,9 @@ use surf.Pgp4Pkg.all; entity Pgp4RxEb is generic ( - TPD_G : time := 1 ns; - RST_ASYNC_G : boolean := false); + TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset + RST_ASYNC_G : boolean := false); port ( phyRxClk : in sl; phyRxRst : in sl; @@ -112,7 +113,7 @@ begin end if; -- Reset - if (RST_ASYNC_G = false and phyRxRst = '1') then + if (RST_ASYNC_G = false and phyRxRst = RST_POLARITY_G) then -- Maintain save behavior before the remLinkData update (not reseting fifoIn or fifoWrEn) v.remLinkData := (others => '0'); end if; @@ -124,7 +125,7 @@ begin seq : process (phyRxClk, phyRxRst) is begin - if (RST_ASYNC_G) and (phyRxRst = '1') then + if (RST_ASYNC_G) and (phyRxRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif rising_edge(phyRxClk) then r <= rin after TPD_G; @@ -133,9 +134,10 @@ begin U_remLinkData : entity surf.SynchronizerFifo generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - DATA_WIDTH_G => 48) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + DATA_WIDTH_G => 48) port map ( rst => phyRxRst, wr_clk => phyRxClk, @@ -146,13 +148,14 @@ begin U_FifoAsync_1 : entity surf.FifoAsync generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - MEMORY_TYPE_G => "block", - FWFT_EN_G => true, - PIPE_STAGES_G => 0, - DATA_WIDTH_G => 66, - ADDR_WIDTH_G => 9) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + MEMORY_TYPE_G => "block", + FWFT_EN_G => true, + PIPE_STAGES_G => 0, + DATA_WIDTH_G => 66, + ADDR_WIDTH_G => 9) port map ( rst => phyRxRst, -- Write Interface diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeed.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeed.vhd new file mode 100644 index 0000000000..ad9eb2fb81 --- /dev/null +++ b/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeed.vhd @@ -0,0 +1,182 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: Pgp4RxLite Low Speed Wrapper +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiStreamPkg.all; +use surf.AxiLitePkg.all; +use surf.Pgp4Pkg.all; + +entity Pgp4LiteRxLowSpeed is + generic ( + TPD_G : time := 1 ns; + SIMULATION_G : boolean := false; + DLY_STEP_SIZE_G : positive range 1 to 255 := 1; + NUM_LANE_G : positive := 1; + STATUS_CNT_WIDTH_G : natural range 1 to 32 := 16; + ERROR_CNT_WIDTH_G : natural range 1 to 32 := 8; + AXIL_CLK_FREQ_G : real; -- In units of HZ + AXIL_BASE_ADDR_G : slv(31 downto 0)); + port ( + -- Deserialization Interface (deserClk domain) + deserClk : in sl; + deserRst : in sl; + deserData : in Slv8Array(NUM_LANE_G-1 downto 0); + dlyLoad : out slv(NUM_LANE_G-1 downto 0); + dlyCfg : out Slv9Array(NUM_LANE_G-1 downto 0); + -- PGP Streaming Outputs (deserClk domain) + pgpRxMasters : out AxiStreamMasterArray(NUM_LANE_G-1 downto 0); + -- AXI-Lite Interface (axilClk domain) + axilClk : in sl; + axilRst : in sl; + axilReadMaster : in AxiLiteReadMasterType; + axilReadSlave : out AxiLiteReadSlaveType; + axilWriteMaster : in AxiLiteWriteMasterType; + axilWriteSlave : out AxiLiteWriteSlaveType); +end Pgp4LiteRxLowSpeed; + +architecture mapping of Pgp4LiteRxLowSpeed is + + constant NUM_AXIL_MASTERS_C : positive := NUM_LANE_G+1; + + constant XBAR_CONFIG_C : AxiLiteCrossbarMasterConfigArray(NUM_AXIL_MASTERS_C-1 downto 0) := genAxiLiteConfig(NUM_AXIL_MASTERS_C, AXIL_BASE_ADDR_G, 20, 12); + + signal axilWriteMasters : AxiLiteWriteMasterArray(NUM_AXIL_MASTERS_C-1 downto 0); + signal axilWriteSlaves : AxiLiteWriteSlaveArray(NUM_AXIL_MASTERS_C-1 downto 0) := (others => AXI_LITE_WRITE_SLAVE_EMPTY_SLVERR_C); + signal axilReadMasters : AxiLiteReadMasterArray(NUM_AXIL_MASTERS_C-1 downto 0); + signal axilReadSlaves : AxiLiteReadSlaveArray(NUM_AXIL_MASTERS_C-1 downto 0) := (others => AXI_LITE_READ_SLAVE_EMPTY_SLVERR_C); + + signal deserReset : sl; + signal dlyConfig : Slv9Array(NUM_LANE_G-1 downto 0); + + signal enUsrDlyCfg : sl; + signal usrDlyCfg : Slv9Array(NUM_LANE_G-1 downto 0); + signal minEyeWidth : slv(7 downto 0); + signal lockingCntCfg : slv(23 downto 0); + signal bypFirstBerDet : sl; + signal polarity : slv(NUM_LANE_G-1 downto 0); + signal bitOrder : slv(1 downto 0); + signal errorDet : slv(NUM_LANE_G-1 downto 0); + signal bitSlip : slv(NUM_LANE_G-1 downto 0); + signal eyeWidth : Slv9Array(NUM_LANE_G-1 downto 0); + signal locked : slv(NUM_LANE_G-1 downto 0); + +begin + + dlyCfg <= dlyConfig; + + U_deserReset : entity surf.RstPipeline + generic map ( + TPD_G => TPD_G) + port map ( + clk => deserClk, + rstIn => deserRst, + rstOut => deserReset); + + U_XBAR : entity surf.AxiLiteCrossbar + generic map ( + TPD_G => TPD_G, + NUM_SLAVE_SLOTS_G => 1, + NUM_MASTER_SLOTS_G => NUM_AXIL_MASTERS_C, + MASTERS_CONFIG_G => XBAR_CONFIG_C) + port map ( + axiClk => axilClk, + axiClkRst => axilRst, + sAxiWriteMasters(0) => axilWriteMaster, + sAxiWriteSlaves(0) => axilWriteSlave, + sAxiReadMasters(0) => axilReadMaster, + sAxiReadSlaves(0) => axilReadSlave, + mAxiWriteMasters => axilWriteMasters, + mAxiWriteSlaves => axilWriteSlaves, + mAxiReadMasters => axilReadMasters, + mAxiReadSlaves => axilReadSlaves); + + U_Reg : entity surf.Pgp4RxLiteLowSpeedReg + generic map ( + TPD_G => TPD_G, + SIMULATION_G => SIMULATION_G, + STATUS_CNT_WIDTH_G => STATUS_CNT_WIDTH_G, + NUM_LANE_G => NUM_LANE_G) + port map ( + -- Deserialization Interface (deserClk domain) + deserClk => deserClk, + deserRst => deserRst, + dlyConfig => dlyConfig, + errorDet => errorDet, + bitSlip => bitSlip, + eyeWidth => eyeWidth, + locked => locked, + enUsrDlyCfg => enUsrDlyCfg, + usrDlyCfg => usrDlyCfg, + minEyeWidth => minEyeWidth, + lockingCntCfg => lockingCntCfg, + bypFirstBerDet => bypFirstBerDet, + polarity => polarity, + bitOrder => bitOrder, + -- AXI-Lite Interface (axilClk domain) + axilClk => axilClk, + axilRst => axilRst, + axilReadMaster => axilReadMasters(0), + axilReadSlave => axilReadSlaves(0), + axilWriteMaster => axilWriteMasters(0), + axilWriteSlave => axilWriteSlaves(0)); + + GEN_LANE : + for i in NUM_LANE_G-1 downto 0 generate + + U_PgpLane : entity surf.Pgp4RxLiteLowSpeedLane + generic map ( + TPD_G => TPD_G, + SIMULATION_G => SIMULATION_G, + DLY_STEP_SIZE_G => DLY_STEP_SIZE_G, + STATUS_CNT_WIDTH_G => STATUS_CNT_WIDTH_G, + ERROR_CNT_WIDTH_G => ERROR_CNT_WIDTH_G, + AXIL_CLK_FREQ_G => AXIL_CLK_FREQ_G) + port map ( + -- Deserialization Interface (deserClk domain) + deserClk => deserClk, + deserRst => deserReset, + deserData => deserData(i), + dlyLoad => dlyLoad(i), + dlyCfg => dlyConfig(i), + -- Config/Status Interface (deserClk domain) + enUsrDlyCfg => enUsrDlyCfg, + usrDlyCfg => usrDlyCfg(i), + minEyeWidth => minEyeWidth, + lockingCntCfg => lockingCntCfg, + bypFirstBerDet => bypFirstBerDet, + polarity => polarity(i), + bitOrder => bitOrder, + errorDet => errorDet(i), + bitSlip => bitSlip(i), + eyeWidth => eyeWidth(i), + locked => locked(i), + -- PGP Streaming Outputs (deserClk domain) + pgpRxMaster => pgpRxMasters(i), + -- AXI-Lite Register Interface (axilClk domain) + axilClk => axilClk, + axilRst => axilRst, + axilReadMaster => axilReadMasters(i+1), + axilReadSlave => axilReadSlaves(i+1), + axilWriteMaster => axilWriteMasters(i+1), + axilWriteSlave => axilWriteSlaves(i+1)); + + end generate GEN_LANE; + +end mapping; diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeedLane.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeedLane.vhd new file mode 100644 index 0000000000..c533f3a121 --- /dev/null +++ b/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeedLane.vhd @@ -0,0 +1,205 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: Wrapper on the Pgp4RxLite Low Speed Lane +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiStreamPkg.all; +use surf.AxiLitePkg.all; +use surf.Pgp4Pkg.all; + +entity Pgp4RxLiteLowSpeedLane is + generic ( + TPD_G : time := 1 ns; + SIMULATION_G : boolean := false; + DLY_STEP_SIZE_G : positive range 1 to 255 := 1; + STATUS_CNT_WIDTH_G : natural range 1 to 32 := 16; + ERROR_CNT_WIDTH_G : natural range 1 to 32 := 8; + AXIL_CLK_FREQ_G : real); -- In units of HZ + port ( + -- Deserialization Interface (deserClk domain) + deserClk : in sl; + deserRst : in sl; + deserData : in slv(7 downto 0); + dlyLoad : out sl; + dlyCfg : out slv(8 downto 0); + -- Config/Status Interface (deserClk domain) + enUsrDlyCfg : in sl; + usrDlyCfg : in slv(8 downto 0); + minEyeWidth : in slv(7 downto 0); + lockingCntCfg : in slv(23 downto 0); + bypFirstBerDet : in sl; + polarity : in sl; + bitOrder : in slv(1 downto 0); + errorDet : out sl; + bitSlip : out sl; + eyeWidth : out slv(8 downto 0); + locked : out sl; + -- PGP Streaming Outputs (deserClk domain) + pgpRxMaster : out AxiStreamMasterType; + -- AXI-Lite Interface (axilClk domain) + axilClk : in sl; + axilRst : in sl; + axilReadMaster : in AxiLiteReadMasterType; + axilReadSlave : out AxiLiteReadSlaveType; + axilWriteMaster : in AxiLiteWriteMasterType; + axilWriteSlave : out AxiLiteWriteSlaveType); +end Pgp4RxLiteLowSpeedLane; + +architecture mapping of Pgp4RxLiteLowSpeedLane is + + signal deserDataMask : slv(7 downto 0) := (others => '0'); + + signal deserReset : sl := '1'; + signal gearboxAligned : sl := '0'; + signal slip : sl := '0'; + + signal phyRxValid : sl := '0'; + signal phyRxData : slv(65 downto 0); + + signal phyRxValidMask : sl := '0'; + +begin + + process(deserClk) + begin + if rising_edge(deserClk) then + bitSlip <= slip after TPD_G; + locked <= gearboxAligned after TPD_G; + end if; + end process; + + U_reset : entity surf.RstPipeline + generic map ( + TPD_G => TPD_G) + port map ( + clk => deserClk, + rstIn => deserRst, + rstOut => deserReset); + + deserDataMask <= deserData when(polarity = '0') else not(deserData); + + --------------- + -- 8:66 Gearbox + --------------- + U_Gearbox : entity surf.Gearbox + generic map ( + TPD_G => TPD_G, + SLAVE_WIDTH_G => 8, + MASTER_WIDTH_G => 66) + port map ( + clk => deserClk, + rst => deserReset, + slip => slip, + -- Slave Interface + slaveValid => '1', + slaveData => deserDataMask, + slaveBitOrder => bitOrder(0), + -- Master Interface + masterValid => phyRxValid, + masterData => phyRxData, + masterReady => '1', + masterBitOrder => bitOrder(1)); + + ------------------ + -- Gearbox Aligner + ------------------ + U_GearboxAligner : entity surf.SelectIoRxGearboxAligner + generic map ( + TPD_G => TPD_G, + SIMULATION_G => SIMULATION_G, + DLY_STEP_SIZE_G => DLY_STEP_SIZE_G, + CODE_TYPE_G => "SCRAMBLER") + port map ( + -- Clock and Reset + clk => deserClk, + rst => deserReset, + -- Line-Code Interface (CODE_TYPE_G = "LINE_CODE") + lineCodeValid => '0', + lineCodeErr => '0', + lineCodeDispErr => '0', + linkOutOfSync => '0', + -- 64b/66b Interface (CODE_TYPE_G = "SCRAMBLER") + rxHeaderValid => phyRxValid, + rxHeader => phyRxData(65 downto 64), + -- Link Status and Gearbox Slip + bitSlip => slip, + -- IDELAY (DELAY_TYPE="VAR_LOAD") Interface + dlyLoad => dlyLoad, + dlyCfg => dlyCfg, + -- Configuration Interface + enUsrDlyCfg => enUsrDlyCfg, + usrDlyCfg => usrDlyCfg, + bypFirstBerDet => bypFirstBerDet, + minEyeWidth => minEyeWidth, + lockingCntCfg => lockingCntCfg, + -- Status Interface + errorDet => errorDet, + eyeWidth => eyeWidth, + locked => gearboxAligned); + + -- Mask off the Valid until the gearbox is locked + phyRxValidMask <= phyRxValid and gearboxAligned; + + ------------------ + -- PGPv4 Core Lite + ------------------ + U_Pgp4CoreLite : entity surf.Pgp4CoreLite + generic map ( + TPD_G => TPD_G, + NUM_VC_G => 1, -- Only 1 VC per PGPv4 Lite link + PGP_RX_ENABLE_G => true, -- Enable the RX path + PGP_TX_ENABLE_G => false, -- Disable the unused TX path + SKIP_EN_G => false, -- No skips (assumes clock source synchronous system) + FLOW_CTRL_EN_G => false, -- No flow control + EN_PGP_MON_G => true, -- Enable the AXI-Lite interface + WRITE_EN_G => true, + STATUS_CNT_WIDTH_G => STATUS_CNT_WIDTH_G, + ERROR_CNT_WIDTH_G => ERROR_CNT_WIDTH_G, + AXIL_CLK_FREQ_G => AXIL_CLK_FREQ_G) + port map ( + -- Tx User interface + pgpTxClk => deserClk, + pgpTxRst => deserReset, + pgpTxActive => '0', + pgpTxMasters => (others => AXI_STREAM_MASTER_INIT_C), + -- Tx PHY interface + phyTxActive => '0', + phyTxReady => '0', + -- Rx User interface + pgpRxClk => deserClk, + pgpRxRst => deserReset, + pgpRxMasters(0) => pgpRxMaster, + pgpRxCtrl(0) => AXI_STREAM_CTRL_UNUSED_C, + -- Rx PHY interface + phyRxClk => deserClk, + phyRxRst => deserReset, + phyRxActive => gearboxAligned, + phyRxStartSeq => '0', + phyRxValid => phyRxValidMask, + phyRxData => phyRxData(63 downto 0), + phyRxHeader => phyRxData(65 downto 64), + -- AXI-Lite Register Interface (axilClk domain) + axilClk => axilClk, + axilRst => axilRst, + axilReadMaster => axilReadMaster, + axilReadSlave => axilReadSlave, + axilWriteMaster => axilWriteMaster, + axilWriteSlave => axilWriteSlave); + +end mapping; diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeedReg.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeedReg.vhd new file mode 100644 index 0000000000..fc21864c7c --- /dev/null +++ b/protocols/pgp/pgp4/core/rtl/Pgp4RxLiteLowSpeedReg.vhd @@ -0,0 +1,223 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: Pgp4RxLite Low Speed Lane Registers +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiLitePkg.all; + +entity Pgp4RxLiteLowSpeedReg is + generic ( + TPD_G : time := 1 ns; + SIMULATION_G : boolean := false; + STATUS_CNT_WIDTH_G : natural range 1 to 32 := 16; + NUM_LANE_G : positive := 1); + port ( + -- Deserialization Interface (deserClk domain) + deserClk : in sl; + deserRst : in sl; + dlyConfig : in Slv9Array(NUM_LANE_G-1 downto 0); + errorDet : in slv(NUM_LANE_G-1 downto 0); + bitSlip : in slv(NUM_LANE_G-1 downto 0); + eyeWidth : in Slv9Array(NUM_LANE_G-1 downto 0); + locked : in slv(NUM_LANE_G-1 downto 0); + enUsrDlyCfg : out sl; + usrDlyCfg : out Slv9Array(NUM_LANE_G-1 downto 0); + minEyeWidth : out slv(7 downto 0); + lockingCntCfg : out slv(23 downto 0); + bypFirstBerDet : out sl; + polarity : out slv(NUM_LANE_G-1 downto 0); + bitOrder : out slv(1 downto 0); + -- AXI-Lite Interface (axilClk domain) + axilClk : in sl; + axilRst : in sl; + axilReadMaster : in AxiLiteReadMasterType; + axilReadSlave : out AxiLiteReadSlaveType; + axilWriteMaster : in AxiLiteWriteMasterType; + axilWriteSlave : out AxiLiteWriteSlaveType); +end Pgp4RxLiteLowSpeedReg; + +architecture mapping of Pgp4RxLiteLowSpeedReg is + + constant STATUS_SIZE_C : positive := 3*NUM_LANE_G; + + type RegType is record + enUsrDlyCfg : sl; + usrDlyCfg : Slv9Array(NUM_LANE_G-1 downto 0); + minEyeWidth : slv(7 downto 0); + lockingCntCfg : slv(23 downto 0); + bypFirstBerDet : sl; + polarity : slv(NUM_LANE_G-1 downto 0); + bitOrder : slv(1 downto 0); + cntRst : sl; + rollOverEn : slv(STATUS_SIZE_C-1 downto 0); + readSlave : AxiLiteReadSlaveType; + writeSlave : AxiLiteWriteSlaveType; + end record; + + constant REG_INIT_C : RegType := ( + enUsrDlyCfg => ite(SIMULATION_G, '1', '0'), + usrDlyCfg => (others => toSlv(219, 9)), + minEyeWidth => toSlv(80, 8), + lockingCntCfg => ite(SIMULATION_G, x"00_0004", x"00_FFFF"), + bypFirstBerDet => '1', + polarity => (others => '0'), + bitOrder => (others => '0'), + cntRst => '1', + rollOverEn => (others => '0'), + readSlave => AXI_LITE_READ_SLAVE_INIT_C, + writeSlave => AXI_LITE_WRITE_SLAVE_INIT_C); + + signal r : RegType := REG_INIT_C; + signal rin : RegType; + + signal statusIn : slv(STATUS_SIZE_C-1 downto 0); + signal statusOut : slv(STATUS_SIZE_C-1 downto 0); + signal statusCnt : SlVectorArray(STATUS_SIZE_C-1 downto 0, STATUS_CNT_WIDTH_G-1 downto 0); + + signal readMaster : AxiLiteReadMasterType; + signal readSlave : AxiLiteReadSlaveType; + signal writeMaster : AxiLiteWriteMasterType; + signal writeSlave : AxiLiteWriteSlaveType; + +begin + + U_AxiLiteAsync : entity surf.AxiLiteAsync + generic map ( + TPD_G => TPD_G, + NUM_ADDR_BITS_G => 12) + port map ( + -- Slave Interface + sAxiClk => axilClk, + sAxiClkRst => axilRst, + sAxiReadMaster => axilReadMaster, + sAxiReadSlave => axilReadSlave, + sAxiWriteMaster => axilWriteMaster, + sAxiWriteSlave => axilWriteSlave, + -- Master Interface + mAxiClk => deserClk, + mAxiClkRst => deserRst, + mAxiReadMaster => readMaster, + mAxiReadSlave => readSlave, + mAxiWriteMaster => writeMaster, + mAxiWriteSlave => writeSlave); + + comb : process (deserRst, dlyConfig, eyeWidth, r, readMaster, statusCnt, + statusOut, writeMaster) is + variable v : RegType; + variable axilEp : AxiLiteEndPointType; + begin + -- Latch the current value + v := r; + + -- Reset the strobes + v.cntRst := '0'; + + -- Determine the transaction type + axiSlaveWaitTxn(axilEp, writeMaster, readMaster, v.writeSlave, v.readSlave); + + -- Map the read registers + for i in STATUS_SIZE_C-1 downto 0 loop + axiSlaveRegisterR(axilEp, toSlv((4*i), 12), 0, muxSlVectorArray(statusCnt, i)); + end loop; + axiSlaveRegisterR(axilEp, x"400", 0, statusOut); + + for i in NUM_LANE_G-1 downto 0 loop + + -- Address starts at 0x200 + axiSlaveRegisterR(axilEp, toSlv(512+4*i, 12), 0, eyeWidth(i)); + + -- Address starts at 0x500 + axiSlaveRegister (axilEp, toSlv(1280+4*i, 12), 0, v.usrDlyCfg(i)); + + -- Address starts at 0x600 + axiSlaveRegisterR(axilEp, toSlv(1536+4*i, 12), 0, dlyConfig(i)); + + end loop; + + axiSlaveRegisterR(axilEp, x"7FC", 8, toSlv(NUM_LANE_G, 8)); + + axiSlaveRegister (axilEp, x"800", 0, v.enUsrDlyCfg); + -- axiSlaveRegister (axilEp, x"804", 0, v.usrDlyCfg); -- Changed from "common" to 1 per lane + axiSlaveRegister (axilEp, x"808", 0, v.minEyeWidth); + axiSlaveRegister (axilEp, x"80C", 0, v.lockingCntCfg); + + axiSlaveRegister (axilEp, x"810", 0, v.bypFirstBerDet); + axiSlaveRegister (axilEp, x"814", 0, v.polarity); + axiSlaveRegister (axilEp, x"818", 0, v.bitOrder); + + axiSlaveRegister (axilEp, x"FF8", 0, v.rollOverEn); + axiSlaveRegister (axilEp, x"FFC", 0, v.cntRst); + + -- Closeout the transaction + axiSlaveDefault(axilEp, v.writeSlave, v.readSlave, AXI_RESP_DECERR_C); + + -- Outputs + writeSlave <= r.writeSlave; + readSlave <= r.readSlave; + enUsrDlyCfg <= r.enUsrDlyCfg; + usrDlyCfg <= r.usrDlyCfg; + minEyeWidth <= r.minEyeWidth; + lockingCntCfg <= r.lockingCntCfg; + bypFirstBerDet <= r.bypFirstBerDet; + polarity <= r.polarity; + bitOrder <= r.bitOrder; + + -- Synchronous Reset + if (deserRst = '1') then + v := REG_INIT_C; + end if; + + -- Register the variable for next clock cycle + rin <= v; + + end process comb; + + seq : process (deserClk) is + begin + if (rising_edge(deserClk)) then + r <= rin after TPD_G; + end if; + end process seq; + + U_SyncStatusVector : entity surf.SyncStatusVector + generic map ( + TPD_G => TPD_G, + COMMON_CLK_G => true, + OUT_POLARITY_G => '1', + CNT_RST_EDGE_G => false, + CNT_WIDTH_G => STATUS_CNT_WIDTH_G, + WIDTH_G => STATUS_SIZE_C) + port map ( + -- Input Status bit Signals (wrClk domain) + statusIn => statusIn, + -- Output Status bit Signals (rdClk domain) + statusOut => statusOut, + -- Status Bit Counters Signals (rdClk domain) + cntRstIn => r.cntRst, + rollOverEnIn => r.rollOverEn, + cntOut => statusCnt, + -- Clocks and Reset Ports + wrClk => deserClk, + rdClk => deserClk); + + statusIn((2*NUM_LANE_G)+NUM_LANE_G-1 downto 2*NUM_LANE_G) <= errorDet; + statusIn((1*NUM_LANE_G)+NUM_LANE_G-1 downto 1*NUM_LANE_G) <= bitSlip; + statusIn((0*NUM_LANE_G)+NUM_LANE_G-1 downto 0*NUM_LANE_G) <= locked; + +end mapping; diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4RxProtocol.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4RxProtocol.vhd index c0f7164bba..6aacdcaf92 100644 --- a/protocols/pgp/pgp4/core/rtl/Pgp4RxProtocol.vhd +++ b/protocols/pgp/pgp4/core/rtl/Pgp4RxProtocol.vhd @@ -31,9 +31,10 @@ use surf.Pgp4Pkg.all; entity Pgp4RxProtocol is generic ( - TPD_G : time := 1 ns; - RST_ASYNC_G : boolean := false; - NUM_VC_G : integer range 1 to 16 := 4); + TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset + RST_ASYNC_G : boolean := false; + NUM_VC_G : integer range 1 to 16 := 4); port ( -- User Transmit interface pgpRxClk : in sl; @@ -90,8 +91,9 @@ begin U_phyRxActiveSync : entity surf.SynchronizerEdge generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G) port map ( clk => pgpRxClk, rst => pgpRxRst, @@ -278,7 +280,7 @@ begin locRxLinkReady <= r.pgpRxOut.linkReady; -- Reset - if (RST_ASYNC_G = false and pgpRxRst = '1') then + if (RST_ASYNC_G = false and pgpRxRst = RST_POLARITY_G) then v := REG_INIT_C; end if; @@ -289,7 +291,7 @@ begin seq : process (pgpRxClk, pgpRxRst) is begin - if (RST_ASYNC_G) and (pgpRxRst = '1') then + if (RST_ASYNC_G) and (pgpRxRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif rising_edge(pgpRxClk) then r <= rin after TPD_G; diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4TxLite.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4TxLite.vhd index 0a3a179ffe..8cafbe26c1 100644 --- a/protocols/pgp/pgp4/core/rtl/Pgp4TxLite.vhd +++ b/protocols/pgp/pgp4/core/rtl/Pgp4TxLite.vhd @@ -28,6 +28,7 @@ use surf.Pgp4Pkg.all; entity Pgp4TxLite is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; NUM_VC_G : integer range 1 to 16 := 1; SKIP_EN_G : boolean := false; @@ -82,8 +83,9 @@ begin -- Synchronize remote link and FIFO status to tx clock U_Synchronizer_REM : entity surf.Synchronizer generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G) port map ( clk => pgpTxClk, -- [in] rst => pgpTxRst, -- [in] @@ -92,9 +94,10 @@ begin REM_STATUS_SYNC : for i in NUM_VC_G-1 downto 0 generate U_SynchronizerVector_1 : entity surf.SynchronizerVector generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G, - WIDTH_G => 2) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G, + WIDTH_G => 2) port map ( clk => pgpTxClk, -- [in] rst => pgpTxRst, -- [in] @@ -107,8 +110,9 @@ begin -- Synchronize local rx status U_Synchronizer_LOC : entity surf.Synchronizer generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G) port map ( clk => pgpTxClk, -- [in] rst => pgpTxRst, -- [in] @@ -117,8 +121,9 @@ begin LOC_STATUS_SYNC : for i in NUM_VC_G-1 downto 0 generate U_Synchronizer_pause : entity surf.Synchronizer generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G) port map ( clk => pgpTxClk, -- [in] rst => pgpTxRst, -- [in] @@ -126,8 +131,9 @@ begin dataOut => syncLocRxFifoCtrl(i).pause); -- [out] U_Synchronizer_overflow : entity surf.SynchronizerOneShot generic map ( - TPD_G => TPD_G, - RST_ASYNC_G => RST_ASYNC_G) + TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, + RST_ASYNC_G => RST_ASYNC_G) port map ( clk => pgpTxClk, -- [in] rst => pgpTxRst, -- [in] @@ -158,6 +164,7 @@ begin U_AxiStreamMux_1 : entity surf.AxiStreamMux generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, NUM_SLAVES_G => NUM_VC_G, MODE_G => "INDEXED", @@ -189,6 +196,7 @@ begin U_Protocol : entity surf.Pgp4TxLiteProtocol generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, NUM_VC_G => NUM_VC_G, SKIP_EN_G => SKIP_EN_G, @@ -216,6 +224,7 @@ begin U_Scrambler_1 : entity surf.Scrambler generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, DIRECTION_G => "SCRAMBLER", DATA_WIDTH_G => 64, @@ -237,6 +246,7 @@ begin outputSideband(1 downto 0) => phyTxHeader, -- [out] outputSideband(2) => phyTxStart); -- [out] - phyTxActiveL <= not(phyTxActive); + -- not using ite to prevent errors in ASIC synth flow + phyTxActiveL <= not(phyTxActive) when RST_POLARITY_G = '1' else phyTxActive; end architecture rtl; diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4TxLiteProtocol.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4TxLiteProtocol.vhd index 0f28e10d17..7b9aac70d2 100644 --- a/protocols/pgp/pgp4/core/rtl/Pgp4TxLiteProtocol.vhd +++ b/protocols/pgp/pgp4/core/rtl/Pgp4TxLiteProtocol.vhd @@ -32,6 +32,7 @@ use surf.Pgp4Pkg.all; entity Pgp4TxLiteProtocol is generic ( TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset RST_ASYNC_G : boolean := false; NUM_VC_G : integer range 1 to 16 := 1; SKIP_EN_G : boolean := false; @@ -127,6 +128,7 @@ begin U_Crc32 : entity surf.Crc32Parallel generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, INPUT_REGISTER_G => false, BYTE_WIDTH_G => 8, @@ -453,7 +455,7 @@ begin end loop; -- Reset - if (RST_ASYNC_G = false and pgpTxRst = '1') then + if (RST_ASYNC_G = false and pgpTxRst = RST_POLARITY_G) then v := REG_INIT_C; end if; @@ -464,7 +466,7 @@ begin seq : process (pgpTxClk, pgpTxRst) is begin - if (RST_ASYNC_G) and (pgpTxRst = '1') then + if (RST_ASYNC_G) and (pgpTxRst = RST_POLARITY_G) then r <= REG_INIT_C after TPD_G; elsif rising_edge(pgpTxClk) then r <= rin after TPD_G; diff --git a/protocols/pgp/pgp4/core/rtl/Pgp4TxLiteWrapper.vhd b/protocols/pgp/pgp4/core/rtl/Pgp4TxLiteWrapper.vhd index 2eb515de10..c51528b645 100644 --- a/protocols/pgp/pgp4/core/rtl/Pgp4TxLiteWrapper.vhd +++ b/protocols/pgp/pgp4/core/rtl/Pgp4TxLiteWrapper.vhd @@ -24,12 +24,13 @@ use surf.Pgp4Pkg.all; entity Pgp4TxLiteWrapper is generic ( - TPD_G : time := 1 ns; - RST_ASYNC_G : boolean := false); + TPD_G : time := 1 ns; + RST_POLARITY_G : sl := '1'; -- '1' for active HIGH reset, '0' for active LOW reset + RST_ASYNC_G : boolean := false); port ( -- Clock and Reset clk : in sl; - rst : in sl; -- Active HIGH reset + rst : in sl; -- 64-bit Input Framing Interface txValid : in sl; -- tValid txReady : out sl; -- tReady @@ -71,8 +72,9 @@ begin U_Pgp4TxLite : entity surf.Pgp4TxLite generic map ( TPD_G => TPD_G, + RST_POLARITY_G => RST_POLARITY_G, RST_ASYNC_G => RST_ASYNC_G, - NUM_VC_G => 1, -- Only 1 VC per PGPv4 link + NUM_VC_G => 1, -- Only 1 VC per PGPv4 link SKIP_EN_G => false, -- No skips (assumes clock source synchronous system) FLOW_CTRL_EN_G => false) -- no pause flow control from PGPv4.RX side port map ( @@ -97,6 +99,7 @@ begin phyTxData => phyTxData(63 downto 0), phyTxHeader => phyTxData(65 downto 64)); - rstL <= not(rst); + -- not using ite to prevent errors in ASIC synth flow + rstL <= not(rst) when RST_POLARITY_G = '1' else rst; end architecture mapping; diff --git a/protocols/saci/rtl/AxiLiteSaciMaster.vhd b/protocols/saci/rtl/AxiLiteSaciMaster.vhd index 139add9c56..50025de5e1 100644 --- a/protocols/saci/rtl/AxiLiteSaciMaster.vhd +++ b/protocols/saci/rtl/AxiLiteSaciMaster.vhd @@ -27,13 +27,13 @@ use surf.SaciMasterPkg.all; entity AxiLiteSaciMaster is generic ( - TPD_G : time := 1 ns; - AXIL_CLK_PERIOD_G : real := 8.0e-9; -- In units of seconds - AXIL_TIMEOUT_G : real := 1.0E-3; -- In units of seconds - SACI_CLK_PERIOD_G : real := 1.0e-6; -- In units of seconds - SACI_CLK_FREERUN_G : boolean := false; - SACI_NUM_CHIPS_G : positive range 1 to 4 := 1; - SACI_RSP_BUSSED_G : boolean := false); + TPD_G : time := 1 ns; + AXIL_CLK_PERIOD_G : real := 8.0e-9; -- In units of seconds + AXIL_TIMEOUT_G : real := 1.0E-3; -- In units of seconds + SACI_CLK_PERIOD_G : real := 1.0e-6; -- In units of seconds + SACI_CLK_FREERUN_G : boolean := false; + SACI_NUM_CHIPS_G : positive := 1; + SACI_RSP_BUSSED_G : boolean := false); port ( -- SACI interface saciClk : out sl; @@ -43,6 +43,8 @@ entity AxiLiteSaciMaster is -- Optional SACI bus arbitration saciBusReq : out sl; saciBusGr : in sl := '1'; + -- Optional ASIC Global Reset + asicRstL : in sl := '1'; -- AXI-Lite Register Interface axilClk : in sl; axilRst : in sl; @@ -128,6 +130,7 @@ begin port map ( sysClk => axilClk, -- [in] sysRst => r.saciRst, -- [in] + asicRstL => asicRstL, -- [in] req => r.req, -- [in] ack => ack, -- [out] fail => fail, -- [out] @@ -142,7 +145,7 @@ begin saciCmd => saciCmd, -- [out] saciRsp => saciRsp); -- [in] - comb : process (ack, axilReadMaster, axilRst, axilWriteMaster, fail, r, rdData, saciBusGr) is + comb : process (ack, asicRstL, axilReadMaster, axilRst, axilWriteMaster, fail, r, rdData, saciBusGr) is variable v : RegType; variable axilStatus : AxiLiteStatusType; variable resp : slv(1 downto 0); @@ -170,7 +173,7 @@ begin v.saciRst := '0'; v.timer := 0; v.saciBusReq := '0'; - if (saciBusGr = '1') then + if (saciBusGr = '1') and (asicRstL = '1') then -- Check for a write request if (axilStatus.writeEnable = '1') then v.saciBusReq := '1'; diff --git a/protocols/saci/rtl/SaciAxiLiteMaster.vhd b/protocols/saci/rtl/SaciAxiLiteMaster.vhd new file mode 100644 index 0000000000..a0893d8688 --- /dev/null +++ b/protocols/saci/rtl/SaciAxiLiteMaster.vhd @@ -0,0 +1,163 @@ +------------------------------------------------------------------------------- +-- Title : SACI Protocol: https://confluence.slac.stanford.edu/x/YYcRDQ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: AXI-Lite master bridge for SACI bus slave +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.std_logic_arith.all; + + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiLitePkg.all; +use surf.SaciMasterPkg.all; + +entity SaciAxiLiteMaster is + generic ( + TPD_G : time := 1 ns); + port ( + -- Global Reset + rstL : in sl; + -- SACI Slave interface + saciClk : in sl; + saciCmd : in sl; + saciSelL : in sl; + saciRsp : out sl; + -- AXI-Lite Register Interface + axilClk : in sl; + axilRst : in sl; + axilReadMaster : out AxiLiteReadMasterType; + axilReadSlave : in AxiLiteReadSlaveType; + axilWriteMaster : out AxiLiteWriteMasterType; + axilWriteSlave : in AxiLiteWriteSlaveType); +end SaciAxiLiteMaster; + +architecture rtl of SaciAxiLiteMaster is + + -- AXI-Lite Master Interface + signal axilReq : AxiLiteReqType; + signal axilAck : AxiLiteAckType; + + -- SACI resets + signal rstOutL : sl; + signal rstInL : sl; + + + -- SACI Slave parallel interface + signal exec : sl; + signal ack : sl; + signal readL : sl; + signal cmd : slv(6 downto 0); + signal addr : slv(11 downto 0); + signal wrData : slv(31 downto 0); + signal rdData : slv(31 downto 0); + + + -- attribute dont_touch : string; + -- attribute dont_touch of r : signal is "true"; + +begin + + rstInL <= rstOutL; + + U_SaciSlave_1 : entity surf.SaciSlave + generic map ( + TPD_G => TPD_G) + port map ( + rstL => rstL, -- [in] + saciClk => saciClk, -- [in] + saciSelL => saciSelL, -- [in] + saciCmd => saciCmd, -- [in] + saciRsp => saciRsp, -- [out] + rstOutL => rstOutL, -- [out] + rstInL => rstInL, -- [in] + exec => exec, -- [out] + ack => ack, -- [in] + readL => readL, -- [out] + cmd => cmd, -- [out] + addr => addr, -- [out] + wrData => wrData, -- [out] + rdData => rdData); -- [in] + + ------------------------------------------------------ + -- Synchronize exec to axilReq.request + ------------------------------------------------------ + U_Synchronizer_1 : entity surf.Synchronizer + generic map ( + TPD_G => TPD_G, + RST_POLARITY_G => '1', + OUT_POLARITY_G => '1', + RST_ASYNC_G => true, + STAGES_G => 2, + BYPASS_SYNC_G => false, + INIT_G => "0") + port map ( + clk => axilClk, -- [in] + rst => axilRst, -- [in] + dataIn => exec, -- [in] + dataOut => axilReq.request); -- [out] + + ------------------------------------------------------ + -- These should have settled to be sampled by axilClk + -- By the time exec gets synced to axilReq + ------------------------------------------------------ + axilReq.rnw <= not readL; + axilReq.address(1 downto 0) <= "00"; + axilReq.address(13 downto 2) <= addr; + axilReq.address(20 downto 14) <= cmd; + axilReq.address(31 downto 21) <= (others => '0'); + axilReq.wrData <= wrData; + + ------------------------------------------------------ + -- Synchronize axilAck.done to saciClk + ------------------------------------------------------ + U_Synchronizer_2 : entity surf.Synchronizer + generic map ( + TPD_G => TPD_G, + RST_POLARITY_G => '1', + OUT_POLARITY_G => '1', + RST_ASYNC_G => true, + STAGES_G => 2, + BYPASS_SYNC_G => false, + INIT_G => "0") + port map ( + clk => saciClk, -- [in] + rst => '0', -- [in] + dataIn => axilAck.done, -- [in] + dataOut => ack); -- [out] + + ------------------------------------------------------ + -- This should have settled to be sampled by saciClk + -- By the time axilAck.done gets synced to ack + ------------------------------------------------------ + rdData <= axilAck.rdData; + + U_AxiLiteMaster_1 : entity surf.AxiLiteMaster + generic map ( + TPD_G => TPD_G, + RST_ASYNC_G => true) + port map ( + axilClk => axilClk, -- [in] + axilRst => axilRst, -- [in] + req => axilReq, -- [in] + ack => axilAck, -- [out] + axilWriteMaster => axilWriteMaster, -- [out] + axilWriteSlave => axilWriteSlave, -- [in] + axilReadMaster => axilReadMaster, -- [out] + axilReadSlave => axilReadSlave); -- [in] + + +end rtl; diff --git a/protocols/saci/rtl/SaciMaster2.vhd b/protocols/saci/rtl/SaciMaster2.vhd index 684a827235..e2d1307edb 100644 --- a/protocols/saci/rtl/SaciMaster2.vhd +++ b/protocols/saci/rtl/SaciMaster2.vhd @@ -19,7 +19,6 @@ use IEEE.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; - library surf; use surf.StdRtlPkg.all; @@ -33,9 +32,13 @@ entity SaciMaster2 is SACI_NUM_CHIPS_G : positive := 1; SACI_RSP_BUSSED_G : boolean := false); port ( - sysClk : in sl; -- Main clock + -- Clock and Reset + sysClk : in sl; sysRst : in sl; + -- Optional ASIC Global Reset + asicRstL : in sl := '1'; + -- Request interface req : in sl; ack : out sl; @@ -67,6 +70,7 @@ architecture rtl of SaciMaster2 is state : StateType; shiftReg : slv(52 downto 0); shiftCount : slv(5 downto 0); + asicRstL : slv(31 downto 0); --Saci clk gen clkCount : slv(SACI_CLK_COUNTER_SIZE_C downto 0); @@ -88,6 +92,7 @@ architecture rtl of SaciMaster2 is state => IDLE_S, shiftReg => (others => '0'), shiftCount => (others => '0'), + asicRstL => (others => '1'), clkCount => (others => '0'), saciClkRising => '0', saciClkFalling => '0', @@ -105,6 +110,8 @@ architecture rtl of SaciMaster2 is begin + assert (SACI_CLK_HALF_PERIOD_C >= 2) report "SACI_CLK_PERIOD_G is too fast for SYS_CLK_PERIOD_G" severity failure; + ------------------------------------------------------------------------------------------------- -- Synchronize saciRsp to sysClk ------------------------------------------------------------------------------------------------- @@ -122,7 +129,7 @@ begin ------------------------------------------------------------------------------------------------- -- Main logic ------------------------------------------------------------------------------------------------- - comb : process (addr, chip, cmd, op, r, req, saciRspSync, sysRst, wrData) is + comb : process (addr, asicRstL, chip, cmd, op, r, req, saciRspSync, sysRst, wrData) is variable v : RegType; variable rspIndex : integer; begin @@ -137,6 +144,7 @@ begin if (r.clkCount = SACI_CLK_HALF_PERIOD_C) then v.saciClk := not r.saciClk; v.clkCount := (others => '0'); + v.asicRstL := r.asicRstL(30 downto 0) & '1'; end if; -- Create saciClk edge strobes @@ -151,15 +159,20 @@ begin end if; end if; + -- Check for ASIC reset condition + if (asicRstL = '0') then + -- Reset the bus + v.asicRstL := (others => '0'); + end if; + case (r.state) is when IDLE_S => v.fail := '0'; v.shiftReg := (others => '0'); v.shiftCount := (others => '0'); v.saciSelL := (others => '1'); - -- Hold clock inactive while idle - -- Make this configurable? - if (not SACI_CLK_FREERUN_G) then + -- Hold clock inactive while idle else there is a ASIC reset + if (not SACI_CLK_FREERUN_G) and (r.asicRstL(31)='1') then v.saciClk := '0'; v.clkCount := (others => '0'); end if; diff --git a/protocols/saci/sim/SaciAxiLiteMasterTb.vhd b/protocols/saci/sim/SaciAxiLiteMasterTb.vhd new file mode 100644 index 0000000000..124e240027 --- /dev/null +++ b/protocols/saci/sim/SaciAxiLiteMasterTb.vhd @@ -0,0 +1,183 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: surf.AxiLiteCrossbar cocoTB testbed +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiLitePkg.all; + +entity SaciAxiLiteMasterTb is + port ( + -- AXI-Lite Interface + S_AXI_ACLK : in std_logic; + S_AXI_ARESETN : in std_logic; + S_AXI_AWADDR : in std_logic_vector(31 downto 0); + S_AXI_AWPROT : in std_logic_vector(2 downto 0); + S_AXI_AWVALID : in std_logic; + S_AXI_AWREADY : out std_logic; + S_AXI_WDATA : in std_logic_vector(31 downto 0); + S_AXI_WSTRB : in std_logic_vector(3 downto 0); + S_AXI_WVALID : in std_logic; + S_AXI_WREADY : out std_logic; + S_AXI_BRESP : out std_logic_vector(1 downto 0); + S_AXI_BVALID : out std_logic; + S_AXI_BREADY : in std_logic; + S_AXI_ARADDR : in std_logic_vector(31 downto 0); + S_AXI_ARPROT : in std_logic_vector(2 downto 0); + S_AXI_ARVALID : in std_logic; + S_AXI_ARREADY : out std_logic; + S_AXI_RDATA : out std_logic_vector(31 downto 0); + S_AXI_RRESP : out std_logic_vector(1 downto 0); + S_AXI_RVALID : out std_logic; + S_AXI_RREADY : in std_logic); +end SaciAxiLiteMasterTb; + +architecture mapping of SaciAxiLiteMasterTb is + + signal fpgaAxilClk : sl; + signal fpgaAxilRst : sl; + + signal fpgaAxilReadMaster : AxiLiteReadMasterType; + signal fpgaAxilReadSlave : AxiLiteReadSlaveType; + signal fpgaAxilWriteMaster : AxiLiteWriteMasterType; + signal fpgaAxilWriteSlave : AxiLiteWriteSlaveType; + + signal asicAxilClk : sl; + signal asicAxilRst : sl; + + signal asicAxilReadMaster : AxiLiteReadMasterType; + signal asicAxilReadSlave : AxiLiteReadSlaveType; + signal asicAxilWriteMaster : AxiLiteWriteMasterType; + signal asicAxilWriteSlave : AxiLiteWriteSlaveType; + + signal rstL : sl; + + signal saciClk : sl; + signal saciCmd : sl; + signal saciSelL : slv(0 downto 0); + signal saciRsp : slv(0 downto 0); + signal saciBusReq : sl; + signal saciBusGr : sl := '1'; + +begin + + U_ShimLayer : entity surf.SlaveAxiLiteIpIntegrator + generic map ( + EN_ERROR_RESP => true, + FREQ_HZ => 125000000, + ADDR_WIDTH => 32) + port map ( + -- IP Integrator AXI-Lite Interface + S_AXI_ACLK => S_AXI_ACLK, + S_AXI_ARESETN => S_AXI_ARESETN, + S_AXI_AWADDR => S_AXI_AWADDR, + S_AXI_AWPROT => S_AXI_AWPROT, + S_AXI_AWVALID => S_AXI_AWVALID, + S_AXI_AWREADY => S_AXI_AWREADY, + S_AXI_WDATA => S_AXI_WDATA, + S_AXI_WSTRB => S_AXI_WSTRB, + S_AXI_WVALID => S_AXI_WVALID, + S_AXI_WREADY => S_AXI_WREADY, + S_AXI_BRESP => S_AXI_BRESP, + S_AXI_BVALID => S_AXI_BVALID, + S_AXI_BREADY => S_AXI_BREADY, + S_AXI_ARADDR => S_AXI_ARADDR, + S_AXI_ARPROT => S_AXI_ARPROT, + S_AXI_ARVALID => S_AXI_ARVALID, + S_AXI_ARREADY => S_AXI_ARREADY, + S_AXI_RDATA => S_AXI_RDATA, + S_AXI_RRESP => S_AXI_RRESP, + S_AXI_RVALID => S_AXI_RVALID, + S_AXI_RREADY => S_AXI_RREADY, + -- SURF AXI-Lite Interface + axilClk => fpgaAxilClk, + axilRst => fpgaAxilRst, + axilReadMaster => fpgaAxilReadMaster, + axilReadSlave => fpgaAxilReadSlave, + axilWriteMaster => fpgaAxilWriteMaster, + axilWriteSlave => fpgaAxilWriteSlave); + + ------------------------------------------------------------------------------------------------- + -- FPGA Side + ------------------------------------------------------------------------------------------------- + U_AxiLiteSaciMaster_1 : entity surf.AxiLiteSaciMaster + generic map ( + TPD_G => 1 ns, + AXIL_CLK_PERIOD_G => 8.0e-9, + AXIL_TIMEOUT_G => 1.0e-3, + SACI_CLK_PERIOD_G => 50.0e-9, + SACI_CLK_FREERUN_G => false, + SACI_NUM_CHIPS_G => 1, + SACI_RSP_BUSSED_G => false) + port map ( + saciClk => saciClk, -- [out] + saciCmd => saciCmd, -- [out] + saciSelL => saciSelL, -- [out] + saciRsp => saciRsp, -- [in] + saciBusReq => saciBusReq, -- [out] + saciBusGr => saciBusGr, -- [in] + axilClk => fpgaAxilClk, -- [in] + axilRst => fpgaAxilRst, -- [in] + axilReadMaster => fpgaAxilReadMaster, -- [in] + axilReadSlave => fpgaAxilReadSlave, -- [out] + axilWriteMaster => fpgaAxilWriteMaster, -- [in] + axilWriteSlave => fpgaAxilWriteSlave); -- [out] + + ------------------------------------------------------------------------------------------------- + -- ASIC side + ------------------------------------------------------------------------------------------------- + U_ClkRst_1 : entity surf.ClkRst + generic map ( + CLK_PERIOD_G => 8.0 ns) + port map ( + clkP => asicAxilClk, -- [out] + rst => asicAxilRst, -- [out] + rstL => rstL); -- [out] + + U_SaciAxiLiteMaster_1 : entity surf.SaciAxiLiteMaster + generic map ( + TPD_G => 1 ns) + port map ( + rstL => rstL, -- [in] + saciClk => saciClk, -- [in] + saciCmd => saciCmd, -- [in] + saciSelL => saciSelL(0), -- [in] + saciRsp => saciRsp(0), -- [out] + axilClk => asicAxilClk, -- [in] + axilRst => asicAxilRst, -- [in] + axilReadMaster => asicAxilReadMaster, -- [in] + axilReadSlave => asicAxilReadSlave, -- [out] + axilWriteMaster => asicAxilWriteMaster, -- [in] + axilWriteSlave => asicAxilWriteSlave); -- [out] + + + U_MEM : entity surf.AxiDualPortRam + generic map ( + ADDR_WIDTH_G => 22, + DATA_WIDTH_G => 32) + port map ( + -- Axi Port + axiClk => asicAxilClk, + axiRst => asicAxilRst, + axiReadMaster => asicAxilReadMaster, + axiReadSlave => asicAxilReadSlave, + axiWriteMaster => asicAxilWriteMaster, + axiWriteSlave => asicAxilWriteSlave); + + +end mapping; diff --git a/protocols/saci/sim/SaciAxiLiteMasterTbWrapper.vhd b/protocols/saci/sim/SaciAxiLiteMasterTbWrapper.vhd new file mode 100644 index 0000000000..0bdce368df --- /dev/null +++ b/protocols/saci/sim/SaciAxiLiteMasterTbWrapper.vhd @@ -0,0 +1,142 @@ +------------------------------------------------------------------------------- +-- Company : SLAC National Accelerator Laboratory +------------------------------------------------------------------------------- +-- Description: surf.AxiLiteCrossbar cocoTB testbed +------------------------------------------------------------------------------- +-- This file is part of 'SLAC Firmware Standard Library'. +-- It is subject to the license terms in the LICENSE.txt file found in the +-- top-level directory of this distribution and at: +-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +-- No part of 'SLAC Firmware Standard Library', including this file, +-- may be copied, modified, propagated, or distributed except according to +-- the terms contained in the LICENSE.txt file. +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +library surf; +use surf.StdRtlPkg.all; +use surf.AxiLitePkg.all; + +entity SaciAxiLiteMasterTbWrapper is +end SaciAxiLiteMasterTbWrapper; + +architecture mapping of SaciAxiLiteMasterTbWrapper is + + signal axilClk : sl; + signal axilRstL : sl; + + signal axilReadMaster : AxiLiteReadMasterType; + signal axilReadSlave : AxiLiteReadSlaveType; + signal axilWriteMaster : AxiLiteWriteMasterType; + signal axilWriteSlave : AxiLiteWriteSlaveType; + + +begin + + U_SaciAxiLiteMasterTb_1 : entity surf.SaciAxiLiteMasterTb + port map ( + S_AXI_ACLK => axilClk, -- [in] + S_AXI_ARESETN => axilRstL, -- [in] + S_AXI_AWADDR => axilWriteMaster.awaddr, -- [in] + S_AXI_AWPROT => axilWriteMaster.awprot, -- [in] + S_AXI_AWVALID => axilWriteMaster.awvalid, -- [in] + S_AXI_AWREADY => axilWriteSlave.awready, -- [out] + S_AXI_WDATA => axilWriteMaster.wdata, -- [in] + S_AXI_WSTRB => axilWriteMaster.wstrb, -- [in] + S_AXI_WVALID => axilWriteMaster.wvalid, -- [in] + S_AXI_WREADY => axilWriteSlave.WREADY, -- [out] + S_AXI_BRESP => axilWriteSlave.BRESP, -- [out] + S_AXI_BVALID => axilWriteSlave.BVALID, -- [out] + S_AXI_BREADY => axilWriteMaster.BREADY, -- [in] + S_AXI_ARADDR => axilReadMaster.ARADDR, -- [in] + S_AXI_ARPROT => axilReadMaster.ARPROT, -- [in] + S_AXI_ARVALID => axilReadMaster.ARVALID, -- [in] + S_AXI_ARREADY => axilReadSlave.ARREADY, -- [out] + S_AXI_RDATA => axilReadSlave.RDATA, -- [out] + S_AXI_RRESP => axilReadSlave.RRESP, -- [out] + S_AXI_RVALID => axilReadSlave.RVALID, -- [out] + S_AXI_RREADY => axilReadMaster.RREADY); -- [in] + + U_ClkRst_2 : entity surf.ClkRst + generic map ( + CLK_PERIOD_G => 8.0 ns, + CLK_DELAY_G => 3.2 ns) + port map ( + clkP => axilClk, -- [out] + rstL => axilRstL); -- [out] + + process is + variable wrData : slv(31 downto 0); + variable rdData : slv(31 downto 0); + begin + wait for 10 us; + wait until axilClk = '1'; + wait until axilClk = '1'; + wait until axilClk = '1'; + + wrData := X"12345678"; + axiLiteBusSimWrite( + axilClk, + axilWriteMaster, + axilWriteSlave, + X"00000000", + wrData); + + axiLiteBusSimRead( + axilClk, + axilReadMaster, + axilReadSlave, + X"00000000", + rdData); + + assert (wrData = rdData) report "Data Mismatch" severity error; + + wrData := X"9abcdef0"; + axiLiteBusSimWrite( + axilClk, + axilWriteMaster, + axilWriteSlave, + X"00000004", + wrData); + + axiLiteBusSimRead( + axilClk, + axilReadMaster, + axilReadSlave, + X"00000004", + rdData); + + assert (wrData = rdData) report "Data Mismatch" severity error; + + + wrData := X"deadbeef"; + axiLiteBusSimWrite( + axilClk, + axilWriteMaster, + axilWriteSlave, + X"00100008", + wrData); + + axiLiteBusSimRead( + axilClk, + axilReadMaster, + axilReadSlave, + X"00100008", + rdData); + + assert (wrData = rdData) report "Data Mismatch" severity error; + + + + wait until axilClk = '1'; + wait; + + end process; + + + +end mapping; diff --git a/protocols/spi/rtl/AxiSpiMaster.vhd b/protocols/spi/rtl/AxiSpiMaster.vhd index 79c85a3f35..2a900f9770 100644 --- a/protocols/spi/rtl/AxiSpiMaster.vhd +++ b/protocols/spi/rtl/AxiSpiMaster.vhd @@ -55,8 +55,8 @@ entity AxiSpiMaster is axiWriteMaster : in AxiLiteWriteMasterType; axiWriteSlave : out AxiLiteWriteSlaveType; -- Copy of the shadow memory (SHADOW_EN_G=true) - shadowAddr : in slv(ADDRESS_SIZE_G-1 downto 0) := (others => '0'); - shadowData : out slv(DATA_SIZE_G-1 downto 0) := (others => '0'); + shadowAddr : in slv(log2(SPI_NUM_CHIPS_G)+ADDRESS_SIZE_G-1 downto 0) := (others => '0'); + shadowData : out slv(DATA_SIZE_G-1 downto 0) := (others => '0'); -- SPI Interface coreSclk : out sl; coreSDin : in sl; @@ -77,7 +77,8 @@ architecture rtl of AxiSpiMaster is type StateType is (WAIT_AXI_TXN_S, WAIT_CYCLE_S, WAIT_CYCLE_SHADOW_S, WAIT_SPI_TXN_DONE_S, SHADOW_READ_DONE_S); - signal memData : slv(DATA_SIZE_G-1 downto 0) := (others => '0'); + signal memData : slv(DATA_SIZE_G-1 downto 0) := (others => '0'); + signal memAddr : slv(ADDRESS_SIZE_G+CHIP_BITS_C-1 downto 0) := (others => '0'); -- Registers type RegType is record @@ -105,26 +106,27 @@ architecture rtl of AxiSpiMaster is begin SHADOW_RAM_GEN : if (SHADOW_EN_G) generate + memAddr <= r.chipSel & r.wrData(DATA_SIZE_G+ADDRESS_SIZE_G-1 downto DATA_SIZE_G); U_DualPortRam_1 : entity surf.DualPortRam generic map ( TPD_G => TPD_G, MEMORY_TYPE_G => SHADOW_MEM_TYPE_G, REG_EN_G => false, DATA_WIDTH_G => DATA_SIZE_G, - ADDR_WIDTH_G => ADDRESS_SIZE_G) + ADDR_WIDTH_G => ADDRESS_SIZE_G+CHIP_BITS_C) port map ( - clka => axiClk, -- [in] - ena => '1', -- [in] - wea => r.wrEn, -- [in] - rsta => axiRst, -- [in] - addra => r.wrData(DATA_SIZE_G+ADDRESS_SIZE_G-1 downto DATA_SIZE_G), -- [in] - dina => r.wrData(DATA_SIZE_G-1 downto 0), -- [in] - douta => memData, -- [out] - clkb => axiClk, -- [in] - enb => '1', -- [in] - rstb => axiRst, -- [in] - addrb => shadowAddr, -- [in] - doutb => shadowData); -- [out] + clka => axiClk, -- [in] + ena => '1', -- [in] + wea => r.wrEn, -- [in] + rsta => axiRst, -- [in] + addra => memAddr, -- [in] + dina => r.wrData(DATA_SIZE_G-1 downto 0), -- [in] + douta => memData, -- [out] + clkb => axiClk, -- [in] + enb => '1', -- [in] + rstb => axiRst, -- [in] + addrb => shadowAddr, -- [in] + doutb => shadowData); -- [out] end generate SHADOW_RAM_GEN; @@ -147,6 +149,7 @@ begin if (ADDRESS_SIZE_G > 0) then v.wrData(DATA_SIZE_G+ADDRESS_SIZE_G-1 downto DATA_SIZE_G) := axiReadMaster.araddr(2+ADDRESS_SIZE_G-1 downto 2); -- setup memAddr end if; + v.chipSel := axiReadMaster.araddr(CHIP_BITS_C+ADDRESS_SIZE_G+1 downto 2+ADDRESS_SIZE_G); elsif (MODE_G = "WO") then axiSlaveReadResponse(v.axiReadSlave, AXI_RESP_DECERR_C); else diff --git a/python/surf/devices/transceivers/_Qsfp.py b/python/surf/devices/transceivers/_Qsfp.py index 6ac1caf298..50f5cf6e39 100644 --- a/python/surf/devices/transceivers/_Qsfp.py +++ b/python/surf/devices/transceivers/_Qsfp.py @@ -124,6 +124,37 @@ def __init__(self,**kwargs): dependencies = [self.TxPwrRaw[2*i+0],self.TxPwrRaw[2*i+1]], )) + for i in range(4): + self.add(pr.RemoteVariable( + name = f'TxDisable[{i}]', + description = 'Tx_Disable bit that allows software disable of transmitters, Writing 1 disables the laser of the channel', + offset = (86 << 2), + bitSize = 1, + bitOffset = i, + mode = 'RW', + base = pr.Bool, + )) + + self.add(pr.RemoteVariable( + name = 'PowerOverride', + description = '0: allows setting power mode with hardware, 1: allows setting power mode with software', + offset = (93 << 2), + bitSize = 1, + bitOffset = 0, + mode = 'RW', + base = pr.Bool, + )) + + self.add(pr.RemoteVariable( + name = 'PowerMode', + description = 'Power set to low power mode: 1 sets to LP mode if PowerOverride is 1', + offset = (93 << 2), + bitSize = 1, + bitOffset = 1, + mode = 'RW', + base = pr.Bool, + )) + ################ # Upper Page 00h ################ diff --git a/python/surf/protocols/pgp/_Pgp4RxLiteLowSpeedReg.py b/python/surf/protocols/pgp/_Pgp4RxLiteLowSpeedReg.py new file mode 100644 index 0000000000..5cef5d059f --- /dev/null +++ b/python/surf/protocols/pgp/_Pgp4RxLiteLowSpeedReg.py @@ -0,0 +1,197 @@ +#----------------------------------------------------------------------------- +# This file is part of the 'SLAC Firmware Standard Library'. It is subject to +# the license terms in the LICENSE.txt file found in the top-level directory +# of this distribution and at: +# https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +# No part of the 'SLAC Firmware Standard Library', including this file, may be +# copied, modified, propagated, or distributed except according to the terms +# contained in the LICENSE.txt file. +#----------------------------------------------------------------------------- + +import pyrogue as pr + +class Pgp4RxLiteLowSpeedReg(pr.Device): + def __init__(self, + numberLanes = 1, + statusCountBits = 16, + **kwargs): + super().__init__(**kwargs) + + self.addRemoteVariables( + name = 'LockedCnt', + description = 'status count that increases per locked detection event', + offset = 0*(numberLanes<<2), + bitSize = statusCountBits, + mode = 'RO', + number = numberLanes, + stride = 4, + pollInterval = 1, + ) + + self.addRemoteVariables( + name = 'BitSlipCnt', + description = 'status count that increases per bitslip detection event', + offset = 1*(numberLanes<<2), + bitSize = statusCountBits, + mode = 'RO', + number = numberLanes, + stride = 4, + pollInterval = 1, + ) + + self.addRemoteVariables( + name = 'ErrorDetCnt', + description = 'status count that increases per error detection event', + offset = 2*(numberLanes<<2), + bitSize = statusCountBits, + mode = 'RO', + number = numberLanes, + stride = 4, + pollInterval = 1, + ) + + self.addRemoteVariables( + name = 'EyeWidth', + description = 'Measured eye width after locking completed', + offset = 0x200, + bitSize = 9, + mode = 'RO', + number = numberLanes, + stride = 4, + pollInterval = 1, + ) + + self.add(pr.RemoteVariable( + name = 'Locked', + description = 'auto aligner locked status', + offset = 0x400, + bitSize = numberLanes, + mode = 'RO', + pollInterval = 1, + )) + + self.addRemoteVariables( + name = 'UsrDlyCfg', + description = 'manual user delay value when EnUsrDlyCfg = 0x1', + offset = 0x500, + bitSize = 9, + mode = 'RW', + number = numberLanes, + stride = 4, + ) + + self.addRemoteVariables( + name = 'DlyConfig', + description = 'Current IDELAY value', + offset = 0x600, + bitSize = 9, + mode = 'RO', + number = numberLanes, + stride = 4, + pollInterval = 1, + ) + + self.add(pr.RemoteVariable( + name = 'NUM_LANE_G', + description = 'NUM_LANE_G VHDL genenic value', + offset = 0x7FC, + bitSize = 8, + bitOffset = 8, + mode = 'RO', + disp = '{:d}', + )) + + self.add(pr.RemoteVariable( + name = 'EnUsrDlyCfg', + description = 'Enables User delay config (UsrDlyCfg)', + offset = 0x800, + bitSize = 1, + mode = 'RW', + )) + +##################################### +# Changed from "common" to 1 per lane +##################################### +# self.add(pr.RemoteVariable( +# name = 'UsrDlyCfg', +# description = 'User delay config', +# offset = 0x804, +# bitSize = 9, +# mode = 'RW', +# )) + + self.add(pr.RemoteVariable( + name = 'MinEyeWidth', + description = 'Sets the minimum eye width required for locking (units of IDELAY step)', + offset = 0x808, + bitSize = 8, + mode = 'RW', + )) + + self.add(pr.RemoteVariable( + name = 'LockingCntCfg', + description = 'Number of error-free event before state=LOCKED_S', + offset = 0x80C, + bitSize = 24, + mode = 'RW', + )) + + self.add(pr.RemoteVariable( + name = 'BypFirstBerDet', + description = 'Set to 0x1 if IDELAY full scale range > 2 Unit Intervals (UI) of serial rate (example: IDELAY range 2.5ns > 1 ns (1Gb/s) )', + offset = 0x810, + bitSize = 1, + mode = 'RW', + )) + + self.add(pr.RemoteVariable( + name = 'Polarity', + description = '1: Invert diff pair, 0: Non-inverted diff pair', + offset = 0x814, + bitSize = numberLanes, + mode = 'RW', + )) + + self.add(pr.RemoteVariable( + name = 'GearboxSlaveBitOrder', + description = '1: reverse gearbox input bit ordering, 0: normal bit ordering', + offset = 0x818, + bitSize = 1, + bitOffset = 0, + mode = 'RW', + )) + + self.add(pr.RemoteVariable( + name = 'GearboxMasterBitOrder', + description = '1: reverse gearbox output bit ordering, 0: normal', + offset = 0x818, + bitSize = 1, + bitOffset = 1, + mode = 'RW', + )) + + self.add(pr.RemoteVariable( + name = 'RollOverEn', + description = 'Rollover enable for status counters', + offset = 0xFF8, + bitSize = 7, + mode = 'RW', + )) + + self.add(pr.RemoteCommand( + name = 'CntRst', + description = 'Status counter reset', + offset = 0xFFC, + bitSize = 1, + function = lambda cmd: cmd.post(1), + hidden = False, + )) + + def hardReset(self): + self.CntRst() + + def softReset(self): + self.CntRst() + + def countReset(self): + self.CntRst() diff --git a/python/surf/protocols/pgp/__init__.py b/python/surf/protocols/pgp/__init__.py index 4dc84b367a..c15cdbbeae 100644 --- a/python/surf/protocols/pgp/__init__.py +++ b/python/surf/protocols/pgp/__init__.py @@ -11,3 +11,4 @@ from surf.protocols.pgp._Pgp2fcAxi import * from surf.protocols.pgp._Pgp3AxiL import * from surf.protocols.pgp._Pgp4AxiL import * +from surf.protocols.pgp._Pgp4RxLiteLowSpeedReg import * diff --git a/tests/test_SaciAxiLiteMasterTb.py b/tests/test_SaciAxiLiteMasterTb.py new file mode 100644 index 0000000000..66812e6d5d --- /dev/null +++ b/tests/test_SaciAxiLiteMasterTb.py @@ -0,0 +1,160 @@ +############################################################################## +## This file is part of 'SLAC Firmware Standard Library'. +## It is subject to the license terms in the LICENSE.txt file found in the +## top-level directory of this distribution and at: +## https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +## No part of 'SLAC Firmware Standard Library', including this file, +## may be copied, modified, propagated, or distributed except according to +## the terms contained in the LICENSE.txt file. +############################################################################## + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, Timer +from cocotb.regression import TestFactory + +from cocotbext.axi import AxiLiteBus, AxiLiteMaster + +# test_SaciAxiLiteMasterTb +from cocotb_test.simulator import run +import pytest +import glob +import os +import itertools +import logging + +class TB: + def __init__(self, dut): + + # Pointer to DUT object + self.dut = dut + + self.log = logging.getLogger("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # Start clock (125 MHz) in a separate thread + cocotb.start_soon(Clock(dut.S_AXI_ACLK, 8.0, units='ns').start()) + + # Create the AXI-Lite Master + self.axil_master = AxiLiteMaster( + bus = AxiLiteBus.from_prefix(dut, 'S_AXI'), + clock = dut.S_AXI_ACLK, + reset = dut.S_AXI_ARESETN, + reset_active_level=False) + + def set_idle_generator(self, generator=None): + if generator: + self.axil_master.write_if.aw_channel.set_pause_generator(generator()) + self.axil_master.write_if.w_channel.set_pause_generator(generator()) + self.axil_master.read_if.ar_channel.set_pause_generator(generator()) + + def set_backpressure_generator(self, generator=None): + if generator: + self.axil_master.write_if.b_channel.set_pause_generator(generator()) + self.axil_master.read_if.r_channel.set_pause_generator(generator()) + + async def cycle_reset(self): + self.dut.S_AXI_ARESETN.setimmediatevalue(0) + await RisingEdge(self.dut.S_AXI_ACLK) + await RisingEdge(self.dut.S_AXI_ACLK) + self.dut.S_AXI_ARESETN.value = 0 + await RisingEdge(self.dut.S_AXI_ACLK) + await RisingEdge(self.dut.S_AXI_ACLK) + self.dut.S_AXI_ARESETN.value = 1 + await RisingEdge(self.dut.S_AXI_ACLK) + await RisingEdge(self.dut.S_AXI_ACLK) + + +async def run_test_words(dut): + + tb = TB(dut) + + await tb.cycle_reset() + + # Wait for internal reset to fall + await Timer(10, 'us') + + for offsetHigh in range(17): + for offsetLow in range(0, 0xF, 4): + high = 0 + if offsetHigh != 0: + high = (1 << (offsetHigh+3)) + addr = high | offsetLow + + test_data = addr.to_bytes(length=4, byteorder='little') + event = tb.axil_master.init_write(addr, test_data) + await event.wait() + event = tb.axil_master.init_read(addr, 4) + await event.wait() + assert event.data.data == test_data + + await RisingEdge(dut.S_AXI_ACLK) + await RisingEdge(dut.S_AXI_ACLK) + + +def cycle_pause(): + return itertools.cycle([1, 1, 1, 0]) + + +if cocotb.SIM_NAME: + + ################# + # run_test_words + ################# + factory = TestFactory(run_test_words) + factory.generate_tests() + +tests_dir = os.path.dirname(__file__) +tests_module = 'SaciAxiLiteMasterTb' + +############################################################################## + +@pytest.mark.parametrize( + "parameters", [ + None + ]) +def test_SaciAxiLiteMasterTb(parameters): + + # https://github.com/themperek/cocotb-test#arguments-for-simulatorrun + # https://github.com/themperek/cocotb-test/blob/master/cocotb_test/simulator.py + run( + # top level HDL + toplevel = f'surf.{tests_module}'.lower(), + + # name of the file that contains @cocotb.test() -- this file + # https://docs.cocotb.org/en/stable/building.html?#envvar-MODULE + module = f'test_{tests_module}', + + # https://docs.cocotb.org/en/stable/building.html?#var-TOPLEVEL_LANG + toplevel_lang = 'vhdl', + + # VHDL source files to include. + # Can be specified as a list or as a dict of lists with the library name as key, + # if the simulator supports named libraries. + vhdl_sources = { + 'surf' : glob.glob(f'{tests_dir}/../build/SRC_VHDL/surf/*'), + 'ruckus' : glob.glob(f'{tests_dir}/../build/SRC_VHDL/ruckus/*'), + }, + + # A dictionary of top-level parameters/generics. + parameters = parameters, + + # The directory used to compile the tests. (default: sim_build) + sim_build = f'{tests_dir}/sim_build/{tests_module}', + + # A dictionary of extra environment variables set in simulator process. + extra_env=parameters, + + # Select a simulator + simulator="ghdl", + + # use of synopsys package "std_logic_arith" needs the -fsynopsys option + # -frelaxed-rules option to allow IP integrator attributes + # When two operators are overloaded, give preference to the explicit declaration (-fexplicit) + vhdl_compile_args = ['-fsynopsys','-frelaxed-rules', '-fexplicit'], + + ######################################################################## + # Dump waveform to file ($ gtkwave sim_build/path/To/{tests_module}.ghw) + ######################################################################## + # sim_args =[f'--wave={tests_module}.ghw'], + ) diff --git a/xilinx/UltraScale/general/rtl/SelectioDeserUltraScale.vhd b/xilinx/UltraScale/general/rtl/SelectioDeserUltraScale.vhd index 325aebb03e..cd3799d3ae 100644 --- a/xilinx/UltraScale/general/rtl/SelectioDeserUltraScale.vhd +++ b/xilinx/UltraScale/general/rtl/SelectioDeserUltraScale.vhd @@ -34,20 +34,23 @@ entity SelectioDeserUltraScale is CLKIN_PERIOD_G : real := 10.0; -- 100 MHz DIVCLK_DIVIDE_G : positive := 1; CLKFBOUT_MULT_G : positive := 10; -- 1 GHz = 100 MHz x 10 / 1 - CLKOUT0_DIVIDE_G : positive := 2); -- 500 MHz = 1 GHz/2 + CLKOUT0_DIVIDE_G : positive := 2; -- 500 MHz = 1 GHz/2 + CLKOUT1_DIVIDE_G : positive := 32); -- 31.25 MHz = 1 GHz/32 port ( -- SELECTIO Ports rxP : in slv(NUM_LANE_G-1 downto 0); rxN : in slv(NUM_LANE_G-1 downto 0); - pllClk : out sl; - -- External PLL Interface + -- Optional Clock Outputs + pllClk : out sl; -- clkout0 + userClk : out sl; -- clkout1 + -- External PLL Interface (EXT_PLL_G = TRUE) extPllClkIn : in sl := '0'; extPllRstIn : in sl := '1'; - -- Reference Clock and Reset + -- Reference Clock and Reset (EXT_PLL_G = FALSE) refClk : in sl; refRst : in sl; -- Deserialization Interface (deserClk domain) - deserClk : out sl; + deserClk : out sl; -- clkout0/4 deserRst : out sl; deserData : out Slv8Array(NUM_LANE_G-1 downto 0); dlyLoad : in slv(NUM_LANE_G-1 downto 0); @@ -73,6 +76,7 @@ architecture mapping of SelectioDeserUltraScale is signal locked : sl := '0'; signal clkFb : sl := '0'; signal clkout0 : sl := '0'; + signal clkout1 : sl := '0'; signal clkx4 : sl := '0'; signal clkx1 : sl := '0'; @@ -122,7 +126,8 @@ begin CLKIN_PERIOD => CLKIN_PERIOD_G, DIVCLK_DIVIDE => DIVCLK_DIVIDE_G, CLKFBOUT_MULT => CLKFBOUT_MULT_G, - CLKOUT0_DIVIDE => CLKOUT0_DIVIDE_G) + CLKOUT0_DIVIDE => CLKOUT0_DIVIDE_G, + CLKOUT1_DIVIDE => CLKOUT1_DIVIDE_G) port map ( DCLK => axilClk, DRDY => drpRdy, @@ -139,7 +144,7 @@ begin CLKFBIN => clkFb, LOCKED => locked, CLKOUT0 => clkout0, - CLKOUT1 => open); + CLKOUT1 => clkout1); end generate GEN_REAL; @@ -148,7 +153,7 @@ begin axilReadSlave <= AXI_LITE_READ_SLAVE_EMPTY_DECERR_C; axilWriteSlave <= AXI_LITE_WRITE_SLAVE_EMPTY_DECERR_C; - U_ClkRst : entity surf.ClkRst + U_clkout0 : entity surf.ClkRst generic map ( CLK_PERIOD_G => (CLKIN_PERIOD_G*DIVCLK_DIVIDE_G*CLKOUT0_DIVIDE_G/CLKFBOUT_MULT_G)*(1.0 ns), RST_START_DELAY_G => 0 ns, @@ -157,6 +162,14 @@ begin clkP => clkout0, rstL => locked); + U_clkout1 : entity surf.ClkRst + generic map ( + CLK_PERIOD_G => (CLKIN_PERIOD_G*DIVCLK_DIVIDE_G*CLKOUT1_DIVIDE_G/CLKFBOUT_MULT_G)*(1.0 ns), + RST_START_DELAY_G => 0 ns, + RST_HOLD_TIME_G => 1000 ns) + port map ( + clkP => clkout1); + end generate GEN_SIM; U_Bufg640 : BUFG @@ -169,9 +182,15 @@ begin GEN_EXT_PLL : if (EXT_PLL_G = true) generate clkx4 <= extPllClkIn; clkout0 <= extPllClkIn; + clkout1 <= extPllClkIn; locked <= not(extPllRstIn); end generate GEN_EXT_PLL; + U_UserClk : BUFG + port map ( + I => clkout1, + O => userClk); + ------------------------------------------------------------------------------------------------------ -- clkx1 is the ISERDESE3/OSERDESE3's CLKDIV port -- Refer to "Figure 3-49: Sub-Optimal to Optimal Clocking Topologies for OSERDESE3" in UG949 (v2018.2)