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.
HDL's only allow you to drive a signal from a single process so it understands from a very narrow context what the next value should be.
ReplyDeleteThe errors are just saying that you assign the signal 'rx_average_i' in two separate processes - one in the 'rx_sample' process, and the other in the 'average' process. You can use 'rx_average_i' in any process, but only assign to it in a single process.
Also, your 'count' variable in the 'average' process is just an integer. By default, VHDL will make all integers 32 bits. You should constrain your integers if you know you won't be using them. To do that you type 'variable count : integer range 0 to 127;'. Also note that integer is signed, natural is 0 and higher, and positive is 1 and higher. They can all be compared to each other, but the extra limits may be helpful for you.
In general, VHDL is a very strict language. You will get a lot of compilation errors before things will attempt to even simulate. Speaking of which, I highly recommend you get ModelSim from Altera and simulate your algorithm you plan on using. It's much, much easier in a simulation environment to verify it is doing what you expect.
Good luck!