Sunday, January 23, 2011

Pressing on with IQ Correction algorithm - vhdl entity and architecture update

Here's tonight's progress on the entity and architecture for the implementation
of the IQ Correction algorithm.

It compiled after solving some trouble I had with implmenting shifts. Standard
logic vectors can't be shifted, but signed vectors can be. So converting, then
shifting, then converting back did the trick.

More soon,
-Michelle W5NYV



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

entity IQGainPhaseCorrection is
generic(input_width:natural:=15;
output_width:natural:=31);
port(
clk :in std_logic;
x1 :in std_logic_vector(input_width downto 0);
y1 :in std_logic_vector(input_width downto 0);
gain_error :out std_logic_vector(output_width downto 0);
phase_error :out std_logic_vector(output_width downto 0)
);
end IQGainPhaseCorrection;


architecture IQGainPhaseCorrection_beh of IQGainPhaseCorrection is
--signal declarations
--phase error calculation
signal reg_1:std_logic_vector(input_width downto 0);
signal reg_1_sv:std_logic_vector(input_width downto 0);
--gain error calculation
signal reg_2:std_logic_vector(input_width downto 0);
signal reg_2_sv:std_logic_vector(input_width downto 0);

--Phase Offset Corrected
signal y2:std_logic_vector(2*input_width downto 0);

--Gain and Phase Offset Corrected
signal y3:std_logic_vector(input_width downto 0);
signal x1y2:signed(2*input_width downto 0);
signal mu_1:signed(2*input_width downto 0);
signal x1x1y3y3:signed(4*input_width downto 0);
signal mu_2:signed(2*input_width downto 0);

begin
correction : process
begin
wait until clk'event and clk = '1';

--phase error estimate, step size set to 0.000244
y2 <= y1 - reg_1 * x1;
--reg_1_sv <= reg_1;
x1y2 <= signed(x1 * y2); --have to convert to signed to use shift.
mu_1 <= shift_right(x1y2,12); --step size applied.
reg_1 <= reg_1 + std_logic_vector(mu_1); --convert back to std_logic_vector.
phase_error <= reg_1; --update phase error estimate.

--gain error estimate, step size set to 0.000122
y3 <= y2 * reg_2;
--reg_2_sv <= reg_2;
x1x1y3y3 <= signed(abs((x1)*(x1)) - abs((y3)*(y3))); --have to convert to signed to use shift.
mu_2 <= shift_right(x1x1y3y3, 13); --step size applied.
reg_2 <= reg_2 + std_logic_vector(mu_2); --convert back to std_logic_vector.
gain_error <= reg_2; --update gain error estimate.

end process;
end IQGainPhaseCorrection_beh;

No comments: