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

Subversion Repositories viterbi_decoder_axi4s

[/] [viterbi_decoder_axi4s/] [trunk/] [testbench/] [tb_dec_viterbi.vhd] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 mfehrenz
--!
2 6 mfehrenz
--! Copyright (C) 2011 - 2014 Creonic GmbH
3 2 mfehrenz
--!
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  Generic Viterbi Decoder Testbench
9
--! @author Markus Fehrenz
10
--! @date   2011/12/05
11
--!
12
 
13
library ieee;
14
use ieee.std_logic_1164.all;
15
use ieee.numeric_std.all;
16
use std.textio.all;
17
 
18
library dec_viterbi;
19
use dec_viterbi.pkg_param.all;
20
use dec_viterbi.pkg_param_derived.all;
21
use dec_viterbi.pkg_types.all;
22
use dec_viterbi.pkg_helper.all;
23
use dec_viterbi.pkg_tb_fileio.all;
24
use dec_viterbi.txt_util.all;
25
 
26
 
27
entity tb_dec_viterbi is
28
        generic(
29
                CLK_PERIOD         : time    := 10 ns;   -- Clock period within simulation.
30
 
31
                BLOCK_LENGTH_START : natural := 200;     -- First block length to simulate.
32 6 mfehrenz
                BLOCK_LENGTH_END   : natural := 500;     -- Last block length to simulate.
33
                BLOCK_LENGTH_INCR  : integer := 20;       -- Increment from one block length to another.
34 2 mfehrenz
 
35
                SIM_ALL_BLOCKS     : boolean := true;  -- Set to true in order to simulate all blocks within a data file.
36 6 mfehrenz
                SIM_BLOCK_START    : natural := 0;      -- If SIM_ALL_BLOCKS = false, gives block to start simulation with.
37
                SIM_BLOCK_END      : natural := 10;      -- If SIM_ALL_BLOCKS = false, gives last block of simulation.
38 2 mfehrenz
 
39
                WINDOW_LENGTH      : natural := 55;     -- Window length to use for simulation.
40
                ACQUISITION_LENGTH : natural := 50;     -- Acquisition length to use for simulation.
41
 
42 5 mfehrenz
                DATA_DIRECTORY     : string  := "../testbench/WiFi_121_91/" -- Path to testbench data, relative to simulation directory.
43 2 mfehrenz
        );
44
end entity tb_dec_viterbi;
45
 
46
 
47
architecture sim of tb_dec_viterbi is
48
 
49
        component dec_viterbi is
50
        port(
51
                aclk      : in std_logic;
52
                aresetn   : in std_logic;
53
 
54
                s_axis_input_tvalid : in std_logic;
55
                s_axis_input_tdata  : in std_logic_vector(31 downto 0);
56
                s_axis_input_tlast  : in std_logic;
57
                s_axis_input_tready : out std_logic;
58
 
59
                m_axis_output_tvalid : out std_logic;
60
                m_axis_output_tdata  : out std_logic;
61
                m_axis_output_tlast  : out std_logic;
62
                m_axis_output_tready : in std_logic;
63
 
64
                s_axis_ctrl_tvalid : in std_logic;
65
                s_axis_ctrl_tdata  : in std_logic_vector(31 downto 0);
66
                s_axis_ctrl_tlast  : in std_logic;
67
                s_axis_ctrl_tready : out std_logic
68
        );
69
        end component dec_viterbi;
70
 
71
        signal clk     : std_logic := '0';
72
        signal aresetn : std_logic;
73
 
74
        signal m_axis_input_tvalid : std_logic;
75
        signal m_axis_input_tlast  : std_logic;
76
        signal m_axis_input_tready : std_logic;
77
        signal m_axis_input_tdata  : std_logic_vector(31 downto 0);
78
 
79
        signal s_axis_output_tvalid : std_logic;
80
        signal s_axis_output_tlast  : std_logic;
81
        signal s_axis_output_tready : std_logic;
82
        signal s_axis_output_tdata  : std_logic;
83
 
84
        signal m_axis_ctrl_tvalid : std_logic;
85
        signal m_axis_ctrl_tlast  : std_logic;
86
        signal m_axis_ctrl_tready : std_logic;
87
        signal m_axis_ctrl_tdata  : std_logic_vector(31 downto 0);
88
 
89
 
90
        --
91
        -- Input data send signals.
92
        --
93
 
