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

📄 add_cyclic_prefix.vhd

📁 OFDM的fpga实现
💻 VHD
📖 第 1 页 / 共 2 页
字号:
-- added valid and ready test. now cnt is not free running when input is not valid
      elsif (in_valid_r = '1') and (in_ready_r = '1') then
        mem_wren <= '1';
      else
        mem_wren <= '0';
      end if;
    end if;
  end process;


  -- when a Buffer has been filled up, toggling appropriate signal
  -- to flag this. These signals are used by the read side of FIFO
  -- to determine when the Buffers contain valid data
  process (clk_in, rst_in_n)
  begin
    if (rst_in_n = '0') then
      bufa_wr_tog <= '0';
      bufb_wr_tog <= '0';
    elsif rising_edge(clk_in) then
      if (in_eop_r2 = '1') then
        if (buf_b_a_n = '0') then
          --actual value of buf_b_a_n is 1 (it gets inverted after sop)
          bufb_wr_tog <= not(bufb_wr_tog);
        else
          bufa_wr_tog <= not(bufa_wr_tog);
        end if;
      end if;
    end if;
  end process;

  bufa_taken <= (bufa_wr_early_tog xor bufa_rd_tog_r2);
  bufb_taken <= (bufb_wr_early_tog xor bufb_rd_tog_r2);

  -- This submodule can only accept the next block of N samples from IFFT core
  -- if either Buffer A OR B is empty. Due to the streaming nature of FFT
  -- output, in_ready_tmp aligns with fft source eop, i.e. it de-asserts the
  -- cycle after in_eop if both buffers are taken.
  process (clk_in, rst_in_n)
  begin  -- process
    if (rst_in_n = '0') then
      in_ready_tmp <= '0';
      in_ready_r   <= '0';
    elsif rising_edge(clk_in) then
      if (bufa_taken = '1' and bufb_taken = '1') then
        if (in_eop = '1') then
          in_ready_tmp <= '0';
        else
          in_ready_tmp <= in_ready_tmp;
        end if;
      else
        in_ready_tmp <= '1';
      end if;
      in_ready_r <= in_ready_tmp;
    end if;
  end process;

  in_ready <= in_ready_tmp;

