OpenCores
URL https://opencores.org/ocsvn/viterbi_decoder_axi4s/viterbi_decoder_axi4s/trunk

Subversion Repositories viterbi_decoder_axi4s

[/] [viterbi_decoder_axi4s/] [trunk/] [src/] [ram_ctrl.vhd] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 mfehrenz
--!
2
--! Copyright (C) 2011 - 2012 Creonic GmbH
3
--!
4
--! This file is part of the Creonic Viterbi Decoder, which is distributed
5
--! under the terms of the GNU General Public License version 2.
6
--!
7
--! @file
8
--! @brief  Viterbi decoder RAM control
9
--! @author Markus Fehrenz
10
--! @date   2011/12/13
11
--!
12
--! @details Manage RAM behavior. Write and read data.
13
--! The decisions are sent to the traceback units
14
--! It is signaled if the data belongs to acquisition or window phase.
15
--!
16
 
17
library ieee;
18
use ieee.std_logic_1164.all;
19
use ieee.numeric_std.all;
20
 
21
library dec_viterbi;
22
use dec_viterbi.pkg_param.all;
23
use dec_viterbi.pkg_param_derived.all;
24
use dec_viterbi.pkg_types.all;
25
use dec_viterbi.pkg_components.all;
26
 
27
 
28
entity ram_ctrl is
29
        port(
30
        clk       : in std_logic;
31
        rst       : in std_logic;
32
 
33
 
34
        --
35
        -- Slave data signals, delivers the LLR parity values.
36
        --
37
        s_axis_input_tvalid : in  std_logic;
38
        s_axis_input_tdata  : in  std_logic_vector(NUMBER_TRELLIS_STATES - 1 downto 0);
39
        s_axis_input_tlast  : in  std_logic;
40
        s_axis_input_tready : out std_logic;
41
 
42
 
43
        --
44
        -- Master data signals for traceback units, delivers the decision vectors.
45
        --
46
        m_axis_output_tvalid       : out std_logic_vector(1 downto 0);
47
        m_axis_output_tdata        : out t_ram_rd_data;
48
        m_axis_output_tlast        : out std_logic_vector(1 downto 0);
49
        m_axis_output_tready       : in  std_logic_vector(1 downto 0);
50
 
51
        -- Signals the traceback unit when the decision bits do not belong to an acquisition.
52
        m_axis_output_window_tuser : out std_logic_vector(1 downto 0);
53
 
54
        -- Signals whether this is the last decision vector of the window.
55
        m_axis_output_last_tuser   : out std_logic_vector(1 downto 0);
56
 
57
 
58
        --
59
        -- Slave configuration signals, delivering the configuration data.
60
        --
61
 
62
        s_axis_ctrl_tvalid : in  std_logic;
63
        s_axis_ctrl_tdata  : in  std_logic_vector(31 downto 0);
64
        s_axis_ctrl_tready : out std_logic
65
);
66
end entity ram_ctrl;
67
 
68
 
69
architecture rtl of ram_ctrl is
70
 
71
        ------------------------
72
        -- Type definition
73
        ------------------------
74
 
75
        --
76
        -- Record contains runtime configuration.
77
        -- The input configuration is stored in a register.
78
        -- It is received from a AXI4-Stream interface from the top entity.
79
        --
80
        -- We just receive window_length and acquisition_length from the outside. All
81
        -- other values are computed internally in order to impreove timing of the core:
82
        -- m denotes minus,
83
        -- p denotes plus.
84
        --
85
        type trec_runtime_param is record
86
                window_length           : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
87
                acquisition_length      : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
88
                window_p_acquisition    : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
89
                window_p_acquisition_m1 : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
90
                window_p_acquisition_m2 : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
91
                window_p_acquisition_m3 : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
92
                window_m1               : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
93
        end record trec_runtime_param;
94
 
95
        -- Types for finite state machines
96
        type t_ram_ctrl is (CONFIGURE, START, BEGINNING, RUNNING, ENDING);
97
 
98
        -- RAM controling types
99
        type t_ram_data    is array (3 downto 0) of std_logic_vector(NUMBER_TRELLIS_STATES - 1 downto 0);
100
        type t_ram_addr    is array (3 downto 0) of unsigned(BW_MAX_WINDOW_LENGTH - 1  downto 0);
101
        type t_ram_rd_addr is array (1 downto 0) of unsigned(BW_MAX_WINDOW_LENGTH - 1  downto 0);
102
        type t_ram_ptr     is array (1 downto 0) of unsigned(1 downto 0);
103
        type t_ram_ptr_int is array (1 downto 0) of integer range 3 downto 0;
104
 
105
        type t_ram_data_cnt is array (1 downto 0) of integer range 2 * MAX_WINDOW_LENGTH downto 0;
106
 
107
 
108
        ------------------------
109
        -- Signal declaration
110
        ------------------------
111
 
112
        signal config          : trec_runtime_param;
113
        signal ram_ctrl_fsm    : t_ram_ctrl;
114
        signal en_ram, wen_ram : std_logic_vector(3 downto 0);
115
        signal addr            : t_ram_addr;
116
        signal d               : std_logic_vector(NUMBER_TRELLIS_STATES - 1 downto 0);
117
        signal q               : t_ram_rd_data;
118
        signal q_reg           : t_ram_data;
119
 
120
        -- ram addess, number and data pointer
121
        signal write_ram_ptr                                : unsigned(1 downto 0);
122
        signal read_ram_ptr, read_ram_data_ptr              : t_ram_ptr;
123
        signal read_ram_data_ptr_d1                         : t_ram_ptr;
124
        signal write_addr_ptr, read_addr_ptr, last_addr_ptr : unsigned(BW_MAX_WINDOW_LENGTH - 1 downto 0);
125
 
126
        -- control flags
127
        signal switch_ram, switch_state, ram_writing : boolean;
128
 
129
        -- internal signals of outputs
130
        signal m_axis_output_tvalid_int     : std_logic_vector(1 downto 0);
131
        signal m_axis_output_last_tuser_int : std_logic_vector(1 downto 0);
132
        signal s_axis_input_tready_int      : std_logic;
133
 
134
        -- delay signals of inputs
135
        signal m_axis_output_tvalid_d1, m_axis_output_tvalid_d2  : std_logic_vector(1 downto 0);
136
 
137
        signal next_traceback, not_next_traceback : integer range 1 downto 0;
138
        signal data_cnt                           : t_ram_data_cnt;
139
 
140
begin
141
 
142
        s_axis_input_tready     <= '1' when (m_axis_output_tready = "11" or m_axis_output_tvalid_int(0) = '0'
143
                                             or m_axis_output_tvalid_int(1) = '0')
144
                                             and ram_ctrl_fsm /= CONFIGURE and ram_ctrl_fsm /= ENDING else
145
                                   '0';
146
 
147
        s_axis_input_tready_int <= '1' when (m_axis_output_tready = "11" or m_axis_output_tvalid_int(0) = '0'
148
                                             or m_axis_output_tvalid_int(1) = '0')
149
                                             and ram_ctrl_fsm /= CONFIGURE and ram_ctrl_fsm /= ENDING else
150
                                   '0';
151
 
152
        m_axis_output_last_tuser <= m_axis_output_last_tuser_int;
153
        m_axis_output_tvalid     <= m_axis_output_tvalid_int;
154
        m_axis_output_tdata      <= q;
155
 
156
 
157
        --
158
        -- Statemachine handles configuration, write/read to/from ram
159
        -- and forwarding decision vectors to corresponding traceback units
160
        --
161
 
162
        pr_ctrl_ram : process(clk, write_ram_ptr, read_ram_ptr) is
163
                variable v_write_ram_ptr : integer range 3 downto 0;
164
                variable v_read_ram_ptr  : t_ram_ptr_int;
165
        begin
166
        v_write_ram_ptr   := to_integer(write_ram_ptr);
167
        v_read_ram_ptr(0) := to_integer(read_ram_ptr(0));
168
        v_read_ram_ptr(1) := to_integer(read_ram_ptr(1));
169
        if rising_edge(clk) then
170
                if rst = '1' then
171
                        ram_ctrl_fsm              <= CONFIGURE;
172
 
173
                        config.window_length      <= (others => '0');
174
                        config.acquisition_length <= (others => '0');
175
 
176
                        en_ram                    <= (others => '1');
177
                        wen_ram                   <= (others => '0');
178
                        addr                      <= (others => (others => '0'));
179
 
180
                        write_ram_ptr             <= to_unsigned(0, 2);
181
                        write_addr_ptr            <= (others => '0');
182
                        last_addr_ptr             <= (others => '0');
183
 
184
                        read_ram_ptr              <= (to_unsigned(2, 2), to_unsigned(3, 2));
185
                        read_ram_data_ptr         <= (to_unsigned(2, 2), to_unsigned(3, 2));
186
                        read_ram_data_ptr_d1      <= (to_unsigned(2, 2), to_unsigned(3, 2));
187
                        read_addr_ptr             <= (others => '0');
188
                        next_traceback            <= 0;
189
                        not_next_traceback        <= 1;
190
 
191
                        switch_ram                <= false;
192
                        switch_state              <= false;
193
                        ram_writing               <= true;
194
 
195
                        m_axis_output_last_tuser_int     <= (others => '0');
196
                        m_axis_output_window_tuser       <= (others => '0');
197
                        m_axis_output_tvalid_int  <= (others => '0');
198
                        m_axis_output_tvalid_d1   <= (others => '0');
199
                        m_axis_output_tvalid_d2   <= (others => '0');
200
                        m_axis_output_tlast       <= (others => '0');
201
                        s_axis_ctrl_tready        <= '1';
202
                else
203
                        addr(v_write_ram_ptr)   <= write_addr_ptr;
204
                        addr(v_read_ram_ptr(0)) <= read_addr_ptr;
205
                        addr(v_read_ram_ptr(1)) <= read_addr_ptr;
206
 
207
                        d <= s_axis_input_tdata;
208
 
209
                        q(0)   <= q_reg(to_integer(read_ram_data_ptr(0)));
210
                        q(1)   <= q_reg(to_integer(read_ram_data_ptr(1)));
211
 
212
                        case ram_ctrl_fsm is
213
 
214
                        --
215
                        -- It is necessary to configure the decoder before each block
216
                        -- The decoder is always ready to receive on the ctrl channel, when it is in this state
217
                        --
218
                        when CONFIGURE =>
219
                                if s_axis_ctrl_tvalid = '1' then
220
                                        config.window_length      <= unsigned(s_axis_ctrl_tdata(BW_MAX_WINDOW_LENGTH - 1 + 16 downto 16));
221
                                        config.acquisition_length <= unsigned(s_axis_ctrl_tdata(BW_MAX_WINDOW_LENGTH - 1      downto  0));
222
                                        ram_ctrl_fsm <= START;
223
                                        wen_ram(v_write_ram_ptr) <= '1';
224
                                        s_axis_ctrl_tready <= '0';
225
                                end if;
226
 
227
                        --
228
                        -- After the decoder is configured, the decoder is waiting for a new block
229
                        -- When the AXIS handshake is there the packettransmission begins
230
                        --
231
                        when START =>
232
                                if s_axis_input_tvalid = '1' and s_axis_input_tready_int = '1' then
233
                                        ram_ctrl_fsm             <= BEGINNING;
234
                                        write_addr_ptr           <= write_addr_ptr + 1;
235
                                        read_ram_ptr(next_traceback)                     <= write_ram_ptr - 1;
236
                                        read_ram_ptr(not_next_traceback)                 <= write_ram_ptr - 2;
237
                                else
238
                                        write_addr_ptr                 <= config.window_length - config.acquisition_length;
239
 
240
                                        config.window_p_acquisition    <= config.window_length + config.acquisition_length;
241
                                        config.window_p_acquisition_m1 <= config.window_length + config.acquisition_length - 1;
242
                                        config.window_p_acquisition_m2 <= config.window_length + config.acquisition_length - 2;
243
                                        config.window_p_acquisition_m3 <= config.window_length + config.acquisition_length - 3;
244
                                        config.window_m1               <= config.window_length - 1;
245
                                end if;
246
 
247
                        --
248
                        -- The first arriving data have to be stored on special locations to guarantee
249
                        -- a non malicious behavior of the traceback units.
250
                        --
251
                        when BEGINNING =>
252
                                if s_axis_input_tvalid = '1' and s_axis_input_tready_int = '1' then
253
                                        if switch_ram then
254
                                                ram_ctrl_fsm <= RUNNING;
255
                                                wen_ram(to_integer(unsigned(write_ram_ptr - 1))) <= '0';
256
                                                wen_ram(v_write_ram_ptr)                         <= '1';
257
                                                write_addr_ptr                                   <= write_addr_ptr + 1;
258
                                                read_addr_ptr                                    <= read_addr_ptr  - 1;
259
                                                switch_ram                                       <= false;
260
                                        else
261
                                                if write_addr_ptr = config.window_m1 then
262
                                                        write_addr_ptr <= to_unsigned(0, BW_MAX_WINDOW_LENGTH);
263
                                                        read_addr_ptr  <= config.window_m1;
264
                                                        write_ram_ptr  <= write_ram_ptr + 1;
265
                                                        switch_ram     <= true;
266
                                                else
