All Classes Namespaces Files Functions Variables Groups Pages
ExampleComponent.vhd
Go to the documentation of this file.
1 -- ************************************************************************** --
2 -- ************* BittWare Incorporated ************* --
3 -- ************* 9 Hills Ave, Concord, NH 03301 ************* --
4 -- ************************************************************************** --
5 -- LEGAL NOTICE: --
6 -- Copyright (c) 2012 BittWare, Inc. --
7 -- The user is hereby granted a non-exclusive license to use and or --
8 -- modify this code provided that it runs on BittWare hardware. --
9 -- Usage of this code on non-BittWare hardware without the express --
10 -- written permission of BittWare is strictly prohibited. --
11 -- --
12 -- E-mail: support@bittware.com Tel: 603-226-0404 --
13 -- ************************************************************************** --
14 
15 --------------------------------------------------------------------------------
16 -- Libraries
17 --------------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.numeric_std.all;
22 
23 use work.UtilityPkg.all;
24 use work.BoardInfoPkg.all;
25 use work.ComponentPkg.all;
26 use work.AvalonPkg.all;
27 use work.MiscPkg.all;
28 use work.RegisterPkg.all;
29 use work.FIFOPkg.all;
30 use work.ExamplePkg.all;
31 
32 --------------------------------------------------------------------------------
33 -- ABSTRACT:
34 --------------------------------------------------------------------------------
42 
43 --------------------------------------------------------------------------------
44 -- DESIGN DETAILS:
45 --------------------------------------------------------------------------------
61 
62 --------------------------------------------------------------------------------
63 -- NOTES:
64 --------------------------------------------------------------------------------
66 
67 --------------------------------------------------------------------------------
68 -- TODO:
69 --------------------------------------------------------------------------------
71 
72 --------------------------------------------------------------------------------
73 -- BUGS
74 --------------------------------------------------------------------------------
76 
77 --------------------------------------------------------------------------------
78 -- RETURN LINKS:
79 --------------------------------------------------------------------------------
81 
82 --------------------------------------------------------------------------------
84 --------------------------------------------------------------------------------
85 generic (
87  BOARD_INFO : BoardInfo;
89  DATA_IN_INFO : AvalonSTInfo;
91  DATA_OUT_INFO : AvalonSTInfo
92 );
93 
94  --
95  -- Other common generic interace parameters
96  --
97 
98  -------------------------------
99  -- Memory Interface Parameters
100  -- The MASTER/SLAVE_INFO parameter is not used in most components.
101  -- In the case of this example, we are restricting the address and data
102  -- width of the memory interface so that we don't have to support reshaping of
103  -- data and variable addres widths. However, these parameters are still very
104  -- necessary when you have a component that is decoding or switching
105  -- the memory interface.
106  -------------------------------
107  -- Master Interface
108  --MASTER_INFO : AvalonMMMasterInfo
109  -- Master Array Interface
110  --MASTER_PORTS : natural;
111  --MASTER_INFO : AvalonMMMasterInfoArray;
112  -------------------------------
113  -- Slave Interface
114  --SLAVE_INFO : AvalonMMSlaveInfo;
115  -- Slave Array Interface
116  --SLAVE_PORTS : natural;
117  --SLAVE_INFO : AvalonMMSlaveInfoArray;
118  -------------------------------
119  -- In the rare occation when there is an input and output interface and both
120  -- share the same configuration info, use the IN/OUT subfix to specify parameters.
121  -- SLAVE/MASTER_IN/OUT_PORTS : natural;
122  -- SLAVE/MASTER_IN/OUT_INFO : AvalonMM(Master/Slave)Info;
123  -- SLAVE/MASTER_IN/OUT_INFO : AvalonMM(Master/Slave)InfoArray;
124  -------------------------------
125  -- Streaming Data Interface
126  --DATA_INFO : AvalonSTInfo;
127  -- OR if the inputs and outputs don't match
128  --DATA_IN_INFO : AvalonSTInfo;
129  --DATA_OUT_INFO : AvalonSTInfo;
130  -------------------------------
131  -- Streaming Array Interface
132  --DATA_PORTS : natural;
133  --DATA_INFO : AvalonSTInfoArray;
134  -- OR
135  --DATA_INFO : AvalonSTInfoArray(0 to DATA_PORTS-1);
136  -------------------------------
137  -- Streaming Array Input/Output Interfaces
138  --DATA_IN_PORTS : natural;
139  --DATA_IN_INFO : AvalonSTInfoArray;
140  --DATA_OUT_PORTS : natural;
141  --DATA_OUT_INFO : AvalonSTInfoArray
142 
143 port (
146  slaveClk : in std_logic;
147  slaveReset : in std_logic;
148  slaveIRQ : out AvalonIRQSenderIntfArray(2 downto 0);
149  slaveIn : in AvalonMMFabricToSlaveIntf;
150  slaveInRsp : out AvalonMMSlaveToFabricIntf;
154  dataClk : in std_logic;
155  dataReset : in std_logic;
156  dataIn : in AvalonSTSourceToSinkIntf;
157  dataInRsp : out AvalonSTSinkToSourceIntf;
158  dataOut : out AvalonSTSourceToSinkIntf;
159  dataOutRsp : in AvalonSTSinkToSourceIntf
161 );
162 
163  --
164  -- Other common Avalon Interface Combinations
165  --
166 
167  -------------------------------
168  -- Master Interface
169  --masterClk : in std_logic;
170  --masterReset : in std_logic;
171  --masterIRQ : in AvalonIRQReceiverIntf;
172  -- Master Input Interface
173  --masterIn : in AvalonMMMasterToFabricIntf;
174  --masterInRsp : out AvalonMMFabricToMasterIntf;
175  -- Master Output Interface
176  --masterOut : out AvalonMMMasterToFabricIntf;
177  --masterOutRsp : in AvalonMMFabricToMasterIntf;
178  -------------------------------
179  -- Slave Interface
180  --slaveClk : in std_logic;
181  --slaveReset : in std_logic;
182  --slaveIRQ : out AvalonIRQSenderIntf;
183  -- Slave Input Interface
184  --slaveIn : in AvalonMMFabricToSlaveIntf;
185  --slaveInRsp : out AvalonMMSlaveToFabricIntf;
186  -- Slave Output Interface
187  --slaveOut : out AvalonMMFabricToSlaveIntf;
188  --slaveOutRsp : in AvalonMMSlaveToFabricIntf;
189  -------------------------------
190  -- Master Array Input Interface
191  --masterIn : in AvalonMMMasterToFabricIntfArray(0 to MASTER_PORTS-1);
192  --masterInRsp : out AvalonMMFabricToMasterIntfArray(0 to MASTER_PORTS-1);
193  -- Master Array Output Interface
194  --masterOut : out AvalonMMMasterToFabricIntfArray(0 to MASTER_PORTS-1);
195  --masterOutRsp : in AvalonMMFabricToMasterIntfArray(0 to MASTER_PORTS-1);
196  -------------------------------
197  -- Slave Array Input Interface
198  --slaveIn : in AvalonMMFabricToSlaveIntfArray(0 to MASTER_PORTS-1);
199  --slaveInRsp : out AvalonMMSlaveToFabricIntfArray(0 to MASTER_PORTS-1);
200  -- Slave Array Output Interface
201  --slaveOut : out AvalonMMFabricToSlaveIntfArray(0 to MASTER_PORTS-1);
202  --slaveOutRsp : in AvalonMMSlaveToFabricIntfArray(0 to MASTER_PORTS-1);
203  -------------------------------
204  -- Single Rate Component Clock Input
205  --dataClk : in std_logic;
206  --dataReset : in std_logic;
207  -- Multi-Rate Component Clock Input
208  --dataInClk : in std_logic;
209  --dataInReset : in std_logic;
210  -- Multi-Rate Component Clock Output
211  --dataOutClk : in std_logic;
212  --dataOutReset : in std_logic;
213  -------------------------------
214  -- Streaming Input Interface
215  --dataIn : in AvalonSTSourceToSinkIntf;
216  --dataInRsp : out AvalonSTSinkToSourcercIntf;
217  -- Streaming Array Input Interface
218  --dataIn : in AvalonSTSourceToSinkIntfArray(0 to DATA_IN_PORTS-1);
219  --dataInRsp : out AvalonSTSinkToSourceIntfArray(0 to DATA_IN_PORTS-1);
220  -- Here is another example except you can defer the sizing.
221  --dataIn : in AvalonSTSourceToSinkIntfArray;
222  --dataInRsp : out AvalonSTSinkToSourceIntfArray;
223  -------------------------------
224  -- Streaming Output Interface
225  --dataOut : out AvalonSTSourceToSinkIntf;
226  --dataOutRsp : in AvalonSTSinkToSourceIntf;
227  -- Streaming Array Output Interface
228  --dataOut : out AvalonSTSourceToSinkIntfArray(0 to DATA_OUT_PORTS-1);
229  --dataOutRsp : in AvalonSTSinkToSourceIntfArray(0 to DATA_OUT_PORTS-1);
230  -------------------------------
231  -- Event Interface
232  --eventCtrl : out AvalonSTEventIntf;
233  --eventStatus : in AvalonSTEventIntf;
234  -- Event Interface Array
235  --eventCtrl : out AvalonSTEventIntfArray;
236  --eventStatus : in AvalonSTEventIntfArray;
237 
238 --------------------------------------------------------------------------------
239 end entity;
240 --------------------------------------------------------------------------------
241 
242 --------------------------------------------------------------------------------
243 -- BRIEF LINKS:
244 --------------------------------------------------------------------------------
251 
252 --------------------------------------------------------------------------------
253 -- BLOCK DIAGRAM:
254 --------------------------------------------------------------------------------
258 
259 --------------------------------------------------------------------------------
260 -- RETURN LINKS:
261 --------------------------------------------------------------------------------
263 
264 --------------------------------------------------------------------------------
265 architecture ExampleComponent_BEH of ExampleComponent is
266 --------------------------------------------------------------------------------
267 
268  ---------------------------
269  -- Size Declarations
270  ---------------------------
271 
272  -- By declaring some range types, access of data is easier. Add more, remove
273  -- some. Do whatever makes it easiest to get at the data fields and meets
274  -- design requirements. Oh, just don't hardcode BITS
275  -- For ports using a single sizing...use DATA_INFO/WIDTH/RANGE
276  --constant DATA_WIDTH : natural := DATA_INFO.BITS_PER_SYMBOL*DATA_INFO.SYMBOLS_PER_BEAT;
277  --subtype DATA_RANGE is natural range (DATA_WIDTH-1) downto 0;
278 
280  constant DATA_IN_WIDTH : natural := DATA_IN_INFO.BITS_PER_SYMBOL*DATA_IN_INFO.SYMBOLS_PER_BEAT;
281  subtype DATA_IN_RANGE is natural range (DATA_IN_WIDTH-1) downto 0;
282 
284  constant DATA_OUT_WIDTH : natural := DATA_OUT_INFO.BITS_PER_SYMBOL*DATA_OUT_INFO.SYMBOLS_PER_BEAT;
285  subtype DATA_OUT_RANGE is natural range (DATA_OUT_WIDTH-1) downto 0;
286 
287  ---------------------------
288  -- Register Configuration
289  ---------------------------
290 
292  constant REG_DATA_WIDTH : natural := 8;
293  subtype REG_DATA_RANGE is natural range (REG_DATA_WIDTH-1) downto 0;
294 
295  ------------------------------------------------------------------------------
296  -- DOXYGEN INSTRUCTIONS
297  ------------------------------------------------------------------------------
298  -- DOXYGEN: Register Description Instructions:
299  -- DOXYGEN: Add a group named for this component. All of the component's registers
300  -- DOXYGEN: will be add to this group. Describe the group detail with the
301  -- DOXYGEN: tag, @details, and add an @see to link back to the architecture.
302  -- DOXYGEN: Create a group with the same name as the register. Describe the
303  -- DOXYGEN: register with @details tag and add an @see link back to the architecture
304  -- DOXYGEN: The @{ and @} bound the group. The entity group name must be unique.
305  -- DOXYGEN: Describe the register bits with the @details tag
306  ------------------------------------------------------------------------------
307 
313 
318  constant CONTROL_REGISTER : RegisterLocation := init( "example_control", REG_COMPONENT_START_ADDR+toInt(x"00"), 3, RW_REG_CFG );
320  constant A_CTRL_BIT : RegisterBit := 0;
323  subtype SOME_CTRL_RANGE is natural range 2 downto 1;
325 
334  constant STATUS_REGISTER : RegisterLocation := init( "exmaple_status", REG_COMPONENT_START_ADDR+toInt(x"01"), 8, RO_STATUS_REG_CFG );
336  constant ALMOST_FULL_BIT : RegisterBit := FIFO_WR_ALMOST_FULL_BIT;
338  constant FULL_BIT : RegisterBit := FIFO_WR_FULL_BIT;
340  constant ALMOST_EMPTY_BIT : RegisterBit := FIFO_RD_ALMOST_EMPTY_BIT;
342  constant EMPTY_BIT : RegisterBit := FIFO_RD_EMPTY_BIT;
344 
349  constant COUNT_CONFIG_REGISTER : RegisterLocation := init( "count_config", REG_COMPONENT_START_ADDR+toInt(x"02"), 2, RW_WR_CLEAR_REG_CFG );
351  constant LOAD_BIT : RegisterBit := 0;
353  constant PAUSE_BIT : RegisterBit := 1;
355 
362  constant COUNT_INIT_REGISTER : RegisterLocation := init( "count_init", REG_COMPONENT_START_ADDR+toInt(x"03"), REG_DATA_WIDTH, RW_REG_CFG );
364 
370  constant COUNT_STEP_REGISTER : RegisterLocation := init( "count_step", REG_COMPONENT_START_ADDR+toInt(x"04"), REG_DATA_WIDTH, RW_REG_CFG );
372 
379  constant FLAGS_REGISTER : RegisterLocation := init( "flags", REG_COMPONENT_START_ADDR+toInt(x"05"), REG_DATA_WIDTH, RO_STATUS_RD_FLAG_REG_CFG );
381 
390  constant IRQ_BIT : RegisterBit := 0;
392  constant NUM_IRQ_BITS : natural := IRQ_BIT + 1;
393 
394  constant TRIGGER_IRQ_REGISTER : RegisterLocation := init( "trigger_irq", REG_COMPONENT_START_ADDR+toInt(x"06"), NUM_IRQ_BITS, RW_REG_CFG );
396 
405  constant LEVEL_IRQ_STATUS_REGISTER : RegisterLocation := init( "level_irq_status", toInt(x"08"), NUM_IRQ_BITS, LEVEL_IRQ_REG_CFG );
407 
415  constant LEVEL_IRQ_MASK_REGISTER : RegisterLocation := init( "level_irq_mask", toInt(x"09"), NUM_IRQ_BITS, STD_IRQ_MASK_REG_CFG );
417 
425  constant FALLING_EDGE_IRQ_STATUS_REGISTER : RegisterLocation := init( "falling_edge_irq_status", toInt(x"0A"), NUM_IRQ_BITS, FALLING_EDGE_IRQ_REG_CFG );
427 
429  constant COMPONENT_REG_LOCATIONS : RegisterLocationArray := ( CONTROL_REGISTER,
434  FLAGS_REGISTER,
439 
440  -- If for some reason, only 1 RegisterLocation is desired, the syntax would be as follows:
441  --constant COMPONENT_REG_LOCATIONS : RegisterLocationArray := (0 => CONTROL_REGISTER);
442 
443  ---------------------------
444  -- Register Bank Setup
445  ---------------------------
446 
447  -- NOTE: All the standard addresses are defined in RegisterPkg.vhd
448 
449  -- UPDATE THE COMPONENT VERSION NUMBER...
451  constant VERSION : natural := 3;
452 
459 
460  constant STD_REG_LOC_CFG : StandardRegisterLocationsConfig := init(ID_EXAMPLE_COMPONENT, VERSION, RISING_EDGE_IRQ, NUM_IRQ_BITS);
461 
463 
464  ---------------------------
465  -- FIFO Configuration
466  ---------------------------
467 
469  constant FIFO_DEPTH : natural := 8;
470 
472  constant FIFO_IN_FIFO_INFO : FIFOInfo := ( FIFO_TYPE => RAM_SINGLE_RATE_FIFO,
473  DEPTH => FIFO_DEPTH,
474  WR_ALMOST_FULL_CNT => FIFO_DEPTH-1,
475  WR_ALMOST_EMPTY_CNT => FIFO_REMOVE_COUNT,
476  RD_ALMOST_FULL_CNT => FIFO_REMOVE_COUNT,
477  RD_ALMOST_EMPTY_CNT => 1,
478  SHOW_AHEAD => true );
479 
481  constant FIFO_OUT_FIFO_INFO : FIFOInfo := init( RAM_SINGLE_RATE_FIFO, FIFO_DEPTH );
482 
483  ---------------------------
484  -- Signal Declarations
485  ---------------------------
486 
487  -- Reset Signals
488  signal reset_in : std_logic;
489  signal data_reset : std_logic;
490 
491  -- Custom Registers
492  signal control_bit : std_logic;
493  signal control_field : std_logic_vector(SOME_CTRL_RANGE);
494 
495  -- Write clear signals
496  signal load : std_logic;
497  signal pause : std_logic;
498 
499  signal count_init : std_logic_vector(REG_DATA_RANGE);
500  signal count_step : std_logic_vector(REG_DATA_RANGE);
501 
502  -- Read Clear Signals
503  signal clear_flags : std_logic;
504  signal flags : std_logic_vector(REG_DATA_RANGE);
505 
506  -- IRQ example signal
507  signal irq_flag : std_logic;
508 
509  -- Register Bank Signals
510  signal reg_ctrl : RegisterControlIntf;
511  signal reg_status : RegisterStatusIntf;
512 
513  -- Input FIFO signals
514  signal fifo_in_status : AvalonMMSlaveToFabricIntf;
515  signal fifo_in_data_out : AvalonSTSourceToSinkIntf;
516  signal fifo_in_data_out_rsp : AvalonSTSinkToSourceIntf;
517 
518  -- Output FIFO signals
519  signal fifo_out_data_in : AvalonSTSourceToSinkIntf;
520  signal fifo_out_data_in_rsp : AvalonSTSinkToSourceIntf;
521 
522  ---------------------------
523  -- Dump XML
524  ---------------------------
525 
526  -- synthesis translate_off
527  use work.ctype_h.all;
528  use work.strings_h.all;
529  use work.stdio_h.all;
530 
531  impure function dump_xml return boolean is
532  constant NAME : string := ExampleComponent'path_name;
533  constant FILE_NAME : FileName := init( "project_config.xml" );
534  variable xml_file : CFILE;
535  begin
536  xml_file := fopen(FILE_NAME, "a");
537 
538  if( xml_file = 0 ) then
539  report "ERROR: ExampleComponent.vhd - Cannot Open XML File " & FILE_NAME
540  severity failure;
541  end if;
542 
543  fprintf(xml_file, "<ComponentInfo type=%s name=%s>\n", addQuotes("ExampleComponent"), addQuotes(NAME) );
544  fprintf(xml_file, "%s", getXML("data_in_info", DATA_IN_INFO));
545  fprintf(xml_file, "%s", getXML("data_out_info", DATA_OUT_INFO));
546  fprintf(xml_file, "</ComponentInfo>\n");
547 
548  fclose(xml_file);
549 
550  return true;
551  end function;
552 
553  constant DUMP_XML_FILES : boolean := dump_xml;
554  -- synthesis translate_on
555 
556 --------------------------------------------------------------------------------
557 begin
558 --------------------------------------------------------------------------------
559 
560  ------------------------------------------------------------------------------
561  -- Component Assertions
562  ------------------------------------------------------------------------------
563 
564  -- Example Assert
565  assert( true ) report "ExampleComponent.vhd - Message goes here..." severity error;
566 
567  assert( DATA_IN_INFO.PROFILE = AVALON_ST_TYPICAL )
568  report "ExampleComponent.vhd - Input profile must be AVALON_ST_TYPICAL"
569  severity failure;
570 
571  assert( DATA_OUT_INFO.PROFILE = AVALON_ST_TYPICAL )
572  report "ExampleComponent.vhd - Output profile must be AVALON_ST_TYPICAL"
573  severity failure;
574 
575  ------------------------------------------------------------------------------
576  example_gen : if( false ) generate
577  ------------------------------------------------------------------------------
578  -- generate specific declarations here...
579  begin
580 
581  -- This isn't needed for this example, but here is how you do one...
582 
583  ------------------------------------------------------------------------------
584  end generate;
585  ------------------------------------------------------------------------------
586 
587  ------------------------------------------------------------------------------
588  -- Register Bank
589  ------------------------------------------------------------------------------
590 
591  register_bank_map : RegisterBank
592  generic map (
593  BOARD_INFO => BOARD_INFO,
594  REGISTER_BANK_INFO => REGISTER_BANK_INFO
595  )
596  port map (
597  -- Avalon-MM Slave Interfaces
598  slaveClk => slaveClk ,
599  slaveReset => slaveReset,
600  slaveIRQ => slaveIRQ ,
601  slaveIn => slaveIn,
602  slaveInRsp => slaveInRsp,
603  -- Register Interface
604  regClk => dataClk ,
605  regReset => dataReset,
606  regCtrl => reg_ctrl ,
607  regStatus => reg_status
608  );
609 
610  ------------------------------------------------------------------------------
611  -- Register Soft Reset
612  ------------------------------------------------------------------------------
613 
614  -- Please don't use the soft reset to reset the RegisterBank slave
615  -- or register interface. It won't work, I PROMISE!
616 
617  reset_in <= dataReset or reg_ctrl.reset;
618 
619  -- We don't want to drive reset lines with combinational logic
620  -- In this case, resets are already synchronized, just register the signal.
621  -- If we needed to synch to a different clock domain, this
622  -- soft reset component will come in handy.
623  soft_reset_map : SoftReset
624  generic map (
625  -- Min Cycles to Hold Reset
626  DELAY => 1
627  )
628  port map (
629  clk => dataClk,
630  arst => reset_in ,
631  srst => data_reset
632  );
633 
634  ------------------------------------------------------------------------------
635  -- Register Control
636  ------------------------------------------------------------------------------
637 
638  -- NOTE:
639  -- If data and mem clocks are not the same, this will perform a retime and
640  -- ease up on timing constraints. Anything critical requires a fifo
641  -- for retiming. Especially on the readback side.
642  -- The best method for retiming a control signal is to have the master
643  -- drive all the configuration registers and then set a single bit
644  -- to latch in the update using a the read and write pulse/clear register access
645  -- modes. The standard register bank will automaticically retime those flags.
646 
648  reg_ctrl_prc : process( dataClk )
649  begin
650  if( dataClk'event and dataClk = '1' ) then
651  if( data_reset = '1' ) then
652  -- If necessary, clear the control signals here...
653  control_bit <= '0';
654  control_field <= (others => '0');
655  load <= '0';
656  pause <= '0';
657  count_init <= (others => '0');
658  count_step <= (others => '0');
659  clear_flags <= '0';
660  irq_flag <= '0';
661  else
662  -- Some example read/write registers. One could also use the
663  -- getValue functions defined in RegisterPkg.vhd
664  control_bit <= reg_ctrl.memory(getAddr(CONTROL_REGISTER))(A_CTRL_BIT);
665  control_field <= reg_ctrl.memory(CONTROL_REGISTER.ADDR)(control_field'range);
666  -- OR: control_field <= reg_ctrl.memory(getAddr(CONTROL_REGISTER))(SOME_CTRL_RANGE);
667  -- OR: control_field <= getValue( reg_ctrl, getAddr(CONTROL_REGISTER), control_field );
668  -- OR: control_field <= getValue( reg_ctrl, getAddr(CONTROL_REGISTER), control_field'length, control_field'low );
669 
670  -- Next is a block of configuration registers that should only be updated once.
671  -- For instace, with a write clear register. In this case, we will allow
672  -- the host to write all the configs and then set a load bit to latch in the new config.
673  -- This can be done with a write pulse also, in which case the last register written
674  -- to triggers a pulse, to indicate the data write is completed.
675  -- With a write clear, the flag will be cleared so that it is only active for
676  -- a single cycle. Be sure to set the access mode to write clear.
677  -- The write clear type register can also be used to latch status, increment
678  -- a counter, write a fifo, or...
679  -- The register bank will automatically retime the flags from the slave clock
680  -- to the register interface clock in standard mode.
681  load <= '0';
682  if( getFlag(reg_ctrl, COUNT_CONFIG_REGISTER) = '1' ) then
683  load <= getValue( reg_ctrl, COUNT_CONFIG_REGISTER, LOAD_BIT );
686 
687  -- In some cases, you may want to latch a write clear register. In that case,
688  -- check the write clear flag and then grab your data. Be careful doing this
689  -- with a bus though because all the bits might not be stable crossing clock
690  -- domains...if you aren't using the standard register bank. Always best with
691  -- a single bit.
692  -- Latch the bit only when the register is written,
694  end if;
695 
696  -- Any of the read clear registers implemented should have an associated
697  -- flag that gets set when the address is read. The register bank
698  -- feeds back a flag so that the component knows to perform the clear.
699  --clear_flags <= reg_ctrl.flags(FLAGS_REGISTER.ADDR);
700  -- OR
701  clear_flags <= getFlag(reg_ctrl, FLAGS_REGISTER);
702  -- OR
703  -- One could even check another register when the flag is set and
704  -- use that to determine if some flags should be cleared or not.
705  --clear_flags <= getValue( reg_ctrl, CLEAR_CTRL_REGISTER, CLEAR_FLAGS_BIT );
706 
707  -- This register is used to set the IRQ bits as an example
709 
710  end if;
711  end if;
712  end process;
713 
714  ------------------------------------------------------------------------------
715  -- Register Status
716  ------------------------------------------------------------------------------
717 
719  reg_stat_prc : process( dataClk )
720  begin
721  -- This process doesn't need to be clocked if slaveClk = dataClk but it won't do
722  -- anything but add a cycle of latency over a slow status interface anyways.
723  -- Don't forget to somehow clear the status on reset.
724  if( dataClk'event and dataClk = '1' ) then
725  if( data_reset = '1' ) then
726  reg_status <= initRegisterStatusIntf;
727  else
728  -- Custom Component Registers
729  reg_status.memory(STATUS_REGISTER.ADDR)(ALMOST_FULL_BIT) <= fifo_in_status.readdata(FIFO_WR_ALMOST_FULL_BIT);
730  reg_status.memory(STATUS_REGISTER.ADDR)(FULL_BIT) <= fifo_in_status.readdata(FIFO_WR_FULL_BIT);
731  reg_status.memory(STATUS_REGISTER.ADDR)(ALMOST_EMPTY_BIT) <= fifo_in_status.readdata(FIFO_RD_ALMOST_EMPTY_BIT);
732  reg_status.memory(STATUS_REGISTER.ADDR)(EMPTY_BIT) <= fifo_in_status.readdata(FIFO_RD_EMPTY_BIT);
733 
734  -- Below is an example read clear register. Basically, each time a register of this type
735  -- is read, the register bank will send us a flag letting us know. When the flag is seen,
736  -- that is a trigger to clear the internal component register. The read clear can be
737  -- used for flags, interrupts, or any other type of transaction with a desired read and
738  -- clear. The control process is used to check the read clear flag.
739  -- A similar register access mode is the read pulse, however, the register need not be
740  -- cleared on the pulse.
741  setValue( reg_status, FLAGS_REGISTER, flags );
742 
743  -- Set the IRQ status register bits using a procedure.
744  setIRQ(reg_status, IRQ_BIT, irq_flag);
747  end if;
748  end if;
749  end process;
750 
751  ------------------------------------------------------------------------------
752  -- Counter Process
753  ------------------------------------------------------------------------------
754 
755  reg_clr_prc : process( dataClk )
756  variable cnt : natural;
757  variable done : boolean;
758  constant INIT_CNT: natural := 10;
759  begin
760  if( dataClk'event and dataClk = '1' ) then
761  if( data_reset = '1' ) then
762  cnt := INIT_CNT;
763  done := true;
764  flags <= (others => '0');
765  elsif( pause = '0' ) then
766 
767  -- When we see the clear flag read event, clear the
768  -- flags register.
769  if( load = '1' or clear_flags = '1' ) then
770  flags <= (others => '0');
771  end if;
772 
773  -- Looks like we got a load event
774  if( load = '1' ) then
775  cnt := toInt(count_init);
776  done := false;
777  end if;
778 
779  -- Set the flags when our counter is done to create some
780  -- status.
781  if( done = false and cnt = 0 ) then
782  flags <= (others => '1');
783  done := true;
784  end if;
785 
786  if( done = false ) then
787  cnt := cnt - toInt(count_step);
788  end if;
789 
790  end if;
791  end if;
792  end process;
793 
794  ------------------------------------------------------------------------------
795  -- Input FIFO
796  ------------------------------------------------------------------------------
797 
798  -- FIFO is used for flow control. If a depth of more than 16 or so
799  -- is required, you would go to a RAM based FIFO...
800  -- The single rate fifo is register based so you don't always want to use it.
801  -- HINT: using a fifo on the input makes avalon backpressure easier to implement
802  -- without dropping data at certain times, so it is not recommeneded to
803  -- take the fifo out.
804  fifo_in_map : FIFO
805  generic map (
806  BOARD_INFO => BOARD_INFO,
807  REG_BANK_CFG => SMALL_REG_BANK_CONFIG,
808  -- Avalon-ST Parameters
809  DATA_INFO => DATA_IN_INFO ,
810  -- FIFO Parameters
811  FIFO_INFO => FIFO_IN_FIFO_INFO
812  )
813  port map (
814  -- Avalon-MM Slave Interfaces
815  slaveInRsp => fifo_in_status ,
816  -- Avalon-ST Input Interface
817  dataInClk => dataClk ,
818  dataInReset => data_reset,
819  dataIn => dataIn ,
820  dataInRsp => dataInRsp,
821  -- Avalon-ST Output Interface
822  dataOutClk => dataClk ,
823  dataOutReset => data_reset,
824  dataOut => fifo_in_data_out ,
825  dataOutRsp => fifo_in_data_out_rsp
826  );
827 
828  ------------------------------------------------------------------------------
829  -- Processing Code and Output Combined
830  ------------------------------------------------------------------------------
831 
832  -- Apply back pressure when output is not ready
834  when (data_reset = '0' and reg_ctrl.enable = '1')
835  else '0';
836 
837  -- Let's do something here.
838  -- Assume that SYMBOLS_PER_BEAT is equal to one to avoid a data reshape.
839  -- In some components the data may need to be reshaped. Usually in multi-rate components.
840  -- Also assuming AVALON_ST_TYPICAL profile.
841  --
842  -- NOTE: This process was implemented specifically for communication with an output
843  -- data FIFO. Otherwise, this code would violate the Avalon spec. It utilizes the
844  -- response ready flag as a FIFO not empty flag. Following the Avalon spec,
845  -- it is required that the valid is NOT set conditional on the ready when the ready
846  -- latency is set to zero. Valid should typically be independent of ready.
847  do_prc : process( dataClk )
848  variable disable_while_valid : boolean;
849  begin
850  if( dataClk'event and dataClk = '1' ) then
851  if( data_reset = '1' ) then
852  fifo_out_data_in <= initAvalonSTSourceToSinkIntf;
853  disable_while_valid := false;
854  elsif( reg_ctrl.enable = '1' ) then
855 
856  -- At this point, a few conditions could have occured.
857  -- 1. We set valid on the previous cycle and it was accepted.
858  -- 2. We set valid on the previous cycle and it was not accepted.
859  -- 3. We didn't send data at all on the previous cycle
860 
861  -- Check the disable flag to help us restart
862  if( disable_while_valid = true ) then
863  fifo_out_data_in.valid <= '1';
864  disable_while_valid := false;
865 
866  -- The sink was ready to accept data on the previous cycle
867  elsif( fifo_out_data_in_rsp.ready = '1' ) then
868 
869  -- Condition #1
870  -- Condition #3
871  -- Either way, transfer the next data point. This is where our
872  -- signal processing would occur.
873  fifo_out_data_in.valid <= fifo_in_data_out.valid;
875 
876  -- The sink was not ready to accept data on the previous cycle
877  else
878 
879  -- Condition #2
880  if( fifo_out_data_in.valid = '1' ) then
881  -- Hold right where we are
882  fifo_out_data_in.valid <= '1';
883  -- Condition #3
884  else
885  -- Don't do anything once again. But you can present
886  -- the next data here if you want to stick to the
887  -- Avalon spec.
888  fifo_out_data_in.valid <= '0';
889  end if;
890 
891  end if;
892 
893  else
894  -- The component is disabled so stop all transfers
895  fifo_out_data_in.valid <= '0';
896 
897  -- Set a disable flag if the data was not accepted
898  if( fifo_out_data_in.valid = '1' and fifo_out_data_in_rsp.ready = '0' ) then
899  disable_while_valid := true;
900  end if;
901 
902  end if;
903 
904  end if;
905  end process;
906 
907  ------------------------------------------------------------------------------
908  -- Output FIFO
909  ------------------------------------------------------------------------------
910 
911  fifo_out_map : FIFO
912  generic map (
913  BOARD_INFO => BOARD_INFO,
914  -- Avalon-ST Parameters
915  DATA_INFO => DATA_OUT_INFO,
916  -- FIFO Parameters
917  FIFO_INFO => FIFO_OUT_FIFO_INFO
918  )
919  port map (
920  -- Avalon-ST Input Interface
921  dataInClk => dataClk ,
922  dataInReset => data_reset,
923  dataIn => fifo_out_data_in ,
924  dataInRsp => fifo_out_data_in_rsp,
925  -- Avalon-ST Output Interface
926  dataOutClk => dataClk ,
927  dataOutReset => data_reset,
928  dataOut => dataOut ,
929  dataOutRsp => dataOutRsp
930  );
931 
932 --------------------------------------------------------------------------------
933 end architecture;
934 --------------------------------------------------------------------------------