-- Synchronising Buffer read signals generated using clk_out into clk_in  domain
  process (clk_in, rst_in_n)
  begin
    if (rst_in_n = '0') then
      bufa_rd_tog_r  <= '0';
      bufa_rd_tog_r2 <= '0';
      bufb_rd_tog_r  <= '0';
      bufb_rd_tog_r2 <= '0';
    elsif rising_edge(clk_in) then
      bufa_rd_tog_r  <= bufa_rd_tog;
      bufa_rd_tog_r2 <= bufa_rd_tog_r;
      bufb_rd_tog_r  <= bufb_rd_tog;
      bufb_rd_tog_r2 <= bufb_rd_tog_r;
    end if;
  end process;

  -----------------------------------------------------------------------------
  -- Reading Data from Dual Port RAM
  -- The memory contains 2*Nmax locations (1 IFFT worth of data).
  -- Reading starts at address current N - Cyclic Prefix Delay to N-1, 
  -- then from address 0 to current N-1, 
  -- then from address 2*Nmax - (current CP) to Nmax-1+current CP
  -- then from address Nmax to Nmax-1+current CP and so on..., 
  -----------------------------------------------------------------------------

  -- Determining start address for first sample for cyclic prefix for buffer A and buffer B
  process (clk_out, rst_out_n)
  begin
    if (rst_out_n = '0') then
      cp_start_addra <= (others => '0');
      cp_start_addrb <= (others => '0');
    elsif rising_edge(clk_out) then
      if (La = 0) then
        cp_start_addra <= (others => '0');
      else
        cp_start_addra <= std_logic_vector(to_unsigned(Na - La, MADDR_WIDTH));
      end if;
      if Lb = 0 then
        cp_start_addrb <= std_logic_vector(to_unsigned(MDEPTH/2, MADDR_WIDTH));
      else
        cp_start_addrb <= std_logic_vector(to_unsigned(MDEPTH/2+Nb - Lb, MADDR_WIDTH));
      end if;
    end if;
  end process;

  -- synchronising Buffer  write signals to clk_out domain
  process (clk_out, rst_out_n)
  begin
    if (rst_out_n = '0') then
      bufa_wr_tog_r  <= '0';
      bufa_wr_tog_r2 <= '0';
      bufb_wr_tog_r  <= '0';
      bufb_wr_tog_r2 <= '0';
    elsif rising_edge(clk_out) then
      bufa_wr_tog_r  <= bufa_wr_tog;
      bufa_wr_tog_r2 <= bufa_wr_tog_r;
      bufb_wr_tog_r  <= bufb_wr_tog;
      bufb_wr_tog_r2 <= bufb_wr_tog_r;
    end if;
  end process;

  bufa_full <= bufa_wr_tog_r2 xor bufa_rd_tog;
  bufb_full <= bufb_wr_tog_r2 xor bufb_rd_tog;

  -- incrementing read address
  process (clk_out, rst_out_n)
  begin
    if (rst_out_n = '0') then
      mem_rdaddr    <= (others => '0');
      start_read    <= '0';
      post_cp       <= '0';
      bufa_rd_tog   <= '0';
      bufb_rd_tog   <= '0';
      bufa_sym_strt <= (others => '0');
      bufb_sym_strt <= (others => '0');
      out_eop_a     <= '0';
      out_eop_b     <= '0';
      out_valid_sr  <= (others => '0');
      out_eop_sr    <= (others => '0');
    elsif rising_edge(clk_out) then
      --shift registers to delay generation of symbol start output pulse
      --according to delay of reading from memory
      bufa_sym_strt(1 downto 0) <= bufa_sym_strt(2 downto 1);
      bufb_sym_strt(1 downto 0) <= bufb_sym_strt(2 downto 1);
      bufa_sym_strt(2)          <= '0';
      bufb_sym_strt(2)          <= '0';
      --shift register to delay generation of out_valid according
      --to delay of reading from memory
      out_valid_sr(2 downto 0)  <= out_valid_sr(3 downto 1);
      out_eop_sr(0)             <= out_eop_sr(1);
      out_eop_sr(1)             <= tmp_eop;
      if (out_ready = '1') then
        if ((start_read = '0') and (bufa_full = '0')) then
          mem_rdaddr                <= cp_start_addra;
          bufa_sym_strt(2 downto 0) <= "100";
          out_valid_sr(3 downto 0)  <= "1000";
        else
          -- first time come here due to bufa_full = '0'; after the first
          -- package come here due to start_read = '1'         
          start_read      <= '1';
          out_valid_sr(3) <= '1';       -- unless buffer is not available
                                        -- to send data from
                                        -- (overwritten later on)
          if (mem_rdaddr = std_logic_vector(to_unsigned(Na-1, MADDR_WIDTH))) then
            -- end of Buffer A (determine if just finished outputting cyclic prefix or 
            -- end of symbol)            
            if (post_cp = '0') then
              mem_rdaddr <= std_logic_vector(to_unsigned(0, MADDR_WIDTH));
              post_cp    <= '1';
            else
              -- reading out post cp data
              out_eop_a <= '1';
              if (bufb_full = '1') then
                mem_rdaddr       <= cp_start_addrb;
                post_cp          <= '0';
                bufa_rd_tog      <= not(bufa_rd_tog);
                bufb_sym_strt(2) <= '1';
              else
                -- buffer B is not full
                out_valid_sr(3) <= '0';
              end if;
            end if;  -- if (post_cp = '0') then
          elsif (mem_rdaddr = std_logic_vector(to_unsigned(MDEPTH/2 + Nb -1, MADDR_WIDTH))) then
            --end of Buffer B (determine if just finished outputting cyclic prefix or 
            -- end of symbol)           
            if (post_cp = '0') then
              mem_rdaddr <= std_logic_vector(to_unsigned(MDEPTH/2, MADDR_WIDTH));
              post_cp    <= '1';
            else
              out_eop_b <= '1';
              if (bufa_full = '1') then
                mem_rdaddr       <= cp_start_addra;
                post_cp          <= '0';
                bufb_rd_tog      <= not(bufb_rd_tog);
                bufa_sym_strt(2) <= '1';
              else
                -- buffer A is not full
                out_valid_sr(3) <= '0';
              end if;  -- if (bufa_full = '0')
            end if;  -- if (post_cp = '0') then
          else
            -- output cp;mem_raddr != N-1 nor 2N-1
            -- may or may not in output mode
            mem_rdaddr <= mem_rdaddr + 1;
            out_eop_a  <= '0';
            out_eop_b  <= '0';
          end if;
        end if;  -- if ((start_read = '0') and (bufa_full = '0')) then
      else
        -- AST Sink not ready to take output: deassert out_valid
        out_valid_sr(3) <= '0';
      end if;  -- if (out_ready = '1') then      
    end if;  -- if (rst_out_n ='0') then
  end process;

  -----------------------------------------------------------------------------
  -- Output AST Data Source Interface
  --
  -- 
  -- This Source assumes ready_latency = 4 clk cycles.
  -- Supports back pressure (i.e. allows Sink to deassert out_ready).
  -- Also if no data to send, will deassert out_valid.
  --
  -- Upon reset waits for slave sink to assert out_ready. This is fed back to input 
  -- interface as when to assert slave_sink_dav.
  --
  -- The start of each OFDM symbol is denoted by a high on out_sop.
  -----------------------------------------------------------------------------
  process (clk_out, rst_out_n)
  begin
    if (rst_out_n = '0') then
      out_real <= (others => '0');
      out_imag <= (others => '0');
    elsif rising_edge(clk_out) then
      out_real <= mem_dout(DOUTWIDTH - 1 downto 0);
      out_imag <= mem_dout(2 * DOUTWIDTH - 1 downto DOUTWIDTH);
    end if;
  end process;

  -- out_sop pulses high at beginning of each OFDM symbol (i.e. 
  -- coincident with first Cyclic Prefix sample).
  -- The delay is calculated from delay of reading first sample of OFDM symbol data
  -- from memory upon and also includes the extra registering
  -- stage above before data is clocked out of this module.
  process (clk_out, rst_out_n)
  begin
    if (rst_out_n = '0') then
      out_sop <= '0';
    elsif rising_edge(clk_out) then
      if (bufa_sym_strt(0) = '1') then
        out_sop <= '1';
      elsif (bufb_sym_strt(0) = '1') then
        out_sop <= '1';
      else
        out_sop <= '0';
      end if;
    end if;
  end process;
  out_valid <= out_valid_sr(0);
  tmp_eop   <= ((out_valid_sr(2) and out_eop_a) or (out_valid_sr(2) and out_eop_b));
  out_eop   <= out_eop_sr(0);

  output_N_L : process (clk_out, rst_out_n)
  begin
    if (rst_out_n = '0') then
      Nout <= (others => '0');
      Lout <= (others => '0');
    elsif rising_edge(clk_out) then
      -- Nout and Lout is sampled at output sop
      if (bufa_sym_strt(0) = '1') then
        Nout <= std_logic_vector(to_unsigned(Na, NWIDTH));
        Lout <= std_logic_vector(to_unsigned(La, CPWIDTH));
      elsif (bufb_sym_strt(0) = '1') then
        Nout <= std_logic_vector(to_unsigned(Nb, NWIDTH));
        Lout <= std_logic_vector(to_unsigned(Lb, CPWIDTH));
      end if;
    end if;
  end process;

--  -----------------------------------------------------------------------------
--  -- test simulation results; not synthesizable. Comment out this section when
--  -- running synthesis.  Uncomment this section if want to use the MATLAB
--  -- script to check CP insertion results.
--  -----------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------------
  -- Write Real and Imginary Components of IFFT Output to Files                                               
--  ---------------------------------------------------------------------------------------------

--  testbench_o : process(clk_in, rst_in_n) is
--    file ro_file    : text open write_mode is "fft_real_output_vhd.txt";
--    variable rdata  : line;
--    variable data_r : integer;
--    file io_file    : text open write_mode is "fft_imag_output_vhd.txt";
--    variable idata  : line;
--    variable data_i : integer;
--  begin
--    if rising_edge(clk_in) and rst_in_n = '1' then
--      if(in_valid_r = '1' and in_ready_r = '1') then
----        data_r := to_integer(signed(d_real));
----        data_i := to_integer(signed(d_imag));
--        data_r := to_integer(signed(in_real_r));
--        data_i := to_integer(signed(in_imag_r));        
--        write(rdata, data_r);
--        writeline(ro_file, rdata);
--        write(idata, data_i);
--        writeline(io_file, idata);
--      end if;
--    end if;
--  end process testbench_o;

  -----------------------------------------------------------------------------
  
end rtl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -