SURF  1.0
SsiPrbsTx.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SsiPrbsTx.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2014-04-02
5 -- Last update: 2016-10-25
6 -------------------------------------------------------------------------------
7 -- Description: This module generates
8 -- PseudoRandom Binary Sequence (PRBS) on Virtual Channel Lane.
9 -------------------------------------------------------------------------------
10 -- This file is part of 'SLAC Firmware Standard Library'.
11 -- It is subject to the license terms in the LICENSE.txt file found in the
12 -- top-level directory of this distribution and at:
13 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
14 -- No part of 'SLAC Firmware Standard Library', including this file,
15 -- may be copied, modified, propagated, or distributed except according to
16 -- the terms contained in the LICENSE.txt file.
17 -------------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.std_logic_unsigned.all;
22 use ieee.std_logic_arith.all;
23 
24 use work.StdRtlPkg.all;
25 use work.AxiLitePkg.all;
26 use work.AxiStreamPkg.all;
27 use work.SsiPkg.all;
28 
29 --! @see entity
30  --! @ingroup protocols_ssi
31 entity SsiPrbsTx is
32  generic (
33  -- General Configurations
34  TPD_G : time := 1 ns;
36  -- FIFO Configurations
37  VALID_THOLD_G : integer range 0 to (2**24) := 1;
38  VALID_BURST_MODE_G : boolean := false;
39  BRAM_EN_G : boolean := true;
40  XIL_DEVICE_G : string := "7SERIES";
41  USE_BUILT_IN_G : boolean := false;
42  GEN_SYNC_FIFO_G : boolean := false;
43  ALTERA_SYN_G : boolean := false;
44  ALTERA_RAM_G : string := "M9K";
45  CASCADE_SIZE_G : natural range 1 to (2**24) := 1;
46  FIFO_ADDR_WIDTH_G : natural range 4 to 48 := 9;
47  FIFO_PAUSE_THRESH_G : natural range 1 to (2**24) := 2**8;
48  -- PRBS Configurations
49  PRBS_SEED_SIZE_G : natural range 8 to 128 := 32;
50  PRBS_TAPS_G : NaturalArray := (0 => 31, 1 => 6, 2 => 2, 3 => 1);
51  PRBS_INCREMENT_G : boolean := false; -- Increment mode by default instead of PRBS
52  -- AXI Stream Configurations
53  MASTER_AXI_STREAM_CONFIG_G : AxiStreamConfigType := ssiAxiStreamConfig(16, TKEEP_COMP_C);
54  MASTER_AXI_PIPE_STAGES_G : natural range 0 to 16 := 0);
55  port (
56  -- Master Port (mAxisClk)
57  mAxisClk : in sl;
58  mAxisRst : in sl;
61  -- Trigger Signal (locClk domain)
62  locClk : in sl;
63  locRst : in sl := '0';
64  trig : in sl := '1';
65  packetLength : in slv(31 downto 0) := X"FFFFFFFF";
66  forceEofe : in sl := '0';
67  busy : out sl;
68  tDest : in slv(7 downto 0) := X"00";
69  tId : in slv(7 downto 0) := X"00";
70  -- Optional: Axi-Lite Register Interface (locClk domain)
75 end SsiPrbsTx;
76 
77 architecture rtl of SsiPrbsTx is
78 
79  constant PRBS_BYTES_C : natural := wordCount(PRBS_SEED_SIZE_G, 8);
80  constant PRBS_SSI_CONFIG_C : AxiStreamConfigType := (
81  TSTRB_EN_C => false,
82  TDATA_BYTES_C => PRBS_BYTES_C,
83  TDEST_BITS_C => 8,
84  TID_BITS_C => 8,
86  TUSER_BITS_C => 2,
88 
89  type StateType is (
90  IDLE_S,
91  SEED_RAND_S,
92  LENGTH_S,
93  DATA_S);
94 
95  type RegType is record
96  busy : sl;
97  overflow : sl;
98  length : slv(31 downto 0);
99  packetLength : slv(31 downto 0);
100  dataCnt : slv(31 downto 0);
101  eventCnt : slv(PRBS_SEED_SIZE_G-1 downto 0);
102  randomData : slv(PRBS_SEED_SIZE_G-1 downto 0);
103  txAxisMaster : AxiStreamMasterType;
104  state : StateType;
105  axiEn : sl;
106  oneShot : sl;
107  trig : sl;
108  cntData : sl;
109  tDest : slv(7 downto 0);
110  tId : slv(7 downto 0);
113  end record;
114 
115  constant REG_INIT_C : RegType := (
116  busy => '1',
117  overflow => '0',
118  length => (others => '0'),
119  packetLength => (others => '0'),
120  dataCnt => (others => '0'),
121  eventCnt => (others => '0'),
122  randomData => (others => '0'),
123  txAxisMaster => AXI_STREAM_MASTER_INIT_C,
124  state => IDLE_S,
125  axiEn => '0',
126  oneShot => '0',
127  trig => '0',
128  cntData => toSl(PRBS_INCREMENT_G),
129  tDest => X"00",
130  tId => X"00",
133 
134  signal r : RegType := REG_INIT_C;
135  signal rin : RegType;
136 
137  signal txSlave : AxiStreamSlaveType;
138  signal txCtrl : AxiStreamCtrlType;
139 
140 begin
141 
142 -- assert (PRBS_SEED_SIZE_G mod 8 = 0) report "PRBS_SEED_SIZE_G must be a multiple of 8" severity failure;
143 
145  trig, txCtrl, txSlave) is
146  variable v : RegType;
147  variable axilStatus : AxiLiteStatusType;
148  variable axilWriteResp : slv(1 downto 0);
149  variable axilReadResp : slv(1 downto 0);
150  begin
151  -- Latch the current value
152  v := r;
153 
154  -- Reset the one shot
155  v.oneShot := '0';
156 
157  ----------------------------------------------------------------------------------------------
158  -- Axi-Lite interface
159  ----------------------------------------------------------------------------------------------
160  axiSlaveWaitTxn(axilWriteMaster, axilReadMaster, v.axilWriteSlave, v.axilReadSlave, axilStatus);
161 
162  if (axilStatus.writeEnable = '1') then
163  axilWriteResp := ite(axilWriteMaster.awaddr(1 downto 0) = "00", AXI_RESP_OK_C, AXI_ERROR_RESP_G);
164  case (axilWriteMaster.awaddr(7 downto 0)) is
165  when X"00" =>
166  v.axiEn := axilWriteMaster.wdata(0);
167  v.trig := axilWriteMaster.wdata(1);
168  -- BIT2 reserved for busy
169  -- BIT3 reserved for overflow
170  v.oneShot := axilWriteMaster.wdata(4);
171  v.cntData := axilWriteMaster.wdata(5);
172  when X"04" =>
173  v.packetLength := axilWriteMaster.wdata(31 downto 0);
174  when X"08" =>
175  v.tDest := axilWriteMaster.wdata(7 downto 0);
176  v.tId := axilWriteMaster.wdata(15 downto 8);
177  when others =>
178  axilWriteResp := AXI_ERROR_RESP_G;
179  end case;
180  axiSlaveWriteResponse(v.axilWriteSlave);
181  end if;
182 
183  if (axilStatus.readEnable = '1') then
184  axilReadResp := ite(axilReadMaster.araddr(1 downto 0) = "00", AXI_RESP_OK_C, AXI_ERROR_RESP_G);
185  v.axilReadSlave.rdata := (others => '0');
186  case (axilReadMaster.araddr(7 downto 0)) is
187  when X"00" =>
188  v.axilReadSlave.rdata(0) := r.axiEn;
189  v.axilReadSlave.rdata(1) := r.trig;
190  v.axilReadSlave.rdata(2) := r.busy;
191  v.axilReadSlave.rdata(3) := r.overflow;
192  -- BIT4 reserved for oneShot
193  v.axilReadSlave.rdata(5) := r.cntData;
194  when X"04" =>
195  v.axilReadSlave.rdata(31 downto 0) := r.packetLength;
196  when X"08" =>
197  v.axilReadSlave.rdata(7 downto 0) := r.tDest;
198  v.axilReadSlave.rdata(15 downto 8) := r.tId;
199  when X"0C" =>
200  v.axilReadSlave.rdata(31 downto 0) := r.dataCnt;
201  when X"10" =>
202  if (PRBS_SEED_SIZE_G < 32) then
203  v.axilReadSlave.rdata(PRBS_SEED_SIZE_G-1 downto 0) := r.eventCnt;
204  else
205  v.axilReadSlave.rdata(31 downto 0) := r.eventCnt(31 downto 0);
206  end if;
207  when X"14" =>
208  if (PRBS_SEED_SIZE_G < 32) then
209  v.axilReadSlave.rdata(PRBS_SEED_SIZE_G-1 downto 0) := r.randomData;
210  else
211  v.axilReadSlave.rdata(31 downto 0) := r.randomData(31 downto 0);
212  end if;
213  when others =>
214  axilReadResp := AXI_ERROR_RESP_G;
215  end case;
216  axiSlaveReadResponse(v.axilReadSlave);
217  end if;
218 
219  -- Override axi settings if axi not enabled
220  if (v.axiEn = '0') then
221  v.trig := trig;
223  v.tDest := tDest;
224  v.tId := tId;
225  end if;
226 
227  -- Check for overflow condition or forced EOFE
228  if (txCtrl.overflow = '1') or (forceEofe = '1') then
229  -- Latch the overflow error bit for the data packet
230  v.overflow := '1';
231  end if;
232 
233  -- Check the AXIS flow control
234  if txSlave.tReady = '1' then
235  v.txAxisMaster.tValid := '0';
236  v.txAxisMaster.tLast := '0';
237  v.txAxisMaster.tUser := (others => '0');
238  v.txAxisMaster.tKeep := (others => '1');
239  end if;
240 
241  -- State Machine
242  case (r.state) is
243  ----------------------------------------------------------------------
244  when IDLE_S =>
245  -- Reset the busy flag
246  v.busy := '0';
247  -- Check for a trigger
248  if (r.trig = '1') or (r.oneShot = '1') then
249  -- Latch the generator seed
250  v.randomData := r.eventCnt;
251  -- Set the busy flag
252  v.busy := '1';
253  -- Reset the overflow flag
254  v.overflow := '0';
255  -- Latch the configuration
256  v.txAxisMaster.tDest := r.tDest;
257  v.txAxisMaster.tId := r.tId;
258  -- Check the packet length request value
259  if r.packetLength = 0 then
260  -- Force minimum packet length of 2 (+1)
261  v.length := toSlv(2, 32);
262  elsif r.packetLength = 1 then
263  -- Force minimum packet length of 2 (+1)
264  v.length := toSlv(2, 32);
265  else
266  v.length := r.packetLength;
267  end if;
268  -- Next State
269  v.state := SEED_RAND_S;
270  end if;
271  ----------------------------------------------------------------------
272  when SEED_RAND_S =>
273  -- Check if the FIFO is ready
274  if v.txAxisMaster.tvalid = '0' then
275  -- Send the random seed word
276  v.txAxisMaster.tvalid := '1';
277  v.txAxisMaster.tData(PRBS_SEED_SIZE_G-1 downto 0) := r.eventCnt;
278  -- Generate the next random data word
279 -- for i in 0 to PRBS_SEED_SIZE_G-1 loop
280  v.randomData := lfsrShift(v.randomData, PRBS_TAPS_G, '0');
281 -- end loop;
282  -- Increment the counter
283  v.eventCnt := r.eventCnt + 1;
284  -- Increment the counter
285  v.dataCnt := r.dataCnt + 1;
286  -- Set the SOF bit
287  ssiSetUserSof(PRBS_SSI_CONFIG_C, v.txAxisMaster, '1');
288  -- Next State
289  v.state := LENGTH_S;
290  end if;
291  ----------------------------------------------------------------------
292  when LENGTH_S =>
293  -- Check if the FIFO is ready
294  if v.txAxisMaster.tvalid = '0' then
295  -- Send the upper packetLength value
296  v.txAxisMaster.tvalid := '1';
297  v.txAxisMaster.tData(31 downto 0) := r.length;
298  -- Increment the counter
299  v.dataCnt := r.dataCnt + 1;
300  -- Next State
301  v.state := DATA_S;
302  end if;
303  ----------------------------------------------------------------------
304  when DATA_S =>
305  -- Check if the FIFO is ready
306  if v.txAxisMaster.tvalid = '0' then
307  -- Send the random data word
308  v.txAxisMaster.tValid := '1';
309  -- Check if we are sending PRBS or counter data
310  if r.cntData = '0' then
311  -- PRBS data
312  v.txAxisMaster.tData(PRBS_SEED_SIZE_G-1 downto 0) := r.randomData;
313  else
314  -- Counter data
315  v.txAxisMaster.tData(PRBS_SEED_SIZE_G-1 downto 0) := (others => '0');
316  v.txAxisMaster.tData(31 downto 0) := r.dataCnt;
317  end if;
318  -- Generate the next random data word
319 -- for i in 0 to PRBS_SEED_SIZE_G-1 loop
320  v.randomData := lfsrShift(v.randomData, PRBS_TAPS_G, '0');
321 -- end loop;
322  -- Increment the counter
323  v.dataCnt := r.dataCnt + 1;
324  -- Check the counter
325  if r.dataCnt = r.length then
326  -- Reset the counter
327  v.dataCnt := (others => '0');
328  -- Set the EOF bit
329  v.txAxisMaster.tLast := '1';
330  -- Set the EOFE bit
331  ssiSetUserEofe(PRBS_SSI_CONFIG_C, v.txAxisMaster, r.overflow);
332  -- Reset the busy flag
333  v.busy := '0';
334  -- Next State
335  v.state := IDLE_S;
336  end if;
337  end if;
338  ----------------------------------------------------------------------
339  end case;
340 
341  -- Reset
342  if (locRst = '1') then
343  v := REG_INIT_C;
344  end if;
345 
346  -- Register the variable for next clock cycle
347  rin <= v;
348 
349  -- Outputs
350  busy <= r.busy;
353 
354  end process comb;
355 
356  seq : process (locClk) is
357  begin
358  if rising_edge(locClk) then
359  r <= rin after TPD_G;
360  end if;
361  end process seq;
362 
363  AxiStreamFifo_Inst : entity work.AxiStreamFifoV2
364  generic map(
365  -- General Configurations
366  TPD_G => TPD_G,
369  SLAVE_READY_EN_G => true,
372  -- FIFO configurations
373  BRAM_EN_G => BRAM_EN_G,
381  FIFO_FIXED_THRESH_G => true,
384  -- AXI Stream Port Configurations
385  SLAVE_AXI_CONFIG_G => PRBS_SSI_CONFIG_C,
387  port map (
388  -- Slave Port
389  sAxisClk => locClk,
390  sAxisRst => locRst,
391  sAxisMaster => r.txAxisMaster,
392  sAxisSlave => txSlave,
393  sAxisCtrl => txCtrl,
394  -- Master Port
395  mAxisClk => mAxisClk,
396  mAxisRst => mAxisRst,
399 
400 end rtl;
PRBS_INCREMENT_Gboolean := false
Definition: SsiPrbsTx.vhd:51
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
Definition: SsiPrbsTx.vhd:37
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 9
natural range 0 to 8 TDEST_BITS_C
in mAxisRstsl
Definition: SsiPrbsTx.vhd:58
out sAxisCtrlAxiStreamCtrlType
ALTERA_RAM_Gstring := "M9K"
PIPE_STAGES_Gnatural range 0 to 16:= 1
CASCADE_SIZE_Gnatural range 1 to ( 2** 24):= 1
Definition: SsiPrbsTx.vhd:45
AxiLiteWriteMasterType
Definition: AxiLitePkg.vhd:111
std_logic sl
Definition: StdRtlPkg.vhd:28
AxiStreamMasterType :=(tValid => '0',tData =>( others => '0'),tStrb =>( others => '1'),tKeep =>( others => '1'),tLast => '0',tDest =>( others => '0'),tId =>( others => '0'),tUser =>( others => '0')) AXI_STREAM_MASTER_INIT_C
SLAVE_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
slv( 31 downto 0) rdata
Definition: AxiLitePkg.vhd:89
slv( 15 downto 0) tKeep
MASTER_AXI_STREAM_CONFIG_GAxiStreamConfigType := ssiAxiStreamConfig( 16, TKEEP_COMP_C)
Definition: SsiPrbsTx.vhd:53
in mAxisSlaveAxiStreamSlaveType
Definition: SsiPrbsTx.vhd:60
SLAVE_READY_EN_Gboolean := true
FIFO_FIXED_THRESH_Gboolean := true
TPD_Gtime := 1 ns
Definition: SsiPrbsTx.vhd:34
in axilReadMasterAxiLiteReadMasterType := AXI_LITE_READ_MASTER_INIT_C
Definition: SsiPrbsTx.vhd:71
natural range 1 to 16 TDATA_BYTES_C
in tIdslv( 7 downto 0) := X"00"
Definition: SsiPrbsTx.vhd:69
USE_BUILT_IN_Gboolean := false
Definition: SsiPrbsTx.vhd:41
GEN_SYNC_FIFO_Gboolean := false
in mAxisClksl
Definition: SsiPrbsTx.vhd:57
VALID_BURST_MODE_Gboolean := false
Definition: SsiPrbsTx.vhd:38
TkeepModeType TKEEP_MODE_C
MASTER_AXI_PIPE_STAGES_Gnatural range 0 to 16:= 0
Definition: SsiPrbsTx.vhd:54
FIFO_ADDR_WIDTH_Gnatural range 4 to 48:= 9
Definition: SsiPrbsTx.vhd:46
XIL_DEVICE_Gstring := "7SERIES"
slv( 31 downto 0) wdata
Definition: AxiLitePkg.vhd:117
out axilReadSlaveAxiLiteReadSlaveType
Definition: SsiPrbsTx.vhd:72
in locClksl
Definition: SsiPrbsTx.vhd:62
GEN_SYNC_FIFO_Gboolean := false
Definition: SsiPrbsTx.vhd:42
natural range 0 to 8 TID_BITS_C
PRBS_SEED_SIZE_Gnatural range 8 to 128:= 32
Definition: SsiPrbsTx.vhd:49
slv( 1 downto 0) := "10" AXI_RESP_SLVERR_C
Definition: AxiLitePkg.vhd:36
slv( 127 downto 0) tData
BRAM_EN_Gboolean := true
Definition: SsiPrbsTx.vhd:39
in tDestslv( 7 downto 0) := X"00"
Definition: SsiPrbsTx.vhd:68
INT_PIPE_STAGES_Gnatural range 0 to 16:= 0
array(natural range <> ) of natural NaturalArray
Definition: StdRtlPkg.vhd:34
AxiLiteReadMasterType
Definition: AxiLitePkg.vhd:59
BRAM_EN_Gboolean := true
boolean TSTRB_EN_C
out busysl
Definition: SsiPrbsTx.vhd:67
AXI_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_SLVERR_C
Definition: SsiPrbsTx.vhd:35
in packetLengthslv( 31 downto 0) := X"FFFFFFFF"
Definition: SsiPrbsTx.vhd:65
slv( 31 downto 0) awaddr
Definition: AxiLitePkg.vhd:113
TUserModeType TUSER_MODE_C
slv( 127 downto 0) tUser
in axilWriteMasterAxiLiteWriteMasterType := AXI_LITE_WRITE_MASTER_INIT_C
Definition: SsiPrbsTx.vhd:73
TPD_Gtime := 1 ns
AxiLiteReadSlaveType :=(arready => '0',rdata =>( others => '0'),rresp =>( others => '0'),rvalid => '0') AXI_LITE_READ_SLAVE_INIT_C
Definition: AxiLitePkg.vhd:95
natural range 0 to 8 TUSER_BITS_C
out sAxisSlaveAxiStreamSlaveType
ALTERA_SYN_Gboolean := false
AxiLiteReadMasterType :=(araddr =>( others => '0'),arprot =>( others => '0'),arvalid => '0',rready => '1') AXI_LITE_READ_MASTER_INIT_C
Definition: AxiLitePkg.vhd:69
VALID_BURST_MODE_Gboolean := false
in trigsl := '1'
Definition: SsiPrbsTx.vhd:64
out mAxisMasterAxiStreamMasterType
Definition: SsiPrbsTx.vhd:59
AxiLiteReadSlaveType
Definition: AxiLitePkg.vhd:85
AxiLiteWriteMasterType :=(awaddr =>( others => '0'),awprot =>( others => '0'),awvalid => '0',wdata =>( others => '0'),wstrb =>( others => '1'),wvalid => '0',bready => '1') AXI_LITE_WRITE_MASTER_INIT_C
Definition: AxiLitePkg.vhd:125
in sAxisMasterAxiStreamMasterType
ALTERA_RAM_Gstring := "M9K"
Definition: SsiPrbsTx.vhd:44
ALTERA_SYN_Gboolean := false
Definition: SsiPrbsTx.vhd:43
out mAxisMasterAxiStreamMasterType
slv( 1 downto 0) := "00" AXI_RESP_OK_C
Definition: AxiLitePkg.vhd:31
_library_ ieeeieee
Definition: SsiPrbsRx.vhd:19
slv( 31 downto 0) araddr
Definition: AxiLitePkg.vhd:61
PRBS_TAPS_GNaturalArray :=( 0=> 31, 1=> 6, 2=> 2, 3=> 1)
Definition: SsiPrbsTx.vhd:50
in locRstsl := '0'
Definition: SsiPrbsTx.vhd:63
in mAxisSlaveAxiStreamSlaveType
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
USE_BUILT_IN_Gboolean := false
XIL_DEVICE_Gstring := "7SERIES"
Definition: SsiPrbsTx.vhd:40
FIFO_PAUSE_THRESH_Ginteger range 1 to ( 2** 24):= 1
VALID_THOLD_Ginteger range 0 to ( 2** 24):= 1
out axilWriteSlaveAxiLiteWriteSlaveType
Definition: SsiPrbsTx.vhd:74
AxiLiteWriteSlaveType :=(awready => '0',wready => '0',bresp =>( others => '0'),bvalid => '0') AXI_LITE_WRITE_SLAVE_INIT_C
Definition: AxiLitePkg.vhd:156
MASTER_AXI_CONFIG_GAxiStreamConfigType := AXI_STREAM_CONFIG_INIT_C
CASCADE_PAUSE_SEL_Ginteger range 0 to ( 2** 24):= 0
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
FIFO_PAUSE_THRESH_Gnatural range 1 to ( 2** 24):= 2** 8
Definition: SsiPrbsTx.vhd:47
in forceEofesl := '0'
Definition: SsiPrbsTx.vhd:66