⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 add_cyclic_prefix.vhd

📁 OFDM的fpga实现
💻 VHD
📖 第 1 页 / 共 2 页
字号:
-- ================================================================================
-- (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 + -