94 6 mfehrenz
        type t_send_data_fsm is (READ_FILE, CONFIGURE, SEND_DATA, DEASSERT_VALID, SEND_DATA_FINISHED, SEND_FIRST_DATA);
95 2 mfehrenz
        signal send_data_fsm : t_send_data_fsm;
96
 
97
        signal block_send_end   : natural;
98
 
99
        signal current_block             : natural;
100
        signal current_block_length      : natural;
101
        signal current_block_length_tail : natural;
102
 
103
 
104
        --
105
        -- Output comparison signals.
106
        --
107
 
108
        signal sys_bit_counter : natural;
109
        signal decoded_hardware : std_logic_vector(0 to max(BLOCK_LENGTH_START, BLOCK_LENGTH_END));
110
 
111
        signal block_receive_complete : boolean;
112
        signal new_block_length       : boolean;
113
 
114
        signal first_block_out            : natural;
115
        signal last_block_out             : natural;
116
        signal current_block_out          : natural;
117
        signal current_block_length_out   : natural;
118
        signal sys_bit_counter_out        : natural;
119
 
120
 
121
        -- Get filename that matches to our current configuration.
122
        function get_filename_part(v_block_length       : natural;
123
                                   v_window_length      : natural;
124
                                   v_acquisition_length : natural) return string is
125
 
126
        begin
127
                return "BL_" & str(v_block_length) & "_WL_" & str(v_window_length) & "_AL_" & str(v_acquisition_length);
128
        end function get_filename_part;
129
 
130
        shared variable v_decoded_software : t_nat_array_ptr;
131
 
132 6 mfehrenz
        signal valid_cnt : natural :=0;
133
        signal ready_cnt : natural :=0;
134 2 mfehrenz
begin
135
 
136
        clk <= not clk after CLK_PERIOD / 2;
137
 
138
 
139
        -- initial reset
140
        pr_reset : process is
141
        begin
142
                aresetn <= '0';
143
                wait for 2 * CLK_PERIOD;
144
                aresetn <= '1';
145
                wait;
146
        end process;
147
 
148
 
149
        -- Configuration and sending data to the core.
150
        pr_send : process(clk) is
151
                variable v_llr          : t_int_array_ptr;
152
                variable v_filepart_ptr : t_string_ptr;
153
                variable v_filename_ptr : t_string_ptr;
154
                variable v_num_lines    : natural := 0;
155
                variable v_num_blocks   : natural := 0;
156
        begin
157
        if rising_edge(clk) then
158
                if aresetn = '0' then
159
 
160
                        --  ctrl_tlast is present but unused in the decoder
161
                        m_axis_ctrl_tlast  <= '0';
162
                        m_axis_ctrl_tvalid <= '0';
163
                        m_axis_ctrl_tdata  <= (others => '0');
164
 
165
                        m_axis_input_tlast  <= '0';
166
                        m_axis_input_tvalid <= '0';
167
                        m_axis_input_tdata  <= (others => '0');
168
 
169
                        current_block_length      <= BLOCK_LENGTH_START;
170
                        current_block_length_tail <= BLOCK_LENGTH_START + ENCODER_MEMORY_DEPTH;
171
                        current_block    <= 0;
172
                        block_send_end   <= 0;
173
                        sys_bit_counter  <= 0;
174
 
175
                        send_data_fsm <= READ_FILE;
176 6 mfehrenz
                        valid_cnt <= 0;
177 2 mfehrenz
 
178
                else
179
 
180
                        case send_data_fsm is
181
 
182
 
183
                                --
184
                                -- For each block length we have a different file as reference data.
185
                                -- Read it when all requested blocks of a file were simulated,
186
                                -- or when we start the simulation.
187
                                --
188
                                when READ_FILE =>
189
 
190
                                        -- Read the appropriate file
191
                                        v_filepart_ptr := new string'(get_filename_part(current_block_length, WINDOW_LENGTH, ACQUISITION_LENGTH));
192
                                        v_filename_ptr := new string'(DATA_DIRECTORY & "llr_" &  v_filepart_ptr.all & "_in.txt");
193
                                        v_num_lines := get_num_lines(v_filename_ptr.all);
194
                                        read_file(v_llr, v_num_lines, BW_LLR_INPUT, v_filename_ptr.all);
195
 
196
                                        -- NUMBER_PARITY_BITS lines are stored in the file per payload bit!
