📄 ofdm_kernel_tx_tb.vhd
字号:
-- ================================================================================
-- (c) 2007 Altera Corporation. All rights reserved.
-- Altera products are protected under numerous U.S. and foreign patents, maskwork
-- rights, copyrights and other intellectual property laws.
-- These design examples may only be used within Altera Corporation devices and remain
-- the property of Altera. They are being provided on "as-is" basis and as an accommodation;
-- therefore, all warranties, representations, or guarantees of any kind (whether express,
-- implied, or statutory) including, without limitation, warranties of merchantability,
-- non-infringement, or fitness for a particular purpose, are specifically disclaimed.
-- Altera expressly does not recommend, suggest, or require that these examples be used
-- in combination with any other product not provided by Altera.
-- ================================================================================
--
-- Filename : ofdm_kernel_Tx_tb.vhd
--
-- Description : TestBench for OFDM Kernel Module.
--
-- Reads Input data from text files and applies to Module.
-- To test different FFT sizes, changes the FFT size and CP size
-- in the test vector.
-- ================================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use std.textio.all;
entity ofdm_kernel_Tx_tb is
end ofdm_kernel_Tx_tb;
architecture rtl of ofdm_kernel_Tx_tb is
-----------------------------------------------------------------------------
-- COMPONENT DECLARATIONS
-----------------------------------------------------------------------------
component ofdm_kernel_Tx
generic
(
DFFTOUTWIDTH : natural := 31;
DOUTWIDTH : natural := 32;
DFFTINWIDTH : natural := 16;
MWIDTH : natural := 64;
MADDR_WIDTH : natural := 12;
CPWIDTH : natural := 10;
NWIDTH : natural := 11;
MDEPTH : natural := 4096
);
port
(
clk_f : in std_logic;
clk_s : in std_logic;
rst_f_n : in std_logic;
rst_s_n : in std_logic;
-- Control
L : in std_logic_vector (CPWIDTH - 1 downto 0);
Lout : out std_logic_vector (CPWIDTH - 1 downto 0);
N : in std_logic_vector (NWIDTH - 1 downto 0);
Nout : out std_logic_vector(NWIDTH -1 downto 0);
inv : in std_logic;
-- Avalon Streaming Data Sink Input Interface
din_valid : in std_logic;
din_real : in std_logic_vector (DFFTINWIDTH - 1 downto 0);
din_imag : in std_logic_vector (DFFTINWIDTH - 1 downto 0);
din_sop : in std_logic;
din_eop : in std_logic;
din_error : in std_logic_vector(1 downto 0);
din_ready : out std_logic;
--Avalon Streaming Data Source Output Interface
dout_ready : in std_logic;
dout_valid : out std_logic;
dout_sop : out std_logic;
dout_eop : out std_logic;
dout_real : out std_logic_vector (DOUTWIDTH - 1 downto 0);
dout_imag : out std_logic_vector (DOUTWIDTH - 1 downto 0)
);
end component;
-----------------------------------------------------------------------------
-- CONSTANT DECLARATIONS
-----------------------------------------------------------------------------
constant DFFTINWIDTH : natural := 16;
constant DOUTWIDTH : natural := 32;
constant CPWIDTH : natural := 10; -- Cyclic Prefix Size
constant NWIDTH : natural := 12; -- this value must match FFT instantiation
constant DFFTOUTWIDTH : natural := 31; -- this value must match FFT output
-- data width
constant MWIDTH : natural := 2*DOUTWIDTH;
constant MDEPTH : natural := 2**NWIDTH; -- = 2*(2**(NWIDTH-1))=2**NWIDTH
constant MADDR_WIDTH : natural := NWIDTH; -- = log2(MDEPTH)
constant HPERIOD_F : time := 5 ns;
constant HPERIOD_S : time := 10 ns;
constant RST_DELAY : time := 50 ns;
constant NUM_FRAMES_c : natural := 7;
signal clk_f : std_logic := '0';
signal clk_s : std_logic := '0';
signal rst_f_n : std_logic := '0';
signal rst_s_n : std_logic := '0';
signal N, Nout : std_logic_vector (NWIDTH - 1 downto 0);
signal L, Lout : std_logic_vector(CPWIDTH - 1 downto 0);
signal inv : std_logic := '0';
signal sink_valid : std_logic;
signal sink_sop : std_logic;
signal sink_eop : std_logic;
signal sink_error : std_logic_vector(1 downto 0);
signal sink_real : std_logic_vector (DFFTINWIDTH - 1 downto 0);
signal sink_imag : std_logic_vector (DFFTINWIDTH - 1 downto 0);
signal source_ready : std_logic;
signal sink_ready : std_logic;
signal source_sop : std_logic;
signal source_sop_r : std_logic;
signal source_eop : std_logic;
signal source_valid : std_logic;
signal source_real : std_logic_vector (DOUTWIDTH - 1 downto 0);
signal source_imag : std_logic_vector (DOUTWIDTH - 1 downto 0);
-- for testing purposes, the input file contains 4128 random data symbols
type fftpts_list_t is array (NUM_FRAMES_c - 1 downto 0) of natural;
signal fftpts_array : fftpts_list_t := (2048,64,256,128,128,1024,512);
type cp_list_t is array (NUM_FRAMES_c - 1 downto 0) of natural;
signal cp_array : cp_list_t := (512,8,32,32,16,16,128);
signal start : std_logic;
-- number of input frames
signal frames_in_index : natural range 0 to NUM_FRAMES_c := 0;
signal cnt : natural range 0 to 2**(NWIDTH-1);
signal end_test : std_logic;
-- signal the end of the input data stream and output data stream.
signal end_input : std_logic;
begin
-----------------------------------------------------------------------------
-- Generating Clk and reset
-----------------------------------------------------------------------------
process
begin
wait for HPERIOD_F;
clk_f <= not(clk_f);
end process;
process
begin
wait for HPERIOD_S;
clk_s <= not(clk_s);
end process;
process
begin
wait for RST_DELAY;
wait until (clk_f = '1');
rst_f_n <= '1';
wait;
end process;
process
begin
wait for RST_DELAY;
wait until (clk_s = '1');
rst_s_n <= '1';
wait;
end process;
-- for example purposes, the ready signal is always asserted.
source_ready <= '1';
-- -- test source_ready; source_ready is a clk_s domain signal
-- source_ready_test : process
-- begin
-- source_ready <= '1';
-- wait for HPERIOD_S*300;
-- wait until (clk_s = '1');
-- source_ready <= '0';
-- wait for HPERIOD_S*10;
-- wait until (clk_s = '1');
-- source_ready <= '1';
-- end process source_ready_test;
-- no input error
sink_error <= (others => '0');
-- start valid for first cycle to indicate that the file reading should start.
start_p : process (clk_f, rst_f_n)
begin
if rst_f_n = '0' then
start <= '1';
elsif rising_edge(clk_f) then
if sink_valid = '1' and sink_ready = '1' then
start <= '0';
end if;
end if;
end process start_p;
-- sop and eop asserted in first and last sample of data
cnt_p : process (clk_f, rst_f_n)
begin
if rst_f_n = '0' then
cnt <= 0;
elsif rising_edge(clk_f) then
if sink_valid = '1' and sink_ready = '1' then
if cnt = fftpts_array(frames_in_index) - 1 then
cnt <= 0;
else
cnt <= cnt + 1;
end if;
end if;
end if;
end process cnt_p;
N <= std_logic_vector(to_unsigned(fftpts_array(frames_in_index), NWIDTH));
L <= std_logic_vector(to_unsigned(cp_array(frames_in_index), CPWIDTH));
-- count the input frames and increment the index
increment_index_p : process (clk_f, rst_f_n)
begin
if rst_f_n = '0' then
frames_in_index <= 0;
elsif rising_edge(clk_f) then
if sink_eop = '1' and sink_valid = '1' and sink_ready = '1' then
if frames_in_index < NUM_FRAMES_c - 1 then
frames_in_index <= frames_in_index + 1;
end if;
end if;
end if;
end process increment_index_p;
-- signal when all of the input data has been sent to the DUT
end_input <= '1' when (sink_eop = '1' and sink_valid = '1' and (frames_in_index = NUM_FRAMES_c - 1)) else
'0';
-- generate start and end of packet signals
sink_sop <= '1' when cnt = 0 else
'0';
sink_eop <= '1' when cnt = fftpts_array(frames_in_index) - 1 else
'0';
-- flag when done
end_test_p : process (clk_f, rst_f_n)
begin
if rst_f_n = '0' then
end_test <= '0';
elsif rising_edge(clk_f) then
source_sop_r <= source_sop;
if end_input = '1' then
end_test <= '1';
end if;
end if;
end process end_test_p;
-----------------------------------------------------------------------------------------------
-- Read input data from files
-----------------------------------------------------------------------------------------------
testbench_i : process(clk_f) is
file r_file : text open read_mode is "real_input.txt";
variable data_r : integer;
variable rdata : line;
file i_file : text open read_mode is "imag_input.txt";
variable idata : line;
variable data_i : integer;
begin
if(rst_f_n = '0') then
sink_real <= std_logic_vector(to_signed(0, 16));
sink_imag <= std_logic_vector(to_signed(0, 16));
sink_valid <= '0';
elsif rising_edge(clk_f) then
-- send in NUM_FRAMES_c of data or until the end of the file
if not endfile(r_file) and (end_input = '0' and end_test = '0') then
if((sink_valid = '1' and sink_ready = '1') or
(start = '1' and not (sink_valid = '1' and sink_ready = '0'))) then
readline(r_file, rdata);
read(rdata, data_r);
readline(i_file, idata);
read(idata, data_i);
sink_valid <= '1';
sink_real <= std_logic_vector(to_signed(data_r, 16));
sink_imag <= std_logic_vector(to_signed(data_i, 16));
else
sink_valid <= '1';
sink_real <= sink_real;
sink_imag <= sink_imag;
end if;
else
sink_valid <= '0';
sink_real <= std_logic_vector(to_signed(0, 16));
sink_imag <= std_logic_vector(to_signed(0, 16));
end if;
-- testsig <= endfile(r_file);
end if;
end process testbench_i;
---------------------------------------------------------------------------------------------
-- Write Real and Imginary Components to Files
---------------------------------------------------------------------------------------------
testbench_o : process(clk_s, rst_s_n) is
file ro_file : text open write_mode is "real_output_vhd.txt";
variable rdata : line;
variable data_r : integer;
file io_file : text open write_mode is "imag_output_vhd.txt";
variable idata : line;
variable data_i : integer;
begin
if rising_edge(clk_s) and rst_s_n = '1' then
-- if(source_valid = '1' and source_ready = '1') then
if(source_valid = '1') then -- removed source_ready since output
-- ready latency is 4
data_r := to_integer(signed(source_real));
data_i := to_integer(signed(source_imag));
write(rdata, data_r);
writeline(ro_file, rdata);
write(idata, data_i);
writeline(io_file, idata);
end if;
end if;
end process testbench_o;
-----------------------------------------------------------------------------
-- Write the blocks sizes and CP sizes generated to files
-----------------------------------------------------------------------------
blksize_report_o : process(clk_f) is
file blk_file : text open write_mode is "blksize_report.txt";
variable blkdata : line;
variable data_blk : integer;
file inv_file : text open write_mode is "inverse_report.txt";
variable invdata : line;
variable data_inv : bit;
file cp_file : text open write_mode is "cpsize_report.txt";
variable cpdata : line;
variable data_cp : integer;
begin
if rising_edge(clk_f) then
if(sink_valid = '1' and sink_ready = '1' and sink_sop = '1') then
data_blk := to_integer(unsigned(N));
write(blkdata, data_blk);
writeline(blk_file, blkdata);
data_cp := to_integer(unsigned(L));
write(cpdata, data_cp);
writeline(cp_file, cpdata);
data_inv := to_bit(inv);
write(invdata, data_inv);
writeline(inv_file, invdata);
end if;
end if;
end process blksize_report_o;
---------------------------------------------------------------------------------------------
-- Kernel Component Instantiation
---------------------------------------------------------------------------------------------
kernel_Tx_inst : ofdm_kernel_Tx
generic map
(
DFFTOUTWIDTH => DFFTOUTWIDTH,
DFFTINWIDTH => DFFTINWIDTH,
DOUTWIDTH => DOUTWIDTH,
MDEPTH => MDEPTH,
NWIDTH => NWIDTH,
MWIDTH => MWIDTH,
CPWIDTH => CPWIDTH,
MADDR_WIDTH => MADDR_WIDTH
)
port map (
clk_f => clk_f,
clk_s => clk_s,
rst_f_n => rst_f_n,
rst_s_n => rst_s_n,
L => L,
Lout => Lout,
N => N,
Nout => Nout,
inv => inv,
din_valid => sink_valid,
din_sop => sink_sop,
din_eop => sink_eop,
din_real => sink_real,
din_imag => sink_imag,
din_error => sink_error,
dout_ready => source_ready,
din_ready => sink_ready,
dout_sop => source_sop,
dout_eop => source_eop,
dout_valid => source_valid,
dout_real => source_real,
dout_imag => source_imag);
end rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -