File: fifo_writer.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 (162 lines) | stat: -rw-r--r-- 6,213 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
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 ;