197
                                        v_num_blocks := v_num_lines / ((current_block_length_tail) * NUMBER_PARITY_BITS);
198
 
199
                                        -- Determine the blocks to simulate.
200
                                        if SIM_ALL_BLOCKS then
201
                                                current_block    <= 0;
202
                                                block_send_end   <= v_num_blocks - 1;
203
                                        else
204
                                                current_block    <= SIM_BLOCK_START;
205
                                                block_send_end   <= SIM_BLOCK_END;
206
                                        end if;
207
                                        send_data_fsm <= CONFIGURE;
208
 
209
 
210
                                --
211
                                -- Configure the Viterbi decoder for every single block it has to process.
212
                                --
213
                                when CONFIGURE =>
214
 
215
                                        -- Set control data.
216
                                        m_axis_ctrl_tdata(16 + BW_MAX_WINDOW_LENGTH - 1 downto 16) <=
217
                                                std_logic_vector(to_unsigned(WINDOW_LENGTH, BW_MAX_WINDOW_LENGTH));
218
                                        m_axis_ctrl_tdata(     BW_MAX_WINDOW_LENGTH - 1 downto  0) <=
219
                                                std_logic_vector(to_unsigned(ACQUISITION_LENGTH, BW_MAX_WINDOW_LENGTH));
220
 
221
                                        -- Check whether configuration succeeded
222
                                        if m_axis_ctrl_tvalid = '1' and m_axis_ctrl_tready = '1' then
223
                                                m_axis_ctrl_tvalid <= '0';
224 6 mfehrenz
                                                send_data_fsm <= SEND_FIRST_DATA;
225
 
226 2 mfehrenz
                                        else
227
                                                m_axis_ctrl_tvalid <= '1';
228
                                        end if;
229
 
230 6 mfehrenz
                                when SEND_FIRST_DATA =>
231
                                        for j in 0 to NUMBER_PARITY_BITS - 1 loop
232
                                                m_axis_input_tdata(j * 8 + BW_LLR_INPUT - 1 downto j * 8) <=
233
                                                         std_logic_vector(to_signed(v_llr(current_block * (current_block_length_tail * NUMBER_PARITY_BITS) + sys_bit_counter * NUMBER_PARITY_BITS + j), BW_LLR_INPUT));
234
                                        end loop;
235
                                        sys_bit_counter <= sys_bit_counter + 1;
236
                                        send_data_fsm <= SEND_DATA;
237
                                        m_axis_input_tvalid <= '1';
238 2 mfehrenz
 
239
                                --
240
                                -- Send all data of a block. If we are done with this, we check what to do next:
241
                                -- 1) Configure the decoder to process the next block of the same length.
242
                                -- 2) Read a new file if all blocks of this block length were simulated.
243
                                -- 3) Quit simulation if all blocks of all block lengths were simulated.
244
                                --
245
                                when SEND_DATA =>
246
 
247
                                        m_axis_input_tvalid <= '1';
248
 
249
                                        -- Data transmission => increase bit counter and update data for next cycle.
250
                                        if m_axis_input_tvalid = '1' and m_axis_input_tready = '1' then
251 6 mfehrenz
                                                if valid_cnt = 5 then
252
                                                        valid_cnt <= 0;
253
                                                        send_data_fsm <= DEASSERT_VALID;
254
                                                        m_axis_input_tvalid <= '0';
255
                                                else
256
                                                        valid_cnt <= valid_cnt + 1;
257
                                                end if;
258
                                                sys_bit_counter <= sys_bit_counter + 1;
259 2 mfehrenz
                                        end if;
260
 
261
 
262 6 mfehrenz
                                        if m_axis_input_tvalid = '1' and m_axis_input_tready = '1' then
263
                                                if sys_bit_counter < current_block_length_tail then
264
                                                        -- trim and move data to stream
265
                                                        for j in 0 to NUMBER_PARITY_BITS - 1 loop
266
                                                                m_axis_input_tdata(j * 8 + BW_LLR_INPUT - 1 downto j * 8) <=
267
                                                                         std_logic_vector(to_signed(v_llr(current_block * (current_block_length_tail * NUMBER_PARITY_BITS) + sys_bit_counter * NUMBER_PARITY_BITS + j), BW_LLR_INPUT));
268
                                                        end loop;
269
                                                end if;
270 2 mfehrenz
 
271
 
272 6 mfehrenz
                                                -- Next data will be last of block
