Commit 98ee9d29 authored by egousiou's avatar egousiou

svec tdc working version (changes in acam_databus_interface.vhd)

git-svn-id: http://svn.ohwr.org/fmc-tdc@112 85dfdc96-de2c-444c-878d-45b388be74a9
parent 6b8ec841
User Configuration
-------------------------------------
Algorithm : Minimum_Area
Memory Type : True_Dual_Port_RAM
Port A Read Width : 128
Port B Read Width : 32
Port A Write Width : 128
Port B Write Width : 32
Memory Depth : 256
--------------------------------------------------------------
Block RAM resource(s) (9K BRAMs) : 0
Block RAM resource(s) (18K BRAMs) : 4
--------------------------------------------------------------
Clock A Frequency : 100
Port A Enable Rate : 100
Port A Write Rate : 50
----------------------------------------------------------
Estimated Power for IP : 11.020496 mW
----------------------------------------------------------
I found the code quite clear, even if there are not many comments.
------------------------------------------
data_engine, data_formatting and circular_buffer
------------------------------------------
I would suggest a bit cleaner names for the WBs:
stb/ack/.. in the data_engine could be renamed to acam_stb/ acam_ack..
stb/ack/.. in the data_formatting could be renamed to internal_stb/ internal_ack..
classic_stb/ classic_ack/.. in the circular_buffer could be renamed to gnum_classic_stb/ gnum_classic_ack..
pipe_stb/ pipe_ack/.. in the circular_buffer could be renamed to gnum_pipe_stb/ gnum_pipe_ack..
one_hz_gen and acam_timecontrol_interface
------------------------------------------
synchronization and edge detection of refclk takes place in both units
one_hz_gen lines 153-170; acam_timecontrol_interface lines 240-258
refclk_edge is a pulse (refclk_edge_p)
use of the first DFF s_acam_refclk(3) should be avoided
acam_timecontrol_interface
------------------------------------------
lines 260: start_trig_edge is a pulses (_p)
use of the first DFF (start_trig_r(2)) should be avoided
lines 120-146 : good!-)
acam_databus_interface
------------------------------------------
lines 227-241: signals ef1/2, lf1/2 shouldn t be synchronized as well (use one more DFF)?
acam_databus_interface and circular_buffer
------------------------------------------
The ack signals are pulses (_p)
acam_databus_interface, ack, line 63
circular_buffer, classic_ack, line 123
circular_buffer
------------------------------------------
lines 37, 50: class_clk_i and pipe_clk_i are actually the same clock; maybe they could just be named gnum_clk_i
Disclaimer: not enough time to do this design justice. Looking at VHDL
constructs independently, not trying to make sense of the design as a
whole.
top_tdc.vhd
===========
- Line 1057 (and others). The wait until spec_clk = '1'; at the end of
the process looks awkward to me. I guess it means this is a
synchronous process working on the rising edge of spec_clk. Is there
any advantage to using this notation?
acam_databus_interface.vhd
==========================
- Line 73. "read" and "write" are not VHDL reserved words but they are
names of functions people use to do I/O. Probably wise to chose
other names for states.
- Line 244. address_o going to the ACAM is not registered. This signal
is driven by adr_i, the wishbone input address. These lines are
being used in another entity (data_engine.vhd) as inputs to other
processes so chances are they will not use IOB FFs, which might be
important to respect setup and hold constraints of the ACAM.
acam_timecontrol_interface.vhd
==============================
- Line 246 (and others). This can be written in one line:
"start_trig_r <= start_trig & start_trig_r(1 downto 0);"
- Line 255 (and others). This edge detector uses signal ref_clk_r(3),
which is potentially metastable. It also relies very heavily on the
fact that ref_clk should be at a given frequency.
clk_rst_managr.vhd
==================
Line 284. This process can create metastability in signal gral_incr,
which is then going to many destinations inside the incr_counter
block, possibly leading to non-deterministic behavior of the counter.
Line 309. Signal cs seems to be negative logic. This should be visible
in its name.
Line 571. cs will not use an IOB FF because it is read in line
366. Please check all other cases when this can happen.
one_hz_gen.vhd
==============
Line 153. Similar comments on metastability as before. Also, the
assumption on the clock frequency of s_acam_refclk is very strong and
might be in trouble if sampling happens close to the edges and the
signals are a bit jittery. Why is this "frequency test" needed?
Summary of all the comments to the code by authors.
General:
========
TOM
- Wait statements in synthesizable code look suspicious...
They indeed synthesize correctly, but to be honest, I've never seen processes
coded in such way.
- (googled a bit) Technically, it should be "wait until rising_edge(clk)" or
" wait until (clk'event and clk = '1')".
- Are I/O always assigned to internal signals for some particular reason?
- I'd suggest declaring commonly used components (e.g. counters) in a shared
package to avoid repetitive declarations.
- Clock signal assignments are dangerous.
On a simulation, there is a big risk of getting timing errors when co-simulated
with Verilog code due to incompatibilities between the way events are
scheduled in VHDL and Verilog simulators
(in VHDL, a continuous assignment is scheduled as an event, while in verilog
it's purely continous).
top_tdc.vhd
===========
JAVIER
- Line 1057 (and others). The wait until spec_clk = '1'; at the end of
the process looks awkward to me. I guess it means this is a
synchronous process working on the rising edge of spec_clk. Is there
any advantage to using this notation?
TOM
- what are g_span and g_width generics (a comment would be helpful)
- gnum_reset signal is asynchronous, but used throughout the design as
synchronous. Add a sync chain.
- put together all the components which form the TDC core into a single VHDL
entity, with the ACAM I/F on one side and Wishbone on other side
(i.e. without the gennum or other platform-specific stuff inside)
- lines 1024, 1039: when decoding addresses, define base addrs as constants
instead of using hardcoded values
acam_databus_interface.vhd
==========================
JAVIER
- Line 73. "read" and "write" are not VHDL reserved words but they are
names of functions people use to do I/O. Probably wise to chose
other names for states.
- Line 244. address_o going to the ACAM is not registered. This signal
is driven by adr_i, the wishbone input address. These lines are
being used in another entity (data_engine.vhd) as inputs to other
processes so chances are they will not use IOB FFs, which might be
important to respect setup and hold constraints of the ACAM.
TOM
- line 192: these signals (efX, lfX) are asynchronous. I'd suggest using a
sync chain of 2-3 flip-flops.
EVA
- lines 227-241: signals ef1/2, lf1/2 shouldn t be synchronized as well
(use one more DFF)?
- The ack signals are pulses (_p)
acam_databus_interface, ack, line 63
acam_timecontrol_interface.vhd
==============================
JAVIER
- Line 246 (and others). This can be written in one line:
"start_trig_r <= start_trig & start_trig_r(1 downto 0);"
- Line 255 (and others). This edge detector uses signal ref_clk_r(3),
which is potentially metastable. It also relies very heavily on the
fact that ref_clk should be at a given frequency.
TOM
- line 89: the name doesn't explain the purpose of this constant. What delay
does it describe?
- line 125: are you sure this will work correctly? err_flag_r(2) is written
twice.
How about using slice & join instead?
err_flag_r <= err_flag_r(err_flag_r'left-1 downto 0) & err_flag_i;
- line 249: acam_refclk and clk are normally phase aligned by the AD9516 PLL,
so there may be a setup time violation here. Is the AD9516 shifter programmed
to ensure the FPGA will correctly sample acam_refclk signal?
(otherwise, the 1st stage could sample on the falling edge of clk).
- line 255: refclk_r(3) can be metastable, causing refclk_edge signal to be
unreliable.
Consider adding 1 more sync stage (or using only (1) and (0) indices)
- line 260: the same for start_trig_edge
EVA
- synchronization and edge detection of refclk takes place in both units
one_hz_gen lines 153-170; acam_timecontrol_interface lines 240-258
refclk_edge is a pulse (refclk_edge_p)
use of the first DFF s_acam_refclk(3) should be avoided
- lines 260: start_trig_edge is a pulses (_p)
use of the first DFF (start_trig_r(2)) should be avoided
- lines 120-146 : good!-)
clk_rst_managr.vhd
==================
JAVIER
- Line 284. This process can create metastability in signal gral_incr,
which is then going to many destinations inside the incr_counter
block, possibly leading to non-deterministic behavior of the counter.
- Line 309. Signal cs seems to be negative logic. This should be visible
in its name.
- Line 571. cs will not use an IOB FF because it is read in line
366. Please check all other cases when this can happen.
TOM
- line 166: IBUFDS + BUFG can be merged into single IBUFGDS
- line 225: chain of two global buffers on spec_clk_i
(IBUFG drives a global clock net, so there's no need to follow it with another
BUFG)
- lines 409+: I'd suggest defining these regs as an array of records?
- lines 289+: I couldn't understand the way the power-on-reset is generated.
A comment would be greatly appreciated.
one_hz_gen.vhd
==============
JAVIER
- Line 153. Similar comments on metastability as before. Also, the
assumption on the clock frequency of s_acam_refclk is very strong and
might be in trouble if sampling happens close to the edges and the
signals are a bit jittery. Why is this "frequency test" needed?
TOM
- lines 161+: you're syncing the same signal (tdc refclock) twice in the design
(here and in acam_timecontrol_interface). Due to possible metastability,
you can get inconsistent pulses in these two modules.
EVA
synchronization and edge detection of refclk takes place in both units
one_hz_gen lines 153-170; acam_timecontrol_interface lines 240-258
refclk_edge is a pulse (refclk_edge_p)
use of the first DFF s_acam_refclk(3) should be avoided
data_engine
===========
TOM
- state names look like signal names, consider using uppercase or prefixes to
avoid confusion.
- line 294: is the others block ever reached?
- define addresses of commonly used ACAM regs as constants
(e.g. c_ACAM_IFIFO1 for x"08", etc...) to improve readability.
EVA
- I would suggest a bit cleaner names for the WBs:
stb/ack/.. in the data_engine could be renamed to
acam_stb/ acam_ack..
circular_buffer
===============
TOM
- pipelined WB is not that complex, there's no need for an FSM.
In case of a non-stalling peripheral (stall == 0 always), the ack signal can
be generated like this:
process(clk)
ack <= stb and cyc;
(adr and dat go straight to the block ram).
- Consider replacing Coregen cores with generic ones. The circular buffer can
be done as a simple array.
EVA
- I would suggest a bit cleaner names for the WBs:
classic_stb/ classic_ack/.. in the circular_buffer renamed to
gnum_classic_stb/ gnum_classic_ack..
pipe_stb/ pipe_ack/.. in the circular_buffer renamed to
gnum_pipe_stb/ gnum_pipe_ack..
- lines 37, 50: class_clk_i and pipe_clk_i are actually the same clock;
maybe they could just be named gnum_clk_i
- The ack signals are pulses (_p)
circular_buffer, classic_ack, line 123
countdown_counter:
free_counter:
incr_counter:
=============
TOM
- line 49, 52: (un)signeds can be compared with integers directly
(numeric_std supports this).
if (value = 0) ...
- coding style (_i suffix for inputs, etc.).
reg_ctrl:
=========
- use constants for defining register adresses
- line 135+: avoid repetitive assignments. Use loop construct instead.
- line 126+: reg_ack <= reg_stb and reg_cyc and not reg_ack;
tdc_core_pkg:
============
- lines 73+: consider defining these constants in decimal format
(these are timeouts, and in decimal they are easier to understand).
sim/
----------------
- Try to avoid uploading binary files if they are not absolutely necessary
(i.e. compiled Xilinx libraries).
- A system-level testbench should be provided (tb_tdc.vhd doesn't include
any actual testbench code, just the models connected together).
Disclaimer. I didn't have too much time to review. Apologize for eventual typos or errors in my comments.
T.
General:
------------------
- Wait statements in synthesizable code look suspicious... They indeed synthesize correctly, but to be honest, I've never seen processes coded in such way.
- (googled a bit) Technically, it should be "wait until rising_edge(clk)" or "wait until (clk'event and clk = '1')".
- Are I/O always assigned to internal signals for some particular reason?
- I'd suggest declaring commonly used components (e.g. counters) in a shared package to avoid repetitive declarations.
- Clock signal assignments are dangerous. On a simulation, there is a big risk of getting timing errors when co-simulated with Verilog code due to incompatibilities between the way events are scheduled in VHDL and Verilog simulators (in VHDL, a continuous assignment is scheduled as an event, while in verilog it's purely continous).
acam_databus_interface:
-------------------------
- line 192: these signals (efX, lfX) are asynchronous. I'd suggest using a sync chain of 2-3 flip-flops.
acam_timecontrol_interface:
----------------------------
- line 89: the name doesn't explain the purpose of this constant. What delay does it describe?
- line 125: are you sure this will work correctly? err_flag_r(2) is written twice.
How about using slice & join instead?
err_flag_r <= err_flag_r(err_flag_r'left-1 downto 0) & err_flag_i;
- line 249: acam_refclk and clk are normally phase aligned by the AD9516 PLL, so there may be a setup time violation here. Is the AD9516 shifter programmed to ensure the FPGA will correctly sample acam_refclk signal? (otherwise, the 1st stage could sample on the falling edge of clk).
- line 255: refclk_r(3) can be metastable, causing refclk_edge signal to be unreliable. Consider adding 1 more sync stage (or using only (1) and (0) indices)
- line 260: the same for start_trig_edge
circular_buffer:
-------------------------
- pipelined WB is not that complex, there's no need for an FSM.
In case of a non-stalling peripheral (stall == 0 always), the ack signal can be generated like this:
process(clk)
ack <= stb and cyc;
(adr and dat go straight to the block ram).
- Consider replacing Coregen cores with generic ones. The circular buffer can be done as a simple array.
clk_rst_managr:
---------------------------
- line 166: IBUFDS + BUFG can be merged into single IBUFGDS
- line 225: chain of two global buffers on spec_clk_i (IBUFG drives a global clock net, so there's no need to follow it with another BUFG)
- lines 409+: I'd suggest defining these regs as an array of records?
- lines 289+: I couldn't understand the way the power-on-reset is generated. A comment would be greatly appreciated.
countdown_counter:
free_counter:
incr_counter:
-----------------------
- line 49, 52: (un)signeds can be compared with integers directly (numeric_std supports this).
if (value = 0) ...
- coding style (_i suffix for inputs, etc.).
data_engine:
-----------------
- state names look like signal names, consider using uppercase or prefixes to avoid confusion.
- line 294: is the others block ever reached?
- define addresses of commonly used ACAM regs as constants (e.g. c_ACAM_IFIFO1 for x"08", etc...) to improve readability.
one_hz_counter:
-----------------
- lines 161+: you're syncing the same signal (tdc refclock) twice in the design (here and in acam_timecontrol_interface). Due to possible metastability, you can get inconsistent pulses in these two modules.
reg_ctrl:
-----------------
- use constants for defining register adresses
- line 135+: avoid repetitive assignments. Use loop construct instead.
- line 126+: reg_ack <= reg_stb and reg_cyc and not reg_ack;
tdc_core_pkg:
---------------------
- lines 73+: consider defining these constants in decimal format (these are timeouts, and in decimal they are easier to understand).
top_tdc:
---------------------
- what are g_span and g_width generics (a comment would be helpful)
- gnum_reset signal is asynchronous, but used throughout the design as synchronous. Add a sync chain.
- put together all the components which form the TDC core into a single VHDL entity, with the ACAM I/F on one side and Wishbone on other side (i.e. without the gennum or other platform-specific stuff inside)
- lines 1024, 1039: when decoding addresses, define base addrs as constants instead of using hardcoded values
sim/
----------------
- Try to avoid uploading binary files if they are not absolutely necessary (i.e. compiled Xilinx libraries).
- A system-level testbench should be provided (tb_tdc.vhd doesn't include any actual testbench code, just the models connected together).
coregen_ip
\ No newline at end of file
-------------------------------------------------------------------------------
-- Title : Parametrizable synchronous FIFO (Xilinx version)
-- Project : Generics RAMs and FIFOs collection
-------------------------------------------------------------------------------
-- File : generic_sync_fifo.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2011-01-25
-- Last update: 2012-07-03
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Single-clock FIFO.
-- - configurable data width and size
-- - "show ahead" mode
-- - configurable full/empty/almost full/almost empty/word count signals
-------------------------------------------------------------------------------
-- Copyright (c) 2011 CERN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-01-25 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
entity generic_sync_fifo is
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean := false;
-- Read-side flag selection
g_with_empty : boolean := true; -- with empty flag
g_with_full : boolean := true; -- with full flag
g_with_almost_empty : boolean := false;
g_with_almost_full : boolean := false;
g_with_count : boolean := false; -- with words counter
g_almost_empty_threshold : integer; -- threshold for almost empty flag
g_almost_full_threshold : integer; -- threshold for almost full flag
g_register_flag_outputs : boolean := true
);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
empty_o : out std_logic;
full_o : out std_logic;
almost_empty_o : out std_logic;
almost_full_o : out std_logic;
count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)
);
end generic_sync_fifo;
architecture syn of generic_sync_fifo is
component inferred_sync_fifo
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean;
g_with_empty : boolean;
g_with_full : boolean;
g_with_almost_empty : boolean;
g_with_almost_full : boolean;
g_with_count : boolean;
g_almost_empty_threshold : integer;
g_almost_full_threshold : integer;
g_register_flag_outputs : boolean);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
empty_o : out std_logic;
full_o : out std_logic;
almost_empty_o : out std_logic;
almost_full_o : out std_logic;
count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0));
end component;
begin -- syn
U_Inferred_FIFO : inferred_sync_fifo
generic map (
g_data_width => g_data_width,
g_size => g_size,
g_show_ahead => g_show_ahead,
g_with_empty => g_with_empty,
g_with_full => g_with_full,
g_with_almost_empty => g_with_almost_empty,
g_with_almost_full => g_with_almost_full,
g_with_count => g_with_count,
g_almost_empty_threshold => g_almost_empty_threshold,
g_almost_full_threshold => g_almost_full_threshold,
g_register_flag_outputs => g_register_flag_outputs)
port map (
rst_n_i => rst_n_i,
clk_i => clk_i,
d_i => d_i,
we_i => we_i,
q_o => q_o,
rd_i => rd_i,
empty_o => empty_o,
full_o => full_o,
almost_empty_o => almost_empty_o,
almost_full_o => almost_full_o,
count_o => count_o);
end syn;
files = [
"generic_dpram.vhd",
"generic_dpram_sameclock.vhd",
"generic_dpram_dualclock.vhd",
"generic_spram.vhd"
]
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.NUMERIC_STD.all;
use work.genram_pkg.all;
entity gc_shiftreg is
generic (
g_size : integer);
port (
clk_i : in std_logic;
en_i : in std_logic;
d_i : in std_logic;
q_o : out std_logic;
a_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0));
end gc_shiftreg;
architecture wrapper of gc_shiftreg is
component SRLC32E
port (
Q : out std_ulogic;
A : in std_logic_vector (4 downto 0);
CE : in std_ulogic;
CLK : in std_ulogic;
D : in std_ulogic);
end component;
signal a : std_logic_vector(4 downto 0);
signal sr : std_logic_vector(g_size-1 downto 0);
begin -- wrapper
assert (g_size <= 32) report "gc_shiftreg[xilinx]: forced SRL32 implementation can be done only for 32-bit or smaller shift registers" severity warning;
a <= std_logic_vector(resize(unsigned(a_i), 5));
gen_srl32 : if(g_size <= 32) generate
U_SRLC32 : SRLC32E
port map (
Q => q_o,
A => a,
CE => en_i,
CLK => clk_i,
D => d_i);
end generate gen_srl32;
gen_inferred : if(g_size > 32) generate
p_srl : process(clk_i)
begin
if rising_edge(clk_i) then
if en_i = '1' then
sr <= sr(sr'left - 1 downto 0) & d_i;
end if;
end if;
end process;
q_o <= sr(TO_INTEGER(unsigned(a_i)));
end generate gen_inferred;
end wrapper;
-------------------------------------------------------------------------------
-- Title : Parametrizable dual-port synchronous RAM (Xilinx version)
-- Project : Generics RAMs and FIFOs collection
-------------------------------------------------------------------------------
-- File : generic_dpram.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2011-01-25
-- Last update: 2012-03-16
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: True dual-port synchronous RAM for Xilinx FPGAs with:
-- - configurable address and data bus width
-- - byte-addressing mode (data bus width restricted to multiple of 8 bits)
-- Todo:
-- - loading initial contents from file
-- - add support for read-first/write-first address conflict resulution (only
-- supported by Xilinx in VHDL templates)
-------------------------------------------------------------------------------
-- Copyright (c) 2011 CERN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-01-25 1.0 twlostow Created
-- 2012-03-13 1.1 wterpstra Added initial value as array
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
use work.genram_pkg.all;
use work.memory_loader_pkg.all;
entity generic_dpram is
generic (
-- standard parameters
g_data_width : natural := 32;
g_size : natural := 16384;
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_init_value : t_generic_ram_init := c_generic_ram_nothing;
g_dual_clock : boolean := true;
g_fail_if_file_not_found : boolean := true
);
port (
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
-- Port A
clka_i : in std_logic;
bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
wea_i : in std_logic;
aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
da_i : in std_logic_vector(g_data_width-1 downto 0);
qa_o : out std_logic_vector(g_data_width-1 downto 0);
-- Port B
clkb_i : in std_logic;
bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
web_i : in std_logic;
ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
db_i : in std_logic_vector(g_data_width-1 downto 0);
qb_o : out std_logic_vector(g_data_width-1 downto 0)
);
end generic_dpram;
architecture syn of generic_dpram is
component generic_dpram_sameclock
generic (
g_data_width : natural;
g_size : natural;
g_with_byte_enable : boolean;
g_addr_conflict_resolution : string;
g_init_file : string;
g_init_value : t_generic_ram_init;
g_fail_if_file_not_found : boolean);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
wea_i : in std_logic;
aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
da_i : in std_logic_vector(g_data_width-1 downto 0);
qa_o : out std_logic_vector(g_data_width-1 downto 0);
bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
web_i : in std_logic;
ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
db_i : in std_logic_vector(g_data_width-1 downto 0);
qb_o : out std_logic_vector(g_data_width-1 downto 0));
end component;
component generic_dpram_dualclock
generic (
g_data_width : natural;
g_size : natural;
g_with_byte_enable : boolean;
g_addr_conflict_resolution : string;
g_init_file : string;
g_init_value : t_generic_ram_init;
g_fail_if_file_not_found : boolean);
port (
rst_n_i : in std_logic := '1';
clka_i : in std_logic;
bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
wea_i : in std_logic;
aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
da_i : in std_logic_vector(g_data_width-1 downto 0);
qa_o : out std_logic_vector(g_data_width-1 downto 0);
clkb_i : in std_logic;
bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
web_i : in std_logic;
ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
db_i : in std_logic_vector(g_data_width-1 downto 0);
qb_o : out std_logic_vector(g_data_width-1 downto 0));
end component;
begin
gen_single_clk : if(g_dual_clock = false) generate
U_RAM_SC: generic_dpram_sameclock
generic map (
g_data_width => g_data_width,
g_size => g_size,
g_with_byte_enable => g_with_byte_enable,
g_addr_conflict_resolution => g_addr_conflict_resolution,
g_init_file => g_init_file,
g_init_value => g_init_value,
g_fail_if_file_not_found => g_fail_if_file_not_found)
port map (
rst_n_i => rst_n_i,
clk_i => clka_i,
bwea_i => bwea_i,
wea_i => wea_i,
aa_i => aa_i,
da_i => da_i,
qa_o => qa_o,
bweb_i => bweb_i,
web_i => web_i,
ab_i => ab_i,
db_i => db_i,
qb_o => qb_o);
end generate gen_single_clk;
gen_dual_clk : if(g_dual_clock = true) generate
U_RAM_DC: generic_dpram_dualclock
generic map (
g_data_width => g_data_width,
g_size => g_size,
g_with_byte_enable => g_with_byte_enable,
g_addr_conflict_resolution => g_addr_conflict_resolution,
g_init_file => g_init_file,
g_init_value => g_init_value,
g_fail_if_file_not_found => g_fail_if_file_not_found)
port map (
rst_n_i => rst_n_i,
clka_i => clka_i,
bwea_i => bwea_i,
wea_i => wea_i,
aa_i => aa_i,
da_i => da_i,
qa_o => qa_o,
clkb_i => clkb_i,
bweb_i => bweb_i,
web_i => web_i,
ab_i => ab_i,
db_i => db_i,
qb_o => qb_o);
end generate gen_dual_clk;
end syn;
-------------------------------------------------------------------------------
-- Title : Parametrizable dual-port synchronous RAM (Xilinx version)
-- Project : Generics RAMs and FIFOs collection
-------------------------------------------------------------------------------
-- File : generic_dpram.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2011-01-25
-- Last update: 2012-03-28
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: True dual-port synchronous RAM for Xilinx FPGAs with:
-- - configurable address and data bus width
-- - byte-addressing mode (data bus width restricted to multiple of 8 bits)
-- Todo:
-- - loading initial contents from file
-- - add support for read-first/write-first address conflict resulution (only
-- supported by Xilinx in VHDL templates)
-------------------------------------------------------------------------------
-- Copyright (c) 2011 CERN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-01-25 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
use work.genram_pkg.all;
use work.memory_loader_pkg.all;
entity generic_dpram_dualclock is
generic (
-- standard parameters
g_data_width : natural := 32;
g_size : natural := 16384;
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_init_value : t_generic_ram_init := c_generic_ram_nothing;
g_fail_if_file_not_found : boolean := true
);
port (
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
-- Port A
clka_i : in std_logic;
bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
wea_i : in std_logic;
aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
da_i : in std_logic_vector(g_data_width-1 downto 0);
qa_o : out std_logic_vector(g_data_width-1 downto 0);
-- Port B
clkb_i : in std_logic;
bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
web_i : in std_logic;
ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
db_i : in std_logic_vector(g_data_width-1 downto 0);
qb_o : out std_logic_vector(g_data_width-1 downto 0)
);
end generic_dpram_dualclock;
architecture syn of generic_dpram_dualclock is
constant c_num_bytes : integer := (g_data_width+7)/8;
type t_ram_type is array(0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0);
function f_memarray_to_ramtype(arr : t_meminit_array) return t_ram_type is
variable tmp : t_ram_type;
variable n, pos : integer;
begin
pos := 0;
while(pos < g_size)loop
n := 0;
-- avoid ISE loop iteration limit
while (pos < g_size and n < 4096) loop
for i in 0 to g_data_width-1 loop
tmp(pos)(i) := arr(pos, i);
end loop; -- i
n := n+1;
pos := pos + 1;
end loop;
end loop;
return tmp;
end f_memarray_to_ramtype;
function f_file_contents return t_meminit_array is
begin
if g_init_value'length > 0 then
return g_init_value;
else
return f_load_mem_from_file(g_init_file, g_size, g_data_width, g_fail_if_file_not_found);
end if;
end f_file_contents;
shared variable ram : t_ram_type := f_memarray_to_ramtype(f_file_contents);
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0);
signal clka_int : std_logic;
signal clkb_int : std_logic;
signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0);
begin
wea_rep <= (others => wea_i);
web_rep <= (others => web_i);
s_we_a <= bwea_i and wea_rep;
s_we_b <= bweb_i and web_rep;
gen_with_byte_enable_readfirst : if(g_with_byte_enable = true and g_addr_conflict_resolution = "read_first") generate
process (clka_i)
begin
if rising_edge(clka_i) then
qa_o <= ram(to_integer(unsigned(aa_i)));
for i in 0 to c_num_bytes-1 loop
if s_we_a(i) = '1' then
ram(to_integer(unsigned(aa_i)))((i+1)*8-1 downto i*8) := da_i((i+1)*8-1 downto i*8);
end if;
end loop;
end if;
end process;
process (clkb_i)
begin
if rising_edge(clkb_i) then
qb_o <= ram(to_integer(unsigned(ab_i)));
for i in 0 to c_num_bytes-1 loop
if s_we_b(i) = '1' then
ram(to_integer(unsigned(ab_i)))((i+1)*8-1 downto i*8)
:= db_i((i+1)*8-1 downto i*8);
end if;
end loop;
end if;
end process;
end generate gen_with_byte_enable_readfirst;
gen_without_byte_enable_readfirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "read_first") generate
process(clka_i)
begin
if rising_edge(clka_i) then
qa_o <= ram(to_integer(unsigned(aa_i)));
if(wea_i = '1') then
ram(to_integer(unsigned(aa_i))) := da_i;
end if;
end if;
end process;
process(clkb_i)
begin
if rising_edge(clkb_i) then
qb_o <= ram(to_integer(unsigned(ab_i)));
if(web_i = '1') then
ram(to_integer(unsigned(ab_i))) := db_i;
end if;
end if;
end process;
end generate gen_without_byte_enable_readfirst;
gen_without_byte_enable_writefirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "write_first") generate
process(clka_i)
begin
if rising_edge(clka_i) then
if(wea_i = '1') then
ram(to_integer(unsigned(aa_i))) := da_i;
qa_o <= da_i;
else
qa_o <= ram(to_integer(unsigned(aa_i)));
end if;
end if;
end process;
process(clkb_i)
begin
if rising_edge(clkb_i) then
if(web_i = '1') then
ram(to_integer(unsigned(ab_i))) := db_i;
qb_o <= db_i;
else
qb_o <= ram(to_integer(unsigned(ab_i)));
end if;
end if;
end process;
end generate gen_without_byte_enable_writefirst;
gen_without_byte_enable_nochange : if(g_with_byte_enable = false and g_addr_conflict_resolution = "no_change") generate
process(clka_i)
begin
if rising_edge(clka_i) then
if(wea_i = '1') then
ram(to_integer(unsigned(aa_i))) := da_i;
else
qa_o <= ram(to_integer(unsigned(aa_i)));
end if;
end if;
end process;
process(clkb_i)
begin
if rising_edge(clkb_i) then
if(web_i = '1') then
ram(to_integer(unsigned(ab_i))) := db_i;
else
qb_o <= ram(to_integer(unsigned(ab_i)));
end if;
end if;
end process;
end generate gen_without_byte_enable_nochange;
end syn;
-------------------------------------------------------------------------------
-- Title : Parametrizable dual-port synchronous RAM (Xilinx version)
-- Project : Generics RAMs and FIFOs collection
-------------------------------------------------------------------------------
-- File : generic_dpram_sameclock.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2011-01-25
-- Last update: 2012-03-28
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: True dual-port synchronous RAM for Xilinx FPGAs with:
-- - configurable address and data bus width
-- - byte-addressing mode (data bus width restricted to multiple of 8 bits)
-- Todo:
-- - loading initial contents from file
-- - add support for read-first/write-first address conflict resulution (only
-- supported by Xilinx in VHDL templates)
-------------------------------------------------------------------------------
-- Copyright (c) 2011 CERN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-01-25 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
use work.genram_pkg.all;
use work.memory_loader_pkg.all;
entity generic_dpram_sameclock is
generic (
g_data_width : natural := 32;
g_size : natural := 16384;
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_init_value : t_generic_ram_init := c_generic_ram_nothing;
g_fail_if_file_not_found : boolean := true
);
port (
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
-- Port A
clk_i : in std_logic;
bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
wea_i : in std_logic;
aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
da_i : in std_logic_vector(g_data_width-1 downto 0);
qa_o : out std_logic_vector(g_data_width-1 downto 0);
-- Port B
bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
web_i : in std_logic;
ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
db_i : in std_logic_vector(g_data_width-1 downto 0);
qb_o : out std_logic_vector(g_data_width-1 downto 0)
);
end generic_dpram_sameclock;
architecture syn of generic_dpram_sameclock is
constant c_num_bytes : integer := (g_data_width+7)/8;
type t_ram_type is array(0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0);
function f_memarray_to_ramtype(arr : t_meminit_array) return t_ram_type is
variable tmp : t_ram_type;
variable n, pos : integer;
begin
pos := 0;
while(pos < g_size)loop
n := 0;
-- avoid ISE loop iteration limit
while (pos < g_size and n < 4096) loop
for i in 0 to g_data_width-1 loop
tmp(pos)(i) := arr(pos, i);
end loop; -- i
n := n+1;
pos := pos + 1;
end loop;
end loop;
return tmp;
end f_memarray_to_ramtype;
function f_file_contents return t_meminit_array is
begin
if g_init_value'length > 0 then
return g_init_value;
else
return f_load_mem_from_file(g_init_file, g_size, g_data_width, g_fail_if_file_not_found);
end if;
end f_file_contents;
shared variable ram : t_ram_type := f_memarray_to_ramtype(f_file_contents);
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0);
signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0);
begin
wea_rep <= (others => wea_i);
web_rep <= (others => web_i);
s_we_a <= bwea_i and wea_rep;
s_we_b <= bweb_i and web_rep;
gen_with_byte_enable_readfirst : if(g_with_byte_enable = true and g_addr_conflict_resolution = "read_first") generate
process (clk_i)
begin
if rising_edge(clk_i) then
qa_o <= ram(to_integer(unsigned(aa_i)));
qb_o <= ram(to_integer(unsigned(ab_i)));
for i in 0 to c_num_bytes-1 loop
if s_we_a(i) = '1' then
ram(to_integer(unsigned(aa_i)))((i+1)*8-1 downto i*8) := da_i((i+1)*8-1 downto i*8);
end if;
if(s_we_b(i) = '1') then
ram(to_integer(unsigned(ab_i)))((i+1)*8-1 downto i*8) := db_i((i+1)*8-1 downto i*8);
end if;
end loop;
end if;
end process;
end generate gen_with_byte_enable_readfirst;
gen_without_byte_enable_readfirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "read_first") generate
process(clk_i)
begin
if rising_edge(clk_i) then
qa_o <= ram(to_integer(unsigned(aa_i)));
qb_o <= ram(to_integer(unsigned(ab_i)));
if(wea_i = '1') then
ram(to_integer(unsigned(aa_i))) := da_i;
end if;
if(web_i = '1') then
ram(to_integer(unsigned(ab_i))) := db_i;
end if;
end if;
end process;
end generate gen_without_byte_enable_readfirst;
gen_without_byte_enable_writefirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "write_first") generate
process(clk_i)
begin
if rising_edge(clk_i) then
if(wea_i = '1') then
ram(to_integer(unsigned(aa_i))) := da_i;
qa_o <= da_i;
else
qa_o <= ram(to_integer(unsigned(aa_i)));
end if;
if(web_i = '1') then
ram(to_integer(unsigned(ab_i))) := db_i;
qb_o <= db_i;
else
qb_o <= ram(to_integer(unsigned(ab_i)));
end if;
end if;
end process;
end generate gen_without_byte_enable_writefirst;
gen_without_byte_enable_nochange : if(g_with_byte_enable = false and g_addr_conflict_resolution = "no_change") generate
process(clk_i)
begin
if rising_edge(clk_i) then
if(wea_i = '1') then
ram(to_integer(unsigned(aa_i))) := da_i;
else
qa_o <= ram(to_integer(unsigned(aa_i)));
end if;
if(web_i = '1') then
ram(to_integer(unsigned(ab_i))) := db_i;
else
qb_o <= ram(to_integer(unsigned(ab_i)));
end if;
end if;
end process;
end generate gen_without_byte_enable_nochange;
end syn;
-------------------------------------------------------------------------------
-- Title : Parametrizable dual-port synchronous RAM (Xilinx version)
-- Project : Generics RAMs and FIFOs collection
-------------------------------------------------------------------------------
-- File : generic_simple_dpram.vhd
-- Author : Wesley W. Terpstra
-- Company : GSI
-- Created : 2013-03-04
-- Last update: 2013-03-04
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: True dual-port synchronous RAM for Xilinx FPGAs with:
-- - configurable address and data bus width
-- - byte-addressing mode (data bus width restricted to multiple of 8 bits)
-- Todo:
-- - loading initial contents from file
-- - add support for read-first/write-first address conflict resulution (only
-- supported by Xilinx in VHDL templates)
-------------------------------------------------------------------------------
-- Copyright (c) 2011 CERN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2013-03-04 1.0 wterpstra Initial version: wrapper to generic_dpram
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
library work;
use work.genram_pkg.all;
use work.memory_loader_pkg.all;
entity generic_simple_dpram is
generic (
-- standard parameters
g_data_width : natural := 32;
g_size : natural := 16384;
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_dual_clock : boolean := true;
g_fail_if_file_not_found : boolean := true
);
port (
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
-- Port A
clka_i : in std_logic;
bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
wea_i : in std_logic;
aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
da_i : in std_logic_vector(g_data_width-1 downto 0);
-- Port B
clkb_i : in std_logic;
ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
qb_o : out std_logic_vector(g_data_width-1 downto 0)
);
end generic_simple_dpram;
architecture syn of generic_simple_dpram is
begin
-- Works well enough until a Xilinx guru can optimize it.
true_dp : generic_dpram
generic map(
g_data_width => g_data_width,
g_size => g_size,
g_with_byte_enable => g_with_byte_enable,
g_addr_conflict_resolution => g_addr_conflict_resolution,
g_init_file => g_init_file,
g_dual_clock => g_dual_clock)
port map(
rst_n_i => rst_n_i,
clka_i => clka_i,
bwea_i => bwea_i,
wea_i => wea_i,
aa_i => aa_i,
da_i => da_i,
qa_o => open,
clkb_i => clkb_i,
bweb_i => (others => '0'),
web_i => '0',
ab_i => ab_i,
db_i => (others => '0'),
qb_o => qb_o);
end syn;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
library work;
use work.genram_pkg.all;
entity generic_spram is
generic (
-- standard parameters
g_data_width : natural := 32;
g_size : natural := 1024;
-- if true, the user can write individual bytes by using bwe_i
g_with_byte_enable : boolean := false;
-- RAM read-on-write conflict resolution. Can be "read_first" (read-then-write)
-- or "write_first" (write-then-read)
g_addr_conflict_resolution : string := "write_first";
g_init_file : string := ""
);
port (
rst_n_i : in std_logic; -- synchronous reset, active LO
clk_i : in std_logic; -- clock input
-- byte write enable, actiwe when g_
bwe_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
-- global write enable (masked by bwe_i if g_with_byte_enable = true)
we_i : in std_logic;
-- address input
a_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
-- data input
d_i : in std_logic_vector(g_data_width-1 downto 0);
-- data output
q_o : out std_logic_vector(g_data_width-1 downto 0)
);
end generic_spram;
architecture syn of generic_spram is
constant c_num_bytes : integer := (g_data_width+7)/8;
type t_ram_type is array(0 to g_size-1) of std_logic_vector(g_data_width-1 downto 0);
type t_string_file_type is file of string;
impure function f_bitstring_2_slv(s : string; num_bits : integer) return std_logic_vector is
begin
end function f_bitstring_2_slv;
impure function f_load_from_file(file_name : string) return t_ram_type is
file f : t_string_file_type;
variable fstatus : file_open_status;
begin
file_open(fstatus, f, file_name, read_mode);
if(fstatus /= open_ok) then
report "generic_spram: Cannot open memory initialization file: " & file_name severity failure;
end if;
end function f_load_from_file;
signal ram : t_ram_type;
signal s_we : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in : std_logic_vector(g_data_width-1 downto 0);
signal s_ram_out : std_logic_vector(g_data_width-1 downto 0);
begin
assert (g_init_file = "") report "generic_spram: Memory initialization files not supported yet. Sorry :(" severity failure;
gen_with_byte_enable_writefirst : if(g_with_byte_enable = true and g_addr_conflict_resolution = "write_first") generate
s_we <= bwe_i when we_i = '1' else (others => '0');
process(s_we, d_i)
begin
for i in 0 to c_num_bytes-1 loop
if s_we(i) = '1' then
s_ram_in(8*i+7 downto 8*i) <= d_i(8*i+7 downto 8*i);
s_ram_out(8*i+7 downto 8*i) <= d_i(8*i+7 downto 8*i);
else
s_ram_in(8*i+7 downto 8*i) <= ram(conv_integer(unsigned(a_i)))(8*i+7 downto 8*i);
s_ram_out(8*i+7 downto 8*i) <= ram(conv_integer(unsigned(a_i)))(8*i+7 downto 8*i);
end if;
end loop; -- i
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
ram(conv_integer(unsigned(a_i))) <= s_ram_in;
q_o <= s_ram_out;
end if;
end process;
end generate gen_with_byte_enable_writefirst;
gen_with_byte_enable_readfirst : if(g_with_byte_enable = true and g_addr_conflict_resolution = "read_first") generate
s_we <= bwe_i when we_i = '1' else (others => '0');
process(s_we, d_i)
begin
for i in 0 to c_num_bytes-1 loop
if (s_we(i) = '1') then
s_ram_in(8*i+7 downto 8*i) <= d_i(8*i+7 downto 8*i);
else
s_ram_in(8*i+7 downto 8*i) <= ram(conv_integer(unsigned(a_i)))(8*i+7 downto 8*i);
end if;
end loop;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
ram(conv_integer(unsigned(a_i))) <= s_ram_in;
q_o <= ram(conv_integer(unsigned(a_i)));
end if;
end process;
end generate gen_with_byte_enable_readfirst;
gen_without_byte_enable_writefirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "write_first") generate
process(clk_i)
begin
if rising_edge(clk_i) then
if(we_i = '1') then
ram(conv_integer(unsigned(a_i))) <= d_i;
q_o <= d_i;
else
q_o <= ram(conv_integer(unsigned(a_i)));
end if;
end if;
end process;
end generate gen_without_byte_enable_writefirst;
gen_without_byte_enable_readfirst : if(g_with_byte_enable = false and g_addr_conflict_resolution = "read_first") generate
process(clk_i)
begin
if rising_edge(clk_i) then
if(we_i = '1') then
ram(conv_integer(unsigned(a_i))) <= d_i;
end if;
q_o <= ram(conv_integer(unsigned(a_i)));
end if;
end process;
end generate gen_without_byte_enable_readfirst;
end syn;
files = ["dummy.vhd"]
library = "fifo_generator_v6_1"
\ No newline at end of file
entity xilinx_dummy_sim is
end xilinx_dummy_sim;
\ No newline at end of file
files =["generic_async_fifo.vhd", "generic_sync_fifo.vhd"];
\ No newline at end of file
files =["generic_async_fifo.vhd", "generic_sync_fifo.vhd"];
\ No newline at end of file
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- Bi-color LED controller
-- http://www.ohwr.org/projects/svec
--------------------------------------------------------------------------------
--
-- unit name: bicolor_led_ctrl
--
-- author: Matthieu Cattin (matthieu.cattin@cern.ch)
--
-- date: 11-07-2012
--
-- version: 1.0
--
-- description: Bi-color LED controller. It controls a matrix of bi-color LED.
-- The FPGA ouputs for the columns (C) are connected to buffers
-- and serial resistances and then to the LEDs. The FPGA outputs
-- for lines (L) are connected to tri-state buffers and the to
-- the LEDs. The FPGA outputs for lines output enable (L_OEN) are
-- connected to the output enable of the tri-state buffers.
--
-- Example with three lines and two columns:
--
-- |<refresh period>|
--
-- L1/L2/L3 __|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__
--
-- L1_OEN -----|___________|-----|___________|-----|___________|-----|___________|--
--
-- L2_OEN _____|-----|___________|-----|___________|-----|___________|-----|________
--
-- L3_OEN ___________|-----|___________|-----|___________|-----|___________|-----|__
--
-- Cn __|--|__|--|__|--|_________________|-----------------|--|__|--|__|--|__|--
--
-- LED Ln/Cn OFF | color_1 | color_2 | both_colors |
--
--
-- dependencies:
--
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------------
-- last changes: see log.
--------------------------------------------------------------------------------
-- TODO: -
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
library work;
use work.bicolor_led_ctrl_pkg.all;
entity bicolor_led_ctrl is
generic(
g_NB_COLUMN : natural := 4;
g_NB_LINE : natural := 2;
g_CLK_FREQ : natural := 125000000; -- in Hz
g_REFRESH_RATE : natural := 250 -- in Hz
);
port
(
rst_n_i : in std_logic;
clk_i : in std_logic;
led_intensity_i : in std_logic_vector(6 downto 0);
led_state_i : in std_logic_vector((g_NB_LINE * g_NB_COLUMN * 2) - 1 downto 0);
column_o : out std_logic_vector(g_NB_COLUMN - 1 downto 0);
line_o : out std_logic_vector(g_NB_LINE - 1 downto 0);
line_oen_o : out std_logic_vector(g_NB_LINE - 1 downto 0)
);
end bicolor_led_ctrl;
architecture rtl of bicolor_led_ctrl is
------------------------------------------------------------------------------
-- Components declaration
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- Constants declaration
------------------------------------------------------------------------------
constant c_REFRESH_CNT_INIT : natural := natural(g_CLK_FREQ/(2 * g_NB_LINE * g_REFRESH_RATE)) - 1;
constant c_REFRESH_CNT_NB_BITS : natural := log2_ceil(c_REFRESH_CNT_INIT);
constant c_LINE_OEN_CNT_NB_BITS : natural := log2_ceil(g_NB_LINE);
------------------------------------------------------------------------------
-- Signals declaration
------------------------------------------------------------------------------
signal refresh_rate_cnt : unsigned(c_REFRESH_CNT_NB_BITS - 1 downto 0);
signal refresh_rate : std_logic;
signal line_ctrl : std_logic;
signal intensity_ctrl_cnt : unsigned(c_REFRESH_CNT_NB_BITS - 1 downto 0);
signal intensity_ctrl : std_logic;
signal line_oen_cnt : unsigned(c_LINE_OEN_CNT_NB_BITS - 1 downto 0);
signal line_oen : std_logic_vector(2**c_LINE_OEN_CNT_NB_BITS - 1 downto 0);
signal led_state : std_logic_vector((g_NB_LINE * g_NB_COLUMN) -1 downto 0);
begin
------------------------------------------------------------------------------
-- Refresh rate counter
------------------------------------------------------------------------------
p_refresh_rate_cnt : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
refresh_rate_cnt <= (others => '0');
refresh_rate <= '0';
elsif refresh_rate_cnt = 0 then
refresh_rate_cnt <= to_unsigned(c_REFRESH_CNT_INIT, c_REFRESH_CNT_NB_BITS);
refresh_rate <= '1';
else
refresh_rate_cnt <= refresh_rate_cnt - 1;
refresh_rate <= '0';
end if;
end if;
end process p_refresh_rate_cnt;
------------------------------------------------------------------------------
-- Intensity control
------------------------------------------------------------------------------
p_intensity_ctrl_cnt : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
intensity_ctrl_cnt <= (others => '0');
elsif refresh_rate = '1' then
intensity_ctrl_cnt <= to_unsigned(natural(c_REFRESH_CNT_INIT/100) * to_integer(unsigned(led_intensity_i)), c_REFRESH_CNT_NB_BITS);
else
intensity_ctrl_cnt <= intensity_ctrl_cnt - 1;
end if;
end if;
end process p_intensity_ctrl_cnt;
p_intensity_ctrl : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
intensity_ctrl <= '0';
elsif refresh_rate = '1' then
intensity_ctrl <= '1';
elsif intensity_ctrl_cnt = 0 then
intensity_ctrl <= '0';
end if;
end if;
end process p_intensity_ctrl;
------------------------------------------------------------------------------
-- Lines ouput
------------------------------------------------------------------------------
p_line_ctrl : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
line_ctrl <= '0';
elsif refresh_rate = '1' then
line_ctrl <= not(line_ctrl);
end if;
end if;
end process p_line_ctrl;
f_line_o : for I in 0 to g_NB_LINE - 1 generate
line_o(I) <= line_ctrl and intensity_ctrl;
end generate f_line_o;
------------------------------------------------------------------------------
-- Lines output enable
------------------------------------------------------------------------------
p_line_oen_cnt : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
line_oen_cnt <= (others => '0');
elsif line_ctrl = '1' and refresh_rate = '1' then
if line_oen_cnt = 0 then
line_oen_cnt <= to_unsigned(g_NB_LINE - 1, c_LINE_OEN_CNT_NB_BITS);
else
line_oen_cnt <= line_oen_cnt - 1;
end if;
end if;
end if;
end process p_line_oen_cnt;
p_line_oen_decode : process(line_oen_cnt)
variable v_onehot : std_logic_vector((2**line_oen_cnt'length)-1 downto 0);
variable v_index : integer range 0 to (2**line_oen_cnt'length)-1;
begin
v_onehot := (others => '0');
v_index := 0;
for i in line_oen_cnt'range loop
if (line_oen_cnt(i) = '1') then
v_index := 2*v_index+1;
else
v_index := 2*v_index;
end if;
end loop;
v_onehot(v_index) := '1';
line_oen <= v_onehot;
end process p_line_oen_decode;
line_oen_o <= line_oen(line_oen_o'left downto 0);
------------------------------------------------------------------------------
-- Columns output
------------------------------------------------------------------------------
f_led_state : for I in 0 to (g_NB_COLUMN * g_NB_LINE) - 1 generate
led_state(I) <= '0' when led_state_i(2 * I + 1 downto 2 * I) = c_LED_RED else
'1' when led_state_i(2 * I + 1 downto 2 * I) = c_LED_GREEN else
(line_ctrl and intensity_ctrl) when led_state_i(2 * I + 1 downto 2 * I) = c_LED_OFF else
not(line_ctrl and intensity_ctrl) when led_state_i(2 * I + 1 downto 2 * I) = c_LED_RED_GREEN;
end generate f_led_state;
f_column_o : for C in 0 to g_NB_COLUMN - 1 generate
column_o(C) <= led_state(g_NB_COLUMN * to_integer(line_oen_cnt) + C);
end generate f_column_o;
end rtl;
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- Bi-color LED controller package
-- http://www.ohwr.org/projects/svec
--------------------------------------------------------------------------------
--
-- unit name: bicolor_led_ctrl_pkg
--
-- author: Matthieu Cattin (matthieu.cattin@cern.ch)
--
-- date: 11-07-2012
--
-- version: 1.0
--
-- description: Package for Bi-color LED controller.
--
-- dependencies:
--
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------------
-- last changes: see log.
--------------------------------------------------------------------------------
-- TODO: -
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
package bicolor_led_ctrl_pkg is
------------------------------------------------------------------------------
-- Constants declaration
------------------------------------------------------------------------------
constant c_LED_RED : std_logic_vector(1 downto 0) := "10";
constant c_LED_GREEN : std_logic_vector(1 downto 0) := "01";
constant c_LED_RED_GREEN : std_logic_vector(1 downto 0) := "11";
constant c_LED_OFF : std_logic_vector(1 downto 0) := "00";
------------------------------------------------------------------------------
-- Functions declaration
------------------------------------------------------------------------------
function log2_ceil(N : natural) return positive;
------------------------------------------------------------------------------
-- Components declaration
------------------------------------------------------------------------------
component bicolor_led_ctrl
generic(
g_NB_COLUMN : natural := 4;
g_NB_LINE : natural := 2;
g_CLK_FREQ : natural := 125000000; -- in Hz
g_REFRESH_RATE : natural := 250 -- in Hz
);
port
(
rst_n_i : in std_logic;
clk_i : in std_logic;
led_intensity_i : in std_logic_vector(6 downto 0);
led_state_i : in std_logic_vector((g_NB_LINE * g_NB_COLUMN * 2) - 1 downto 0);
column_o : out std_logic_vector(g_NB_COLUMN - 1 downto 0);
line_o : out std_logic_vector(g_NB_LINE - 1 downto 0);
line_oen_o : out std_logic_vector(g_NB_LINE - 1 downto 0)
);
end component;
end bicolor_led_ctrl_pkg;
package body bicolor_led_ctrl_pkg is
------------------------------------------------------------------------------
-- Function : Returns log of 2 of a natural number
------------------------------------------------------------------------------
function log2_ceil(N : natural) return positive is
begin
if N <= 2 then
return 1;
elsif N mod 2 = 0 then
return 1 + log2_ceil(N/2);
else
return 1 + log2_ceil((N+1)/2);
end if;
end;
end bicolor_led_ctrl_pkg;
def __helper():
dirs = [
"wb_async_bridge",
"wb_onewire_master",
"wb_i2c_master",
"wb_bus_fanout",
"wb_dpram",
"wb_gpio_port",
"wb_simple_timer",
"wb_uart",
"wb_vic",
"wb_spi",
"wb_crossbar",
"wb_lm32",
"wb_slave_adapter",
"wb_xilinx_fpga_loader",
"wb_clock_crossing",
"wb_dma",
"wb_serial_lcd",
"wb_simple_pwm",
"wbgen2"
]
if (target == "altera"): dirs.extend(["wb_pcie"]);
return dirs
modules = { "local" : __helper() };
files = ["wishbone_pkg.vhd"];
files = ["wbgen2_dpssram.vhd",
"wbgen2_eic.vhd",
"wbgen2_fifo_async.vhd",
"wbgen2_fifo_sync.vhd",
"wbgen2_pkg.vhd"]
#library = "wbgen2"
library ieee;
use ieee.std_logic_1164.all;
--use work.genram_pkg.all;
--use work.common_components.all;
--library wbgen2;
use work.wbgen2_pkg.all;
entity wbgen2_dpssram is
generic (
g_data_width : natural := 32;
g_size : natural := 1024;
g_addr_width : natural := 10;
g_dual_clock : boolean := true;
g_use_bwsel : boolean := true);
port (
clk_a_i : in std_logic;
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : out std_logic_vector(g_data_width-1 downto 0);
data_b_o : out std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic
);
end wbgen2_dpssram;
architecture syn of wbgen2_dpssram is
function f_log2_size (A : natural) return natural is
begin
for I in 1 to 64 loop -- Works for up to 64 bits
if (2**I > A) then
return(I-1);
end if;
end loop;
return(63);
end function f_log2_size;
component generic_dpram
generic (
g_data_width : natural;
g_size : natural;
g_with_byte_enable : boolean;
g_addr_conflict_resolution : string := "read_first";
g_init_file : string := "";
g_dual_clock : boolean);
port (
rst_n_i : in std_logic := '1';
clka_i : in std_logic;
bwea_i : in std_logic_vector(g_data_width/8-1 downto 0);
wea_i : in std_logic;
aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
da_i : in std_logic_vector(g_data_width-1 downto 0);
qa_o : out std_logic_vector(g_data_width-1 downto 0);
clkb_i : in std_logic;
bweb_i : in std_logic_vector(g_data_width/8-1 downto 0);
web_i : in std_logic;
ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
db_i : in std_logic_vector(g_data_width-1 downto 0);
qb_o : out std_logic_vector(g_data_width-1 downto 0));
end component;
begin
wrapped_dpram: generic_dpram
generic map (
g_data_width => g_data_width,
g_size => g_size,
g_with_byte_enable => g_use_bwsel,
g_dual_clock => g_dual_clock)
port map (
rst_n_i => '1',
clka_i => clk_a_i,
bwea_i => bwsel_a_i,
wea_i => wr_a_i,
aa_i => addr_a_i,
da_i => data_a_i,
qa_o => data_a_o,
clkb_i => clk_b_i,
bweb_i => bwsel_b_i,
web_i => wr_b_i,
ab_i => addr_b_i,
db_i => data_b_i,
qb_o => data_b_o);
end syn;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wbgen2_pkg.all;
entity wbgen2_eic is
generic (
g_num_interrupts : natural := 1;
g_irq00_mode : integer := 0;
g_irq01_mode : integer := 0;
g_irq02_mode : integer := 0;
g_irq03_mode : integer := 0;
g_irq04_mode : integer := 0;
g_irq05_mode : integer := 0;
g_irq06_mode : integer := 0;
g_irq07_mode : integer := 0;
g_irq08_mode : integer := 0;
g_irq09_mode : integer := 0;
g_irq0a_mode : integer := 0;
g_irq0b_mode : integer := 0;
g_irq0c_mode : integer := 0;
g_irq0d_mode : integer := 0;
g_irq0e_mode : integer := 0;
g_irq0f_mode : integer := 0;
g_irq10_mode : integer := 0;
g_irq11_mode : integer := 0;
g_irq12_mode : integer := 0;
g_irq13_mode : integer := 0;
g_irq14_mode : integer := 0;
g_irq15_mode : integer := 0;
g_irq16_mode : integer := 0;
g_irq17_mode : integer := 0;
g_irq18_mode : integer := 0;
g_irq19_mode : integer := 0;
g_irq1a_mode : integer := 0;
g_irq1b_mode : integer := 0;
g_irq1c_mode : integer := 0;
g_irq1d_mode : integer := 0;
g_irq1e_mode : integer := 0;
g_irq1f_mode : integer := 0
);
port(
rst_n_i : in std_logic; -- reset & system clock, as always :)
clk_i : in std_logic;
-- raw interrupt inputs
irq_i : in std_logic_vector(g_num_interrupts-1 downto 0);
-- interrupt acknowledge signal, used for level-active interrupts to
-- indicate that the interrupt has been handled
irq_ack_o: out std_logic_vector(g_num_interrupts-1 downto 0);
-- interrupt mask regsiter (slv/bus read-only)
reg_imr_o : out std_logic_vector(g_num_interrupts-1 downto 0);
-- interrupt enable/disable registers (slv/bus pass-through)
reg_ier_i : in std_logic_vector(g_num_interrupts-1 downto 0);
reg_ier_wr_stb_i : in std_logic;
reg_idr_i : in std_logic_vector(g_num_interrupts-1 downto 0);
reg_idr_wr_stb_i : in std_logic;
-- interrupt status register (slv/bus write with LOAD_EXT)
reg_isr_o : out std_logic_vector(g_num_interrupts-1 downto 0);
reg_isr_i : in std_logic_vector(g_num_interrupts-1 downto 0);
reg_isr_wr_stb_i : in std_logic;
-- multiplexed wishbone irq output
wb_irq_o : out std_logic
);
end wbgen2_eic;
architecture syn of wbgen2_eic is
subtype t_irq_mode is integer;
type t_irq_mode_vec is array (0 to 31) of t_irq_mode;
constant c_IRQ_MODE_RISING_EDGE : t_irq_mode := 0;
constant c_IRQ_MODE_FALLING_EDGE : t_irq_mode := 1;
constant c_IRQ_MODE_LEVEL_0 : t_irq_mode := 2;
constant c_IRQ_MODE_LEVEL_1 : t_irq_mode := 3;
signal irq_mode : t_irq_mode_vec;
signal irq_mask : std_logic_vector(g_num_interrupts-1 downto 0);
signal irq_pending : std_logic_vector(g_num_interrupts-1 downto 0);
signal irq_i_d0 : std_logic_vector(g_num_interrupts-1 downto 0);
signal irq_i_d1 : std_logic_vector(g_num_interrupts-1 downto 0);
signal irq_i_d2 : std_logic_vector(g_num_interrupts-1 downto 0);
begin -- syn
irq_mode(0) <= g_irq00_mode;
irq_mode(1) <= g_irq01_mode;
irq_mode(2) <= g_irq02_mode;
irq_mode(3) <= g_irq03_mode;
irq_mode(4) <= g_irq04_mode;
irq_mode(5) <= g_irq05_mode;
irq_mode(6) <= g_irq06_mode;
irq_mode(7) <= g_irq07_mode;
irq_mode(8) <= g_irq08_mode;
irq_mode(9) <= g_irq09_mode;
irq_mode(10) <= g_irq0a_mode;
irq_mode(11) <= g_irq0b_mode;
irq_mode(12) <= g_irq0c_mode;
irq_mode(13) <= g_irq0d_mode;
irq_mode(14) <= g_irq0e_mode;
irq_mode(15) <= g_irq0f_mode;
irq_mode(16) <= g_irq10_mode;
irq_mode(17) <= g_irq11_mode;
irq_mode(18) <= g_irq12_mode;
irq_mode(19) <= g_irq13_mode;
irq_mode(20) <= g_irq14_mode;
irq_mode(21) <= g_irq15_mode;
irq_mode(22) <= g_irq16_mode;
irq_mode(23) <= g_irq17_mode;
irq_mode(24) <= g_irq18_mode;
irq_mode(25) <= g_irq19_mode;
irq_mode(26) <= g_irq1a_mode;
irq_mode(27) <= g_irq1b_mode;
irq_mode(28) <= g_irq1c_mode;
irq_mode(29) <= g_irq1d_mode;
irq_mode(30) <= g_irq1e_mode;
irq_mode(31) <= g_irq1f_mode;
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
irq_i_d0 <= (others => '0');
irq_i_d1 <= (others => '0');
irq_i_d1 <= (others => '0');
irq_pending <= (others => '0');
irq_mask <= (others => '0');
elsif rising_edge(clk_i) then
for i in 0 to g_num_interrupts-1 loop
irq_i_d0(i) <= irq_i(i);
irq_i_d1(i) <= irq_i_d0(i);
irq_i_d2(i) <= irq_i_d1(i);
if((reg_isr_i(i) = '1' and reg_isr_wr_stb_i = '1') or irq_mask(i) = '0') then
irq_pending(i) <= '0';
irq_i_d0(i) <= '0';
irq_i_d1(i) <= '0';
irq_i_d2(i) <= '0';
else
case irq_mode(i) is
when c_IRQ_MODE_LEVEL_0 => irq_pending(i) <= not irq_i_d2(i);
when c_IRQ_MODE_LEVEL_1 => irq_pending(i) <= irq_i_d2(i);
when c_IRQ_MODE_RISING_EDGE => irq_pending(i) <= irq_pending(i) or ((not irq_i_d2(i)) and irq_i_d1(i));
when c_IRQ_MODE_FALLING_EDGE => irq_pending(i) <= irq_pending(i) or ((not irq_i_d1(i)) and irq_i_d2(i));
when others => null;
end case;
end if;
end loop; -- i
if(reg_ier_wr_stb_i = '1') then
for i in 0 to g_num_interrupts-1 loop
if(reg_ier_i(i) = '1') then
irq_mask(i) <= '1';
end if;
end loop;
end if;
if(reg_idr_wr_stb_i = '1') then
for i in 0 to g_num_interrupts-1 loop
if(reg_idr_i(i) = '1') then
irq_mask(i) <= '0';
end if;
end loop;
end if;
end if;
end process;
-- generation of wb_irq_o
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
wb_irq_o <= '0';
elsif rising_edge(clk_i) then
if(irq_pending = std_logic_vector(to_unsigned(0, g_num_interrupts))) then
wb_irq_o <= '0';
else
wb_irq_o <= '1';
end if;
end if;
end process;
gen_irq_ack: for i in 0 to g_num_interrupts-1 generate
irq_ack_o(i) <= '1' when (reg_isr_wr_stb_i = '1' and reg_isr_i(i) = '1') else '0';
end generate gen_irq_ack;
reg_imr_o <= irq_mask;
reg_isr_o <= irq_pending;
end syn;
-------------------------------------------------------------------------------
-- Title : Parametrizable asynchronous FIFO (Generic version)
-- Project : Generics RAMs and FIFOs collection
-------------------------------------------------------------------------------
-- File : generic_async_fifo.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2011-01-25
-- Last update: 2012-07-03
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Dual-clock asynchronous FIFO.
-- - configurable data width and size
-- - configurable full/empty/almost full/almost empty/word count signals
-------------------------------------------------------------------------------
-- Copyright (c) 2011 CERN
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-01-25 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
entity generic_async_fifo is
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean := false;
-- Read-side flag selection
g_with_rd_empty : boolean := true; -- with empty flag
g_with_rd_full : boolean := false; -- with full flag
g_with_rd_almost_empty : boolean := false;
g_with_rd_almost_full : boolean := false;
g_with_rd_count : boolean := false; -- with words counter
g_with_wr_empty : boolean := false;
g_with_wr_full : boolean := true;
g_with_wr_almost_empty : boolean := false;
g_with_wr_almost_full : boolean := false;
g_with_wr_count : boolean := false;
g_almost_empty_threshold : integer; -- threshold for almost empty flag
g_almost_full_threshold : integer -- threshold for almost full flag
);
port (
rst_n_i : in std_logic := '1';
-- write port
clk_wr_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
wr_almost_empty_o : out std_logic;
wr_almost_full_o : out std_logic;
wr_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
-- read port
clk_rd_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
rd_empty_o : out std_logic;
rd_full_o : out std_logic;
rd_almost_empty_o : out std_logic;
rd_almost_full_o : out std_logic;
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)
);
end generic_async_fifo;
architecture syn of generic_async_fifo is
component inferred_async_fifo
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean;
g_with_rd_empty : boolean;
g_with_rd_full : boolean;
g_with_rd_almost_empty : boolean;
g_with_rd_almost_full : boolean;
g_with_rd_count : boolean;
g_with_wr_empty : boolean;
g_with_wr_full : boolean;
g_with_wr_almost_empty : boolean;
g_with_wr_almost_full : boolean;
g_with_wr_count : boolean;
g_almost_empty_threshold : integer;
g_almost_full_threshold : integer);
port (
rst_n_i : in std_logic := '1';
clk_wr_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
wr_almost_empty_o : out std_logic;
wr_almost_full_o : out std_logic;
wr_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
clk_rd_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
rd_empty_o : out std_logic;
rd_full_o : out std_logic;
rd_almost_empty_o : out std_logic;
rd_almost_full_o : out std_logic;
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0));
end component;
begin -- syn
U_Inferred_FIFO : inferred_async_fifo
generic map (
g_data_width => g_data_width,
g_size => g_size,
g_show_ahead => g_show_ahead,
g_with_rd_empty => g_with_rd_empty,
g_with_rd_full => g_with_rd_full,
g_with_rd_almost_empty => g_with_rd_almost_empty,
g_with_rd_almost_full => g_with_rd_almost_full,
g_with_rd_count => g_with_rd_count,
g_with_wr_empty => g_with_wr_empty,
g_with_wr_full => g_with_wr_full,
g_with_wr_almost_empty => g_with_wr_almost_empty,
g_with_wr_almost_full => g_with_wr_almost_full,
g_with_wr_count => g_with_wr_count,
g_almost_empty_threshold => g_almost_empty_threshold,
g_almost_full_threshold => g_almost_full_threshold)
port map (
rst_n_i => rst_n_i,
clk_wr_i => clk_wr_i,
d_i => d_i,
we_i => we_i,
wr_empty_o => wr_empty_o,
wr_full_o => wr_full_o,
wr_almost_empty_o => wr_almost_empty_o,
wr_almost_full_o => wr_almost_full_o,
wr_count_o => wr_count_o,
clk_rd_i => clk_rd_i,
q_o => q_o,
rd_i => rd_i,
rd_empty_o => rd_empty_o,
rd_full_o => rd_full_o,
rd_almost_empty_o => rd_almost_empty_o,
rd_almost_full_o => rd_almost_full_o,
rd_count_o => rd_count_o);
end syn;
library ieee;
use ieee.std_logic_1164.all;
use work.genram_pkg.all;
use work.wbgen2_pkg.all;
entity wbgen2_fifo_async is
generic (
g_size : integer;
g_width : integer;
g_usedw_size : integer
);
port
(
rst_n_i : in std_logic := '1';
rd_clk_i : in std_logic;
rd_req_i : in std_logic;
rd_data_o : out std_logic_vector(g_width-1 downto 0);
rd_empty_o : out std_logic;
rd_full_o : out std_logic;
rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0);
wr_clk_i : in std_logic;
wr_req_i : in std_logic;
wr_data_i : in std_logic_vector(g_width-1 downto 0);
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0)
);
end wbgen2_fifo_async;
architecture rtl of wbgen2_fifo_async is
component generic_async_fifo
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean;
g_with_rd_empty : boolean;
g_with_rd_full : boolean;
g_with_rd_almost_empty : boolean;
g_with_rd_almost_full : boolean;
g_with_rd_count : boolean;
g_with_wr_empty : boolean;
g_with_wr_full : boolean;
g_with_wr_almost_empty : boolean;
g_with_wr_almost_full : boolean;
g_with_wr_count : boolean;
g_almost_empty_threshold : integer;
g_almost_full_threshold : integer);
port (
rst_n_i : in std_logic := '1';
clk_wr_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
wr_almost_empty_o : out std_logic;
wr_almost_full_o : out std_logic;
wr_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
clk_rd_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
rd_empty_o : out std_logic;
rd_full_o : out std_logic;
rd_almost_empty_o : out std_logic;
rd_almost_full_o : out std_logic;
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0));
end component;
begin
wrapped_fifo : generic_async_fifo
generic map (
g_data_width => g_width,
g_size => g_size,
g_show_ahead => false,
g_with_rd_empty => true,
g_with_rd_full => true,
g_with_rd_almost_empty => false,
g_with_rd_almost_full => false,
g_with_rd_count => true,
g_with_wr_empty => true,
g_with_wr_full => true,
g_with_wr_almost_empty => false,
g_with_wr_almost_full => false,
g_with_wr_count => true,
g_almost_empty_threshold => 0,
g_almost_full_threshold => 0)
port map (
rst_n_i => rst_n_i,
clk_wr_i => wr_clk_i,
d_i => wr_data_i,
we_i => wr_req_i,
wr_empty_o => wr_empty_o,
wr_full_o => wr_full_o,
wr_almost_empty_o => open,
wr_almost_full_o => open,
wr_count_o => wr_usedw_o,
clk_rd_i => rd_clk_i,
q_o => rd_data_o,
rd_i => rd_req_i,
rd_empty_o => rd_empty_o,
rd_full_o => rd_full_o,
rd_almost_empty_o => open,
rd_almost_full_o => open,
rd_count_o => rd_usedw_o);
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use work.wbgen2_pkg.all;
entity wbgen2_fifo_sync is
generic (
g_width : integer;
g_size : integer;
g_usedw_size : integer);
port
(
clk_i : in std_logic;
rst_n_i : in std_logic := '1';
wr_data_i : in std_logic_vector(g_width-1 downto 0);
wr_req_i : in std_logic;
rd_data_o : out std_logic_vector(g_width-1 downto 0);
rd_req_i : in std_logic;
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0);
rd_empty_o : out std_logic;
rd_full_o : out std_logic;
rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0)
);
end wbgen2_fifo_sync;
architecture rtl of wbgen2_fifo_sync is
function f_log2_size (A : natural) return natural is
begin
for I in 1 to 64 loop -- Works for up to 64 bits
if (2**I > A) then
return(I-1);
end if;
end loop;
return(63);
end function f_log2_size;
component generic_sync_fifo
generic (
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean;
g_with_empty : boolean;
g_with_full : boolean;
g_with_almost_empty : boolean;
g_with_almost_full : boolean;
g_with_count : boolean;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
empty_o : out std_logic;
full_o : out std_logic;
almost_empty_o : out std_logic;
almost_full_o : out std_logic;
count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0));
end component;
signal empty_int : std_logic;
signal full_int : std_logic;
signal usedw_int : std_logic_vector(g_usedw_size-1 downto 0);
begin
wrapped_fifo: generic_sync_fifo
generic map (
g_data_width => g_width,
g_size => g_size,
g_show_ahead => false,
g_with_empty => true,
g_with_full => true,
g_with_almost_empty => false,
g_with_almost_full => false,
g_with_count => true)
port map (
rst_n_i => rst_n_i,
clk_i => clk_i,
d_i => wr_data_i,
we_i => wr_req_i,
q_o => rd_data_o,
rd_i => rd_req_i,
empty_o => empty_int,
full_o => full_int,
almost_empty_o => open,
almost_full_o => open,
count_o => usedw_int);
rd_empty_o <= empty_int;
rd_full_o <= full_int;
rd_usedw_o <= usedw_int;
wr_empty_o <= empty_int;
wr_full_o <= full_int;
wr_usedw_o <= usedw_int;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
package wbgen2_pkg is
component wbgen2_dpssram
generic (
g_data_width : natural;
g_size : natural;
g_addr_width : natural;
g_dual_clock : boolean;
g_use_bwsel : boolean);
port (
clk_a_i : in std_logic;
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : out std_logic_vector(g_data_width-1 downto 0);
data_b_o : out std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic);
end component;
component wbgen2_eic
generic (
g_num_interrupts : natural;
g_irq00_mode : integer;
g_irq01_mode : integer;
g_irq02_mode : integer;
g_irq03_mode : integer;
g_irq04_mode : integer;
g_irq05_mode : integer;
g_irq06_mode : integer;
g_irq07_mode : integer;
g_irq08_mode : integer;
g_irq09_mode : integer;
g_irq0a_mode : integer;
g_irq0b_mode : integer;
g_irq0c_mode : integer;
g_irq0d_mode : integer;
g_irq0e_mode : integer;
g_irq0f_mode : integer;
g_irq10_mode : integer;
g_irq11_mode : integer;
g_irq12_mode : integer;
g_irq13_mode : integer;
g_irq14_mode : integer;
g_irq15_mode : integer;
g_irq16_mode : integer;
g_irq17_mode : integer;
g_irq18_mode : integer;
g_irq19_mode : integer;
g_irq1a_mode : integer;
g_irq1b_mode : integer;
g_irq1c_mode : integer;
g_irq1d_mode : integer;
g_irq1e_mode : integer;
g_irq1f_mode : integer);
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
irq_i : in std_logic_vector(g_num_interrupts-1 downto 0);
irq_ack_o : out std_logic_vector(g_num_interrupts-1 downto 0);
reg_imr_o : out std_logic_vector(g_num_interrupts-1 downto 0);
reg_ier_i : in std_logic_vector(g_num_interrupts-1 downto 0);
reg_ier_wr_stb_i : in std_logic;
reg_idr_i : in std_logic_vector(g_num_interrupts-1 downto 0);
reg_idr_wr_stb_i : in std_logic;
reg_isr_o : out std_logic_vector(g_num_interrupts-1 downto 0);
reg_isr_i : in std_logic_vector(g_num_interrupts-1 downto 0);
reg_isr_wr_stb_i : in std_logic;
wb_irq_o : out std_logic);
end component;
component wbgen2_fifo_async
generic (
g_size : integer;
g_width : integer;
g_usedw_size : integer);
port (
rst_n_i : in std_logic := '1';
rd_clk_i : in std_logic;
rd_req_i : in std_logic;
rd_data_o : out std_logic_vector(g_width-1 downto 0);
rd_empty_o : out std_logic;
rd_full_o : out std_logic;
rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0);
wr_clk_i : in std_logic;
wr_req_i : in std_logic;
wr_data_i : in std_logic_vector(g_width-1 downto 0);
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0));
end component;
component wbgen2_fifo_sync
generic (
g_width : integer;
g_size : integer;
g_usedw_size : integer);
port (
clk_i : in std_logic;
rst_n_i : in std_logic := '1';
wr_data_i : in std_logic_vector(g_width-1 downto 0);
wr_req_i : in std_logic;
rd_data_o : out std_logic_vector(g_width-1 downto 0);
rd_req_i : in std_logic;
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0);
rd_empty_o : out std_logic;
rd_full_o : out std_logic;
rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0));
end component;
end wbgen2_pkg;
......@@ -32,15 +32,28 @@
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Date 08/2013 |
-- Version v1 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 10/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- 08/2013 v1. EG cs_n_o always active; extra 8ns cycle to the rd_n_o |
-- |
----------------------------------------------/!\-------------------------------------------------|
-- In this design timestamps retreival from the ACAM could not happen in 4 cycles (=4*8ns), as |
-- it was noticed that the ACAM tdc1_ef1_i is arriving to the FPGA more than 16ns after the rd_n_o|
-- activation; en extra cycle is therefore essential and has been added in the |
-- acam_databus_interface unit; this means that the FPGA cannot keep up to pace with the 31.25 M |
-- timestamps/sec max rate of the ACAM; the max rate of the application would now be 25 M |
-- timestamps/sec. However, in practice this is not a problem at all, as the driver layer would |
-- anyway be unable to keep pace with such frequencies! |
-- EVA: add this in the board's specification |
-- EVA: check all commenting in the code that was refering to 4 cycles/ timestamp |
-- EVA: change the acam_err_flag to show overflows of the interface FIFOs rather than Hit FIFOs. |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
......@@ -123,7 +136,7 @@ end acam_databus_interface;
architecture rtl of acam_databus_interface is
type t_acam_interface is (IDLE, RD_START, RD_FETCH, RD_ACK, WR_START, WR_PUSH, WR_ACK);
type t_acam_interface is (IDLE, RD_START, RD_FETCH, RD_ACK, RD_ACK_AUX, WR_START, WR_PUSH, WR_ACK);
signal acam_data_st, nxt_acam_data_st : t_acam_interface;
signal ef1_synch, ef2_synch : std_logic_vector(1 downto 0) := (others =>'1');
......@@ -181,7 +194,7 @@ begin
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when IDLE =>
-----------------------------------------------
ack <= '0';
ack <= '0';
cs_extend <= '0';
rd_extend <= '0';
wr_extend <= '0';
......@@ -227,6 +240,19 @@ begin
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_ACK =>
-----------------------------------------------
ack <= '0';--------------'1';
cs_extend <= '0';
rd_extend <= '0';
wr_extend <= '0';
wr_remove <= '0';
-----------------------------------------------
nxt_acam_data_st <= RD_ACK_AUX;----IDLE;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_ACK_AUX =>
-----------------------------------------------
ack <= '1';
cs_extend <= '0';
......@@ -317,9 +343,9 @@ output_registers: process (clk_i)
end process;
oe_n_o <= '1';
cs <= ((stb_i and cyc_i) or cs_extend) and not(ack);
rd <= ((stb_i and cyc_i and not(we_i)) or rd_extend) and not(ack);
wr <= ((stb_i and cyc_i and we_i) or wr_extend) and not(wr_remove) and not(ack);
cs <= '1';
rd <= ((stb_i and cyc_i and not(we_i)) or rd_extend) and (not(ack));
wr <= ((stb_i and cyc_i and we_i) or wr_extend) and (not(wr_remove)) and (not(ack));
-- the wr signal has to be removed to respect the Acam specs
data_bus_io <= dat_i(27 downto 0) when we_i='1' else (others =>'Z');
adr_o <= adr_i(3 downto 0);
......
This diff is collapsed.
......@@ -310,7 +310,7 @@ begin
if acam_ef2_i = '0' then
nxt_engine_st <= GET_STAMP2;
elsif acam_ef1_synch1_i ='0' then
elsif acam_ef1_synch1_i ='0' then
nxt_engine_st <= GET_STAMP1;
else
nxt_engine_st <= ACTIVE;
......
......@@ -189,7 +189,7 @@ begin
tstamp_wr_cyc <= '0';
tstamp_wr_we <= '0';
elsif acam_tstamp1_ok_p_i ='1' or acam_tstamp2_ok_p_i ='1' then --------------->> to debug try with one_hz_p_i = '1'
elsif acam_tstamp1_ok_p_i ='1' or acam_tstamp2_ok_p_i ='1' then
tstamp_wr_stb <= '1';
tstamp_wr_cyc <= '1';
tstamp_wr_we <= '1';
......@@ -438,17 +438,16 @@ begin
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- metadata: information about the timestamp
metadata <= std_logic_vector(acam_timestamps) &
--acam_start_nb & retrig_nb_offset_i(15 downto 0) & -- for debugging (24 MSbits)
metadata <= acam_start_nb & retrig_nb_offset_i(15 downto 0) & -- for debugging (24 MSbits)
belongs_to_previous_sec & roll_over_incr_recent_i & "0" & -- for debugging (3 bits)
acam_slope & "0" & acam_channel; -- 5 LSbits
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
full_timestamp(31 downto 0) <= fine_time;
full_timestamp(63 downto 32) <= coarse_time;
full_timestamp(95 downto 64) <= local_utc;
full_timestamp(127 downto 96) <= metadata;
tstamp_wr_dat_o <= full_timestamp;
full_timestamp(31 downto 0) <= fine_time;
full_timestamp(63 downto 32) <= coarse_time;
full_timestamp(95 downto 64) <= local_utc;
full_timestamp(127 downto 96) <= metadata;
tstamp_wr_dat_o <= full_timestamp;
---------------------------------------------------------------------------------------------------
......
This diff is collapsed.
......@@ -407,4 +407,4 @@ begin
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
\ No newline at end of file
----------------------------------------------------------------------------------------------------
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
action = "simulation"
target = "xilinx"
fetchto = "../../ip_cores"
vlog_opt="+incdir+../../sim/wb +incdir+../../sim/vme64x_bfm +incdir+../../sim"
files = [ "main.sv" ]
modules = { "local" : [ "../../top/svec" ] }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment