1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;
entity fifo_reader is
port (
clock : in std_logic ;
reset : in std_logic ;
enable : in std_logic ;
usb_speed : in std_logic ;
meta_en : in std_logic ;
timestamp : in unsigned(63 downto 0);
fifo_usedw : in std_logic_vector(11 downto 0);
fifo_read : buffer std_logic ;
fifo_empty : in std_logic ;
fifo_data : in std_logic_vector(31 downto 0) ;
meta_fifo_usedw : in std_logic_vector(2 downto 0);
meta_fifo_read : buffer std_logic ;
meta_fifo_empty : in std_logic ;
meta_fifo_data : in std_logic_vector(127 downto 0) ;
out_i : buffer signed(15 downto 0) ;
out_q : buffer signed(15 downto 0) ;
out_valid : buffer std_logic ;
underflow_led : buffer std_logic ;
underflow_count : buffer unsigned(63 downto 0) ;
underflow_duration : in unsigned(15 downto 0)
) ;
end entity ;
architecture simple of fifo_reader is
signal underflow_detected : std_logic ;
signal meta_time_go : std_logic ;
signal meta_time_eq : std_logic ;
signal meta_time_hit : signed(15 downto 0) ;
signal meta_p_time : unsigned(63 downto 0);
signal meta_loaded : std_logic;
begin
process(clock, reset, meta_fifo_empty, meta_fifo_usedw)
begin
if (reset = '1') then
meta_loaded <= '0';
meta_p_time <= (others => '0');
meta_fifo_read <= '0' ;
elsif( rising_edge(clock) ) then
meta_fifo_read <= '0';
if( meta_loaded = '0' ) then
if( meta_fifo_empty = '0' ) then
meta_p_time <= unsigned(meta_fifo_data(95 downto 32));
meta_loaded <= '1';
meta_fifo_read <= '1';
end if;
else
if (meta_time_eq = '1') then
meta_loaded <= '0';
end if;
end if;
end if;
end process;
meta_time_eq <= '1' when (enable = '1' and meta_loaded = '1' and ((meta_p_time = 0 and meta_time_hit = 0) or (timestamp >= meta_p_time and meta_p_time /= 0))) else '0';
process(clock, reset)
begin
if (reset = '1') then
meta_time_hit <= (others => '0');
elsif(rising_edge(clock)) then
if (meta_time_eq = '1') then
if (usb_speed = '0') then
meta_time_hit <= to_signed(1015, meta_time_hit'length);
else
meta_time_hit <= to_signed(503, meta_time_hit'length);
end if;
else
if (meta_time_hit > 0) then
meta_time_hit <= meta_time_hit - 1;
end if;
end if;
end if;
end process;
meta_time_go <= '1' when (meta_en = '1' and (meta_time_eq = '1' or meta_time_hit > 0 )) else '0';
-- Assumes we want to read every other clock cycle
read_fifo : process( clock, reset )
begin
if( reset = '1' ) then
fifo_read <= '0' ;
elsif( rising_edge( clock ) ) then
fifo_read <= '0' ;
if( enable = '1' ) then
if( fifo_read = '0' and fifo_empty = '0' ) then
if (meta_en = '0' or (meta_en = '1' and meta_time_go = '1')) then
fifo_read <= '1' ;
end if;
end if ;
else
fifo_read <= '0' ;
end if ;
end if ;
end process ;
register_out_valid : process(clock, reset)
constant COUNT_RESET : natural := 11 ;
variable prev_enable : std_logic := '0' ;
variable downcount : natural range 0 to COUNT_RESET := COUNT_RESET ;
begin
if( reset = '1' ) then
out_valid <= '0' ;
prev_enable := '0' ;
downcount := COUNT_RESET ;
elsif( rising_edge(clock) ) then
if( fifo_empty = '1' ) then
out_i <= (others =>'0') ;
out_q <= (others =>'0') ;
else
out_i <= resize(signed(fifo_data(11 downto 0)),out_i'length) ;
out_q <= resize(signed(fifo_data(27 downto 16)),out_q'length) ;
end if ;
if( enable = '1' ) then
if( downcount > 0 ) then
if( downcount mod 2 = 1 ) then
out_valid <= '1' ;
else
out_valid <= '0' ;
end if ;
downcount := downcount - 1 ;
else
out_valid <= fifo_read ;
end if ;
else
downcount := COUNT_RESET ;
end if ;
prev_enable := enable ;
end if ;
end process ;
-- Underflow detection
detect_underflows : process( clock, reset )
begin
if( reset = '1' ) then
underflow_detected <= '0' ;
elsif( rising_edge( clock ) ) then
underflow_detected <= '0' ;
if( enable = '1' and fifo_empty = '1' and (meta_en = '0' or (meta_en = '1' and meta_time_go = '1')) ) then
underflow_detected <= '1' ;
end if ;
end if ;
end process ;
-- Count the number of times we underflow, but only if they are discontinuous
-- meaning we have an underflow condition, a non-underflow condition, then
-- another underflow condition counts as 2 underflows, but an underflow condition
-- followed by N underflow conditions counts as a single underflow condition.
count_underflows : process( clock, reset )
variable prev_underflow : std_logic := '0' ;
begin
if( reset = '1' ) then
prev_underflow := '0' ;
underflow_count <= (others =>'0') ;
elsif( rising_edge( clock ) ) then
if( prev_underflow = '0' and underflow_detected = '1' ) then
underflow_count <= underflow_count + 1 ;
end if ;
prev_underflow := underflow_detected ;
end if ;
end process ;
-- Active high assertion for underflow_duration when the underflow
-- condition has been detected. The LED will stay asserted
-- if multiple underflows have occurred
blink_underflow_led : process( clock, reset )
variable downcount : natural range 0 to 2**underflow_duration'length-1 ;
begin
if( reset = '1' ) then
downcount := 0 ;
underflow_led <= '0' ;
elsif( rising_edge(clock) ) then
-- Default to not being asserted
underflow_led <= '0' ;
-- Countdown so we can see what happened
if( downcount > 0 ) then
downcount := downcount - 1 ;
underflow_led <= '1' ;
end if ;
-- Underflow occurred so light it up
if( underflow_detected = '1' ) then
downcount := to_integer(underflow_duration) ;
end if ;
end if ;
end process ;
end architecture ;
|