273
                                                if sys_bit_counter = current_block_length_tail - 1 then
274
                                                        m_axis_input_tlast <= '1';
275
                                                else
276
                                                        m_axis_input_tlast <= '0';
277
                                                end if;
278 2 mfehrenz
                                        end if;
279
 
280
                                        -- We have just sent the very last bit of this block.
281 6 mfehrenz
                                        if m_axis_input_tvalid = '1' and m_axis_input_tready = '1' and
282 2 mfehrenz
                                           m_axis_input_tlast  = '1' then
283
                                                sys_bit_counter <= 0;
284
                                                m_axis_input_tvalid <= '0';
285
 
286
                                                -- Did we process the last block of a block length?
287
                                                if current_block = block_send_end then
288
 
289
                                                        -- Go to next block length, if we are not done.
290
                                                        if current_block_length_tail = BLOCK_LENGTH_END + ENCODER_MEMORY_DEPTH then
291
                                                                send_data_fsm <= SEND_DATA_FINISHED;
292
                                                        else
293
                                                                send_data_fsm <= READ_FILE;
294
                                                                current_block_length   <= current_block_length + BLOCK_LENGTH_INCR;
295
                                                                current_block_length_tail   <= current_block_length + BLOCK_LENGTH_INCR + ENCODER_MEMORY_DEPTH;
296
                                                        end if;
297
                                                else
298
                                                        send_data_fsm <= CONFIGURE;
299
                                                        current_block <= current_block + 1;
300
                                                end if;
301
                                        end if;
302
 
303 6 mfehrenz
                        when DEASSERT_VALID =>
304
                                send_data_fsm <= SEND_DATA;
305 2 mfehrenz
 
306
                        --
307
                        -- We are done with all blocks, do nothing anynmore.
308
                        --
309
                        when SEND_DATA_FINISHED =>
310
 
311
                        end case;
312
                end if;
313
        end if;
314
        end process;
315
 
316
 
317
        --
318
        -- Process receives the decoded data from the Viterbi decoder
319
        -- The received data is compared to a test vector
320
        --
321
        pr_receive : process(clk) is
322
                variable v_filepart_ptr  : t_string_ptr;
323
                variable v_filename_ptr  : t_string_ptr;
324
                variable v_num_lines     : natural := 0;
325
        begin
326
        if rising_edge(clk) then
327
                if aresetn = '0' then
328
 
329
                        current_block_length_out   <= 0;
330
                        sys_bit_counter_out        <= 0;
331
                        s_axis_output_tready       <= '1';
332
                        block_receive_complete     <= false;
333
                        new_block_length           <= false;
334 6 mfehrenz
                        ready_cnt <= 0;
335 2 mfehrenz
 
336
                else
337
 
338
                        block_receive_complete     <= false;
339
                        new_block_length           <= false;
340 6 mfehrenz
                        s_axis_output_tready <= '1';
341 2 mfehrenz
 
342
                        -- Data passes the output interface.
343
                        if s_axis_output_tvalid = '1' and s_axis_output_tready = '1' then
344 6 mfehrenz
                                if ready_cnt = 8 then
345
                                        ready_cnt <= 0;
346
                                        s_axis_output_tready <= '0';
347
                                else
348
                                        ready_cnt <= ready_cnt + 1;
349
                                end if;
350 2 mfehrenz
 
351
                                decoded_hardware(sys_bit_counter_out) <= s_axis_output_tdata;
352
 
353
                                sys_bit_counter_out <= sys_bit_counter_out + 1;
354
 
355
                                -- This is the last bit of the flag.
356
                                if s_axis_output_tlast = '1' then
357
                                        block_receive_complete   <= true;
358
                                        current_block_length_out <= sys_bit_counter_out + 1;
359
                                        sys_bit_counter_out      <= 0;
360
 
361
                                        -- Block received and block length changed => read file of correct blocks.
362
                                        if current_block_length_out /= sys_bit_counter_out + 1 then
363
                                                new_block_length <= true;
364
                                                v_filepart_ptr := new string'(get_filename_part(sys_bit_counter_out + 1, WINDOW_LENGTH, ACQUISITION_LENGTH));
365
                                                v_filename_ptr := new string'(DATA_DIRECTORY & "decoded_" & v_filepart_ptr.all & "_out.txt");
366
                                                v_num_lines := get_num_lines(v_filename_ptr.all);
