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
|
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;
entity fifo_writer 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);
in_i : in signed(15 downto 0) ;
in_q : in signed(15 downto 0) ;
in_valid : in std_logic ;
fifo_usedw : in std_logic_vector(11 downto 0) ;
fifo_clear : buffer std_logic ;
fifo_write : buffer std_logic ;
fifo_full : in std_logic ;
fifo_data : out std_logic_vector(31 downto 0) ;
meta_fifo_full : in std_logic;
meta_fifo_usedw : in std_logic_vector(4 downto 0);
meta_fifo_data : out std_logic_vector(127 downto 0);
meta_fifo_write : out std_logic;
overflow_led : buffer std_logic ;
overflow_count : buffer unsigned(63 downto 0) ;
overflow_duration : in unsigned(15 downto 0)
) ;
end entity ;
architecture simple of fifo_writer is
signal buf_enough : std_logic;
signal dma_buf_sz : signed(12 downto 0);
signal dma_downcount : signed(12 downto 0);
signal overflow_recovering : std_logic ;
signal overflow_detected : std_logic ;
signal meta_written : std_logic ;
signal meta_written_reg : std_logic ;
begin
dma_buf_sz <= to_signed(1015, dma_buf_sz'length) when usb_speed = '0' else to_signed(503, dma_buf_sz'length);
process( clock, reset)
begin
if( reset = '1') then
dma_downcount <= (others =>'0') ;
meta_written <= '0' ;
elsif( rising_edge( clock ) ) then
if (enable = '1' and meta_en = '1') then
if( dma_downcount > 0 ) then
dma_downcount <= dma_downcount - 1 ;
elsif ( to_signed(2**fifo_usedw'length,fifo_usedw'length+2) - (signed('0'&fifo_full&fifo_usedw)) > dma_buf_sz ) then
-- Guaranteed to be done downcounting here .. so only reset the downcount
-- if we are able to store that amount of samples in the downstream FIFO
if( meta_written = '1' or in_valid = '1' ) then
dma_downcount <= dma_buf_sz;
meta_written <= '1' ;
end if ;
else
meta_written <= '0' ;
end if;
else
dma_downcount <= (others =>'0') ;
meta_written <= '0' ;
end if;
end if;
end process;
buf_enough <= '1' when ( dma_downcount = (dma_buf_sz)) else '0';
meta_fifo_write <= '1' when (enable = '1' and meta_en = '1' and buf_enough = '1') else '0';
meta_fifo_data <= x"FFFFFFFF" & std_logic_vector(timestamp) & x"12344321";
meta_written_reg <= '0' when reset = '1' else meta_written when rising_edge(clock) ;
-- Simple concatenation of samples
fifo_data <= std_logic_vector(in_q & in_i) ;
fifo_write <= in_valid when overflow_recovering = '0' and fifo_full = '0' and (meta_en = '0' or meta_written_reg = '1') else '0' ;
-- Clear out the contents when RX is disabled
clear_fifo : process( clock, reset )
begin
if( reset = '1' ) then
fifo_clear <= '1' ;
elsif( rising_edge(clock) ) then
fifo_clear <= '0' ;
if( enable = '0' ) then
fifo_clear <= '1' ;
end if ;
end if ;
end process ;
-- Overflow detection
detect_overflows : process( clock, reset )
begin
if( reset = '1' ) then
overflow_detected <= '0' ;
elsif( rising_edge( clock ) ) then
overflow_detected <= '0' ;
if( enable = '1' and in_valid = '1' and fifo_full = '1' and fifo_clear = '0' ) then
overflow_detected <= '1' ;
end if ;
end if ;
end process ;
-- Count the number of times we overflow, but only if they are discontinuous
-- meaning we have an overflow condition, a non-overflow condition, then
-- another overflow condition counts as 2 overflows, but an overflow condition
-- followed by N overflow conditions counts as a single overflow condition.
count_overflows : process( clock, reset )
variable prev_overflow : std_logic := '0' ;
begin
if( reset = '1' ) then
prev_overflow := '0' ;
overflow_count <= (others =>'0') ;
overflow_recovering <= '0' ;
elsif( rising_edge( clock ) ) then
overflow_recovering <= '0' ;
if( prev_overflow = '0' and overflow_detected = '1' ) then
overflow_count <= overflow_count + 1 ;
overflow_recovering <= '1' ;
elsif( overflow_recovering = '1' ) then
if( fifo_full = '0' ) then
overflow_recovering <= '0' ;
end if ;
end if ;
prev_overflow := overflow_detected ;
end if ;
end process ;
-- Active high assertion for overflow_duration when the overflow
-- condition has been detected. The LED will stay asserted
-- if multiple overflows have occurred
blink_overflow_led : process( clock, reset )
variable downcount : natural range 0 to 2**overflow_duration'length-1 ;
begin
if( reset = '1' ) then
downcount := 0 ;
overflow_led <= '0' ;
elsif( rising_edge(clock) ) then
-- Default to not being asserted
overflow_led <= '0' ;
-- Countdown so we can see what happened
if( overflow_detected = '1' ) then
downcount := to_integer(overflow_duration) ;
elsif( downcount > 0 ) then
downcount := downcount - 1 ;
overflow_led <= '1' ;
end if ;
end if ;
end process ;
end architecture ;
|