267
                                                        write_addr_ptr <= write_addr_ptr + 1;
268
                                                end if;
269
                                        end if;
270
                                end if;
271
 
272
                        --
273
                        -- The running state handles the most decoding
274
                        -- It handels the writing of forward to ram and reading the decision vecotors
275
                        -- the decision vecotrs are forwarded to the traceback units.
276
                        --
277
                        when RUNNING =>
278
                                if (s_axis_input_tvalid = '1' and s_axis_input_tready_int = '1' and ram_writing) or
279
                                   ((m_axis_output_tready(0) = '1' and m_axis_output_tready(1) = '1') and not(ram_writing)) then
280
 
281
                                        read_ram_data_ptr_d1 <= read_ram_ptr;
282
                                        read_ram_data_ptr    <= read_ram_data_ptr_d1;
283
                                        m_axis_output_tvalid_int <= m_axis_output_tvalid_d1;
284
                                        m_axis_output_tvalid_d1  <= m_axis_output_tvalid_d2;
285
 
286
                                        if switch_ram then
287
                                                if ram_writing then
288
                                                        wen_ram(to_integer(unsigned(write_ram_ptr - 1))) <= '0';
289
                                                        wen_ram(v_write_ram_ptr)                         <= '1';
290
                                                        next_traceback                                   <= not_next_traceback;
291
                                                        not_next_traceback                               <= next_traceback;
292
                                                else
293
                                                        ram_ctrl_fsm <= ENDING;
294
                                                        ram_writing <= true;
295
                                                        wen_ram(to_integer(unsigned(write_ram_ptr - 1))) <= '0';
296
                                                end if;
297
                                                switch_ram      <= false;
298
                                        else
299
                                                if write_addr_ptr = config.window_m1 then
300
                                                        write_ram_ptr                    <= write_ram_ptr + 1;
301
                                                        read_ram_ptr(next_traceback)     <= write_ram_ptr;
302
                                                        read_ram_ptr(not_next_traceback) <= write_ram_ptr - 2;
303
                                                        switch_ram                       <= true;
304
                                                        data_cnt(next_traceback)         <= 0;
305
                                                end if;
306
                                        end if;
307
 
308
                                        -- Store last RAM address and stop writing after last bit of a block arrives
309
                                        if s_axis_input_tlast = '1' then
310
                                                ram_writing              <= false;
311
                                                last_addr_ptr            <= write_addr_ptr;
312
--                                              wen_ram(v_write_ram_ptr) <= '0';
313
                                        end if;
314
 
315
                                        -- Handle RAM addess point increase and reset
316
                                        if write_addr_ptr = config.window_m1 then
317
                                                write_addr_ptr <= to_unsigned(0, BW_MAX_WINDOW_LENGTH);
318
                                                read_addr_ptr  <= config.window_m1;
319
                                        else
320
                                                write_addr_ptr <= write_addr_ptr + 1;
321
                                                read_addr_ptr  <= read_addr_ptr  - 1;
322
                                        end if;
323
 
324
                                        -- Handle side channel information for traceback units.
325
                                        for i in 1 downto 0 loop
326
                                                if m_axis_output_tvalid_d1(i) = '1' then
327
                                                        data_cnt(i) <= data_cnt(i) + 1;
328
                                                end if;
329
 
330
                                                -- Signals the valid signal
331
                                                if data_cnt(i) = config.window_p_acquisition_m2 then
332
                                                        m_axis_output_tvalid_d2(i)              <= '0';
333
                                                end if;
334
                                                if switch_ram and ram_writing then
335
                                                        m_axis_output_tvalid_d2(next_traceback) <= '1';
336
                                                end if;
337
 
338
                                                -- Signals the end of the current window
339
                                                if m_axis_output_last_tuser_int(i) = '1' then
340
                                                        m_axis_output_last_tuser_int(i) <= '0';
341
                                                end if;
342
                                                if data_cnt(i) = config.window_p_acquisition_m1 then
343
                                                        m_axis_output_last_tuser_int(i) <= '1';
344
                                                end if;
345
 
346
                                                -- Signals, whether there is acquisition or window
347
                                                if data_cnt(i) = config.window_p_acquisition then
348
                                                        m_axis_output_window_tuser(i) <= '0';
349
                                                end if;
350
                                                if data_cnt(i) = config.acquisition_length then
351
                                                        m_axis_output_window_tuser(i) <= '1';
352
                                                end if;
353
                                        end loop;
354
                                end if;
355
 
356
                        --
357
                        -- Handle last traceback with no acquisition
358
                        -- Maybe the resulting window is longer than others
359
                        --
360
                        when ENDING =>
361
                                if m_axis_output_tready(0) = '1' and m_axis_output_tready(1) = '1' then
362
 
363
                                        read_ram_data_ptr_d1     <= read_ram_ptr;
364
                                        read_ram_data_ptr        <= read_ram_data_ptr_d1;
365
                                        m_axis_output_tvalid_int <= m_axis_output_tvalid_d1;
366
 
367
                                        for i in 1 downto 0 loop
368
                                                if m_axis_output_tvalid_int(i) = '1' then
369
                                                        data_cnt(i) <= data_cnt(i) + 1;
370
                                                end if;
371
                                        end loop;
372
 
373
                                        if data_cnt(not_next_traceback) = config.window_p_acquisition_m3 then
374
                                                read_addr_ptr <= last_addr_ptr;
375
                                        elsif read_addr_ptr = 0 then
376
                                                read_ram_ptr(0) <= read_ram_ptr(0) - 1;
377
                                                read_ram_ptr(1) <= read_ram_ptr(1) - 1;
378
                                                read_addr_ptr   <= config.window_m1;
379
                                        else
380
                                                read_addr_ptr <= read_addr_ptr  - 1;
381
                                        end if;
382
 
383
                                        if data_cnt(not_next_traceback) =  config.window_p_acquisition_m1 then
384
                                                m_axis_output_last_tuser_int(not_next_traceback) <= '1';
385
                                                m_axis_output_tvalid_d1(next_traceback)          <= '1';
386
                                                m_axis_output_tvalid_d1(not_next_traceback)     <= '0';
387
                                        end if;
388
 
389
                                        if data_cnt(not_next_traceback) = config.window_p_acquisition then
390
                                                m_axis_output_window_tuser(not_next_traceback)  <= '0';
391
                                                m_axis_output_window_tuser(next_traceback) <= '1';
392
                                        end if;
393
 
394
                                        if data_cnt(not_next_traceback) = config.acquisition_length then
395
                                                m_axis_output_window_tuser(not_next_traceback) <= '1';
396
                                        end if;
397
 
398
                                        if m_axis_output_last_tuser_int(not_next_traceback) = '1' then
399
                                                m_axis_output_last_tuser_int(not_next_traceback) <= '0';
400
                                        end if;
401
 
402
                                        if data_cnt(next_traceback) = last_addr_ptr + config.acquisition_length - 1 then
403
                                                m_axis_output_tvalid_d1(next_traceback)      <= '0';
404
                                                m_axis_output_last_tuser_int(next_traceback) <= '1';
405
                                                m_axis_output_tlast(next_traceback)          <= '1';
406
                                                switch_state                                 <= true;
407
                                        end if;
408
 
409
                                        -- block is finished and the decoder is ready for a new configuration and block
410
                                        if switch_state then
411
                                                switch_state                 <= false;
412
                                                m_axis_output_last_tuser_int <= "00";
413
                                                m_axis_output_window_tuser   <= "00";
414
                                                m_axis_output_tlast          <= "00";
415
                                                ram_ctrl_fsm                 <= CONFIGURE;
416
                                                s_axis_ctrl_tready           <= '1';
417
                                                data_cnt(0)                  <= 0;
418
                                                data_cnt(1)                  <= 0;
419
                                                m_axis_output_tvalid_int  <= (others => '0');
420
                                                m_axis_output_tvalid_d1   <= (others => '0');
421
                                                m_axis_output_tvalid_d2   <= (others => '0');
422
                                        end if;
423
                                end if;
424
                        end case;
425
                end if;
426
        end if;
427
        end process pr_ctrl_ram;
428
 
429
 
430
        ------------------------------
431
        --- Portmapping components ---
432
        ------------------------------
433
 
434
        gen_generic_sp_ram : for i in 0 to 3 generate
435
        begin
436
                inst_generic_sp_ram : generic_sp_ram
437
        generic map(
438
                DISTR_RAM => DISTRIBUTED_RAM,
439
                WORDS     => MAX_WINDOW_LENGTH,
440
                BITWIDTH  => NUMBER_TRELLIS_STATES
441
        )
442
        port map(
443
                clk => clk,
444
                rst => rst,
445
                wen => wen_ram(i),
446
                en  => en_ram(i),
447
                a   => std_logic_vector(addr(i)),
448
                d   => d,
449
                q   => q_reg(i)
450
        );
451
        end generate gen_generic_sp_ram;
452
 
453
end architecture rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.