367
                                                read_file(v_decoded_software, v_num_lines, BW_LLR_INPUT, v_filename_ptr.all);
368
 
369
                                                if SIM_ALL_BLOCKS then
370
                                                        first_block_out <= 0;
371 6 mfehrenz
                                                        last_block_out  <= v_num_lines / (sys_bit_counter_out + 1) - 1;
372 2 mfehrenz
                                                else
373
                                                        first_block_out <= SIM_BLOCK_START;
374
                                                        last_block_out  <= SIM_BLOCK_END;
375
                                                end if;
376
 
377
                                        end if;
378
                                end if;
379
                        end if;
380
 
381
                end if; -- reset
382
        end if;
383
        end process pr_receive;
384
 
385
 
386
 
387
        --
388
        -- Compare the block we just received from the decoder with the data stored within the files.
389
        -- Stop simulation if everything was simulated.
390
        --
391
        pr_compare : process(clk) is
392
                variable v_bit_error_count : natural := 0;
393
                variable v_line_out        : line;
394
                variable v_current_block   : natural;
395
        begin
396
        if rising_edge(clk) then
397
                if aresetn = '0' then
398
 
399
                        current_block_out <= 0;
400
 
401
                else
402
 
403
                        -- Which is our current block?
404
                        if new_block_length then
405
                                v_current_block := first_block_out;
406
                        else
407
                                v_current_block := current_block_out;
408
                        end if;
409
 
410
                        -- We got a whole block from the decoder, compare whether decoding was successful.
411
                        if block_receive_complete then
412
 
413
                                for i in 0 to current_block_length_out - 1 loop
414
                                        if (v_decoded_software(v_current_block * current_block_length_out + i) = 0 and decoded_hardware(i) = '1') or
415
                                           (v_decoded_software(v_current_block * current_block_length_out + i) = 1 and decoded_hardware(i) = '0') then
416
 
417
                                                v_bit_error_count := v_bit_error_count + 1;
418
 
419
                                           assert false report "Decoded bit " & str(i) & " in block " & str(v_current_block) & " does not match!"
420 6 mfehrenz
                                                        severity failure;
421 2 mfehrenz
                                        end if;
422
                                end loop;
423
 
424
                                -- Dump message.
425
                                write(v_line_out, string'("Block length: ")  & str(current_block_length_out));
426 6 mfehrenz
                                write(v_line_out, string'(", Block: ")       & str(v_current_block));
427 2 mfehrenz
                                write(v_line_out, string'(", errors: ")      & str(v_bit_error_count));
428 6 mfehrenz
                                writeline(output, v_line_out);
429 2 mfehrenz
 
430 6 mfehrenz
                                current_block_out <= current_block_out + 1;
431
 
432
                                if current_block_out = last_block_out then
433 2 mfehrenz
                                        current_block_out <= 0;
434
 
435
                                        -- Stop simulation, if we are done with all blocks of all block lengths.
436
                                        if current_block_length_out = BLOCK_LENGTH_END then
437 6 mfehrenz
                                                 assert false report "Simulation finished with no errors." severity failure;
438 2 mfehrenz
                                        end if;
439
                                end if;
440
                        end if;
441
                end if;
442
        end if;
443
        end process pr_compare;
444
 
445
 
446
        inst_dec_viterbi : dec_viterbi
447
        port map(
448
                aclk => clk,
449
                aresetn => aresetn,
450
 
451
                s_axis_input_tvalid  => m_axis_input_tvalid,
452
                s_axis_input_tdata   => m_axis_input_tdata,
453
                s_axis_input_tlast   => m_axis_input_tlast,
454
                s_axis_input_tready  => m_axis_input_tready,
455
 
456
                m_axis_output_tvalid => s_axis_output_tvalid,
457
                m_axis_output_tdata  => s_axis_output_tdata,
458
                m_axis_output_tlast  => s_axis_output_tlast,
459
                m_axis_output_tready => s_axis_output_tready,
460
 
461
                s_axis_ctrl_tvalid   => m_axis_ctrl_tvalid,
462
                s_axis_ctrl_tdata    => m_axis_ctrl_tdata,
463
                s_axis_ctrl_tlast    => m_axis_ctrl_tlast,
464
                s_axis_ctrl_tready   => m_axis_ctrl_tready
465
        );
466
 
467
end architecture sim;

powered by: WebSVN 2.1.0

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