📄 add_cyclic_prefix.vhd
字号:
-- ================================================================================
-- (c) 2007 Altera Corporation. All rights reserved.
-- 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 : add_cyclic_prefix.vhd
--
-- Description : IFFT samples are input into this module in blocks of N samples over
-- N cycles for input clk.
--
-- The first sample in a block of N is denoted by a high on SOP signal.
-- The last sample is denoted by a high on EOP signal.
--
-- This module outputs each block of N samples prepended by a number of
-- samples CP copied from the end of the block. The output clk rate is at
-- the required sample rate.
--
-- For worst case scenario, input and output clk rates are assumed to
-- be asynchronous.
--
-- The input buffer that holds the OFDM symbol data being fed into this
-- submodule is two OFDM symbols deep.
--
-- The output from this submodule is continous.
--
-- This submodule halts the data being fed into this block by deasserting
-- in_ready signal when the buffers are full. This forces the FFT
-- core feeding data into this submodule to stall.
-- ================================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use std.textio.all;
entity add_cyclic_prefix is
generic
(
DFFTOUTWIDTH : natural := 31;
DOUTWIDTH : natural := 32;
NWIDTH : natural := 12; -- also works as Max B Width
MWIDTH : natural := 64;
MADDR_WIDTH : natural := 12;
MDEPTH : natural := 4096;
CPWIDTH : natural := 10
);
port
(
clk_in : in std_logic;
clk_out : in std_logic;
rst_in_n : in std_logic;
rst_out_n : in std_logic;
-- Control
L : in 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);
Lout : out std_logic_vector (CPWIDTH - 1 downto 0);
-- Avalon Streaming Input Interface
in_real : in std_logic_vector (DFFTOUTWIDTH - 1 downto 0);
in_imag : in std_logic_vector (DFFTOUTWIDTH - 1 downto 0);
in_valid : in std_logic;
in_sop : in std_logic;
in_eop : in std_logic;
in_ready : out std_logic;
out_ready : in std_logic;
out_valid : out std_logic;
out_sop : out std_logic;
out_eop : out std_logic;
out_real : out std_logic_vector (DOUTWIDTH - 1 downto 0);
out_imag : out std_logic_vector (DOUTWIDTH - 1 downto 0);
-- Interface with memory
mem_dout : in std_logic_vector (MWIDTH - 1 downto 0);
mem_din : out std_logic_vector (MWIDTH - 1 downto 0);
mem_wren : out std_logic := '1';
mem_wraddr : buffer std_logic_vector (MADDR_WIDTH - 1 downto 0);
mem_rdaddr : buffer std_logic_vector (MADDR_WIDTH - 1 downto 0)
);
end add_cyclic_prefix;
architecture rtl of add_cyclic_prefix is
-----------------------------------------------------------------------------
-- SIGNAL DECLARATIONS
-----------------------------------------------------------------------------
signal in_eop_r : std_logic;
signal in_eop_r2 : std_logic;
signal in_sop_r : std_logic;
signal in_valid_r : std_logic;
signal in_real_r : std_logic_vector(DFFTOUTWIDTH - 1 downto 0);
signal in_imag_r : std_logic_vector(DFFTOUTWIDTH - 1 downto 0);
signal cp_start_addra : std_logic_vector (MADDR_WIDTH - 1 downto 0);
signal cp_start_addrb : std_logic_vector (MADDR_WIDTH - 1 downto 0);
-- for bit reversal
signal tmp_mem_wraddr : std_logic_vector (MADDR_WIDTH-1 downto 0);
signal tmp_mem_wraddr_r : std_logic_vector (MADDR_WIDTH-1 downto 0);
signal mem_wraddr_offset : std_logic_vector (MADDR_WIDTH - 1 downto 0);
signal d_real : std_logic_vector(DOUTWIDTH - 1 downto 0);
signal d_imag : std_logic_vector (DOUTWIDTH -1 downto 0);
signal buf_b_a_n : std_logic; -- current buffer being written to
-- bufa_wr_tog: flip after finishing writing to A; keeps current value for 2
-- packets (clk_in domain)
signal bufa_wr_tog : std_logic;
signal bufb_wr_tog : std_logic;
-- bufa_wr_early_tog: flip when starting to write to A; keeps current value
-- for 2 writing-packets (clk_in domain)
signal bufa_wr_early_tog : std_logic;
signal bufb_wr_early_tog : std_logic;
-- bufa_wr_tog_r and _r2, sync to clk_out domain
signal bufa_wr_tog_r : std_logic;
signal bufa_wr_tog_r2 : std_logic;
signal bufb_wr_tog_r : std_logic;
signal bufb_wr_tog_r2 : std_logic;
-- bufa_rd_tog: flip after reading out all the contents of A AND finishing
-- writing to B; keeps current value for 2 reading-packets (clk_out domain)
signal bufa_rd_tog : std_logic;
signal bufb_rd_tog : std_logic;
-- bufa_rd_tog_r, bufa_rd_tog_r2: sync to clk_in domain
signal bufa_rd_tog_r : std_logic;
signal bufa_rd_tog_r2 : std_logic;
signal bufb_rd_tog_r : std_logic;
signal bufb_rd_tog_r2 : std_logic;
-- Buffer-can-be-read-out signal in clk_out domain; bufa_full asserts after
-- finishing writing to A, and deasserts after finishing writing to B
signal bufa_full : std_logic;
signal bufb_full : std_logic;
-- buffer-is-not-empty signal in clk_in domain; bufa_taken asserts
-- after starting writing to A and deasserts after starting reading out from
-- B. It is used to halt fft if buffer A and B are full. Because two clk
-- domains are used, it is possible that fft is halted while input-output
-- control signals are synchronizing
signal bufa_taken, bufb_taken : std_logic;
-- clk_out domain signal; deasserts when outputing cyclic prefix
signal post_cp : std_logic;
-- clk_out signal; indicates start of output data;
signal start_read : std_logic;
signal bufa_sym_strt : std_logic_vector (2 downto 0);
signal bufb_sym_strt : std_logic_vector (2 downto 0);
-- cnt: clk_in domain counter recording how many fft output values have been
-- written to memory; from 0 to FFT Size-1
signal cnt : std_logic_vector (NWIDTH - 1 downto 0);
signal cnt_int : natural range 0 to MDEPTH;
-- Avalon streaming in_ready signal
signal in_ready_tmp : std_logic;
signal in_ready_r : std_logic;
-- FFT Size for current buffer
signal N_int : natural range 0 to 2**(NWIDTH)-1;
signal Na, Nb : natural range 0 to MDEPTH/2 := MDEPTH/2; -- clk_in domain signal
signal B_int : natural range 0 to 12; -- = log2(N)
-- L_int: integer version of CP size
signal L_int : natural range 0 to 2**(CPWIDTH)-1;
signal La, Lb : natural range 0 to MDEPTH/2 := 0;
-- output AST signals
signal out_eop_a, out_eop_b : std_logic;
signal out_eop_sr : std_logic_vector (1 downto 0);
signal out_valid_sr : std_logic_vector (3 downto 0);
signal tmp_eop : std_logic;
constant Nmax : natural := 2**(NWIDTH-1);
begin
N_int <= to_integer(unsigned(N));
L_int <= to_integer(unsigned(L));
cnt <= std_logic_vector(to_unsigned(cnt_int, NWIDTH));
-----------------------------------------------------------------------------
-- Writing Data to Dual Port RAM
--
-- Depth of RAM is equal to 2 OFDM symbols: Buffer A followed by Buffer B.
-----------------------------------------------------------------------------
d_imag <= std_logic_vector(resize(signed(in_imag_r), DOUTWIDTH));
d_real <= std_logic_vector(resize(signed(in_real_r), DOUTWIDTH));
reg_input : process (clk_in, rst_in_n)
begin
if (rst_in_n = '0') then
mem_din <= (others => '0');
in_eop_r <= '0';
in_sop_r <= '0';
in_valid_r <= '0';
in_real_r <= (others => '0');
in_imag_r <= (others => '0');
in_eop_r2 <= in_eop_r;
elsif rising_edge(clk_in) then
mem_din <= d_imag & d_real;
in_eop_r <= in_eop and in_valid;
in_eop_r2 <= in_eop_r;
in_valid_r <= in_valid;
in_sop_r <= in_sop;
in_real_r <= in_real;
in_imag_r <= in_imag;
end if;
end process reg_input;
-- purpose: find B=log2(N)
bitwidth_lut : process (N_int) is
begin -- process bitwidth_lut
case N_int is
when 8 => B_int <= 3;
when 16 => B_int <= 4;
when 32 => B_int <= 5;
when 64 => B_int <= 6;
when 128 => B_int <= 7;
when 256 => B_int <= 8;
when 512 => B_int <= 9;
when 1024 => B_int <= 10;
when 2048 => B_int <= 11;
when others => B_int <= 0;
end case;
end process bitwidth_lut;
write_cnt : process (clk_in, rst_in_n)
begin -- process write_cnt
if rst_in_n = '0' then
-- cnt records write address
cnt_int <= 0;
elsif rising_edge(clk_in) then
-- cnt halts the cycle after fft_source_eop; thus it uses in_ready_tmp
-- instead of in_ready_r
if ((in_valid = '1') and (in_sop = '1') and (in_ready_tmp = '1')) then
cnt_int <= 0;
elsif in_eop_r = '1' then
cnt_int <= 0;
elsif (in_valid = '1') and (in_ready_tmp = '1') then
cnt_int <= cnt_int + 1;
end if;
end if;
end process write_cnt;
bit_reversal : process (cnt, rst_in_n)
variable j : natural range 0 to MADDR_WIDTH - 1;
begin -- process bit_reversal
if rst_in_n = '1' then
for j in 0 to MADDR_WIDTH - 1 loop
if j < B_int then
tmp_mem_wraddr(j) <= cnt(B_int -j-1);
else
tmp_mem_wraddr(j) <= '0';
end if;
end loop;
else
tmp_mem_wraddr <= (others => '0');
end if;
end process bit_reversal;
reg_waddr : process (clk_in, rst_in_n) -- register write address
begin
if (rst_in_n = '0') then
tmp_mem_wraddr_r <= (others => '0');
elsif rising_edge(clk_in) then
tmp_mem_wraddr_r <= tmp_mem_wraddr;
end if;
end process reg_waddr;
mem_wraddr <= tmp_mem_wraddr_r + mem_wraddr_offset;
process (clk_in, rst_in_n)
begin
if (rst_in_n = '0') then
mem_wren <= '0';
mem_wraddr_offset <= (others => '0');
buf_b_a_n <= '0';
bufa_wr_early_tog <= '0';
bufb_wr_early_tog <= '0';
Na <= 0;
Nb <= 0;
La <= 0;
Lb <= 0;
elsif rising_edge(clk_in) then
-- use in_ready_r because fft output is registered in this module.
if ((in_valid_r = '1') and (in_sop_r = '1') and (in_ready_r = '1')) then
mem_wren <= '1';
buf_b_a_n <= not(buf_b_a_n);
-- initialising addr counter
if (buf_b_a_n = '0') then -- A being (will be) written to
mem_wraddr_offset <= (others => '0');
bufa_wr_early_tog <= not(bufa_wr_early_tog);
-- Use Na and Nb to indicate what is the fft size for data stored in this
-- buffer. It makes sure when bufa/b_rd_tog flips mem_raddr is comparing to the
-- right fft size
Na <= N_int;
La <= L_int;
else
mem_wraddr_offset <= std_logic_vector(to_unsigned(Nmax, MADDR_WIDTH));
--offset should be from Nmax
bufb_wr_early_tog <= not(bufb_wr_early_tog);
Nb <= N_int;
Lb <= L_int;
end if;
elsif (in_eop_r2 = '1') then
mem_wren <= '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -