Thursday, March 27, 2014

First VHDL-attempts to remove DC from BladeRF-outputs

First VHDL-attempts to remove DC from BladeRF-outputs


Well, subject says it all.

Last few weeks I did study VHDL a lot and came up with the following change of the lms6002d.vhdl piece:

library ieee ;
    use ieee.std_logic_1164.all ;
    use ieee.numeric_std.all ;

-- modified to remove DC-component
-- March-2014 KdG
           
entity lms6002d is
  port (
    -- RX Controls
    rx_clock            :   in      std_logic ;
    rx_reset            :   in      std_logic ;
    rx_enable           :   in      std_logic ;

    -- RX Interface with LMS6002D
    rx_lms_data         :   in      signed(11 downto 0) ;
    rx_lms_iq_sel       :   in      std_logic ;
    rx_lms_enable       :   buffer  std_logic ;

    -- RX Sample Interface
    rx_sample_i         :   buffer  signed(11 downto 0) ;
    rx_sample_q         :   buffer  signed(11 downto 0) ;
    rx_sample_valid     :   buffer  std_logic ;

    -- TX Controls
    tx_clock            :   in      std_logic ;
    tx_reset            :   in      std_logic ;
    tx_enable           :   in      std_logic ;

    -- TX Sample Interface
    tx_sample_i         :   in      signed(11 downto 0) ;
    tx_sample_q         :   in      signed(11 downto 0) ;
    tx_sample_valid     :   in      std_logic ;

    -- TX Interface to the LMS6002D
    tx_lms_data         :   buffer  signed(11 downto 0) ;
    tx_lms_iq_sel       :   buffer  std_logic ;
    tx_lms_enable       :   buffer  std_logic
  ) ;
end entity ;

architecture arch of lms6002d is

signal rx_average_i, rx_average_q : signed(11 downto 0);
signal accum_i : signed(18 downto 0) ;
signal accum_q : signed(18 downto 0) ;

begin

    -------------
    -- Receive --
    -------------
    rx_sample : process(rx_clock, rx_reset)
    begin
        if( rx_reset = '1' ) then
            rx_sample_i <= (others =>'0') ;
            rx_sample_q <= (others =>'0') ;
                     rx_average_i <= (others => '0'); -- KdG
                     rx_average_q <= (others => '0');     -- KdG              
            rx_sample_valid <= '0' ;
            rx_lms_enable <= '0' ;
        elsif( rising_edge( rx_clock ) ) then
            if( rx_lms_iq_sel = '0' ) then
                rx_lms_enable <= rx_enable ;
            end if ;

            rx_sample_valid <= '0' ;
            if( rx_lms_enable = '1' ) then
                if(rx_lms_iq_sel = '1' ) then
                    -- rx_sample_i <= rx_lms_data;
                               rx_sample_i <= rx_lms_data - rx_average_i; -- KdG
                else
                    -- rx_sample_q <= rx_lms_data;
                                 rx_sample_q <= rx_lms_data - rx_average_q ; -- KdG
                    rx_sample_valid <= '1' ;
                end if ;
            end if ;
        end if ;
    end process ;

    --------------
    -- Transmit --
    --------------
    tx_sample : process(tx_clock, tx_reset)
        variable tx_q_reg   :   signed(11 downto 0) ;
    begin
        if( tx_reset = '1' ) then
            tx_lms_data <= (others =>'0') ;
            tx_lms_iq_sel <= '0' ;
            tx_lms_enable <= '0' ;
            tx_q_reg := (others =>'0') ;
        elsif( rising_edge( tx_clock ) ) then
            if( tx_lms_iq_sel = '0' ) then
                tx_lms_enable <= tx_enable ;
            end if ;

            if( tx_sample_valid = '1' ) then
                tx_lms_data <= tx_sample_i ;
                tx_q_reg := tx_sample_q ;
                tx_lms_iq_sel <= '0' ;
            elsif( tx_lms_enable = '1' ) then
                tx_lms_data <= tx_q_reg ;
                tx_lms_iq_sel <= '1' ;
            else
                tx_lms_data <= (others =>'0') ;
                tx_lms_iq_sel <= '0' ;
            end if ;
        end if ;
    end process ;
      
      average: process(rx_sample_valid)
          variable count : integer ;
    begin
          if( rising_edge( rx_sample_valid ) ) then
                if(rx_lms_iq_sel = '1' ) then
                       accum_i <= accum_i + rx_lms_data;
                     else
                    accum_q <= accum_q + rx_lms_data;
                     end if;  
                count := count + 1;
                     if ( count > 128 ) then
                         count := 0;
                           rx_average_i(11 downto 0) <= accum_i (18 downto 7);
                           rx_average_q(11 downto 0) <= accum_q (18 downto 7);
                           accum_i <= (others =>'0') ;
                           accum_q <= (others =>'0') ;
                     end if;
             end if;
      end process average;
      
end architecture ;

I declared some signals and calculate the average in a separate process.

I get some errors from Quartus:

Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[11]" at lms6002d.vhd(114)
Error (10029): Constant driver at lms6002d.vhd(53)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[10]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[9]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[8]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[7]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[6]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[5]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[4]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[3]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[2]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[1]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_i[0]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_q[11]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_q[10]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_q[9]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_q[8]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_q[7]" at lms6002d.vhd(114)
Error (10028): Can't resolve multiple constant drivers for net "rx_average_q[6]" at lms6002d.vhd(114)

Thusfar I do not understand this error-messages.

Because it was a long time ago already that I posted something on my blog, this is a kind of “I am still alive message”.

I will dig into this problem, but I would LOVE to get some hints from VHDL-gurus!

Next time I hope to come up with a working VHDl-solution.