File: fifo_reader.vhd

package info (click to toggle)
bladerf 0.2017.12~rc1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 14,620 kB
  • sloc: ansic: 50,123; vhdl: 12,873; python: 1,062; tcl: 1,060; xml: 1,017; makefile: 657; sh: 589; csh: 18; cpp: 9
file content (201 lines) | stat: -rw-r--r-- 7,408 bytes parent folder | download | duplicates (3)
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 ;