- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello i am trying to develop my own Cordic core at VHDL.. but i am having some problems.
I basically have a block of gain and a block of angles that works like that (just a snap)
...
case indice_i is
when "000000" => angulo_o_r <= to_sfixed(0.7854, 4, -27);
when "000001" => angulo_o_r <= to_sfixed(0.4636, 4, -27);
when "000010" => angulo_o_r <= to_sfixed(0.2450, 4, -27);
when "000011" => angulo_o_r <= to_sfixed(0.1244, 4, -27);
when "000100" => angulo_o_r <= to_sfixed(0.0624, 4, -27);
...
And i have my main CORDIC core... i am trying to do something like this (matlab)
ka = 1;
for j=1:n;
Kvalues(j) = ka
angles(j) = atan(ka);
ka = ka * 0.5;
end;
for l=1:n;
K = Kvalues(l);
phase_rads = angles(l);
tmp_real = real;
However for doesnt work the same way in VHDL, so i tried to make a state machine with the following states: INIT (reset state) -> CALC_CORDIC -> INCREMENT_COUNTER->CALC_CORDIC (24 times) then -> FINISH Where my counter is the input for my angle/gain blocks and i use the output from those blocks in my calc_cordic. Too bad it isn't working and i don't know why.. I am getting this error
Error (10028): Can't resolve multiple constant drivers for net "angulo_indice" at cordic.vhd(66)
But i don't have multiple constant drivers for that net.. my code is here
-- Logic to advance to the next state
process (clk_i, rst_i_n)
begin
if rst_i_n = '0' then
state <= init;
elsif (rising_edge(clk_i)) then
case state is
when init=>
if ena_i = '1' and working = '0' then
state <= corrigi_q;
else
state <= init;
end if;
when corrigi_q=>
if finish_quadrante = '1' then
state <= calcula_cordic;
else
state <= corrigi_q;
end if;
when calcula_cordic=>
if finish_cordic ='1' then
state <= fim;
end if;
if finish_calc = '1' then
state <= incrementa_cont;
end if;
if finish_calc = '0' and finish_cordic = '0' then
state <= calcula_cordic;
end if;
when incrementa_cont =>
state <= calcula_cordic;
when fim =>
state <= init;
end case;
end if;
end process;
-- Output depends solely on the current state
process (state)
begin
case state is
when init =>
pi <= to_sfixed (3.1416, 4, -27);
pi_2 <= to_sfixed (1.57, 4, -27);
parte_real <= (others => '0');
parte_imaginaria <= (others => '0');
temp_parte_real <= (others => '0');
acc_phase <= (others => '0');
acc_phase_rads <= (others => '0');
K <= (others => '0');
indice <= (others => '0');
ganho_indice <= (others => '0');
angulo_indice <= (others => '0');
tmp_mult_im_k <= (others => '0');
tmp_mult_re_k <= (others => '0');
magnitude_o_r <= (others => '0');
fase_o_r <= (others => '0');
finish_quadrante <= '0';
finish_cordic <= '0';
finish_calc <= '0';
working <= '0';
when corrigi_q =>
working <= '1';
parte_real <= to_sfixed(real_i, 4, -27);
parte_imaginaria <= to_sfixed(imag_i, 4, -27);
if parte_real < "0" then
temp_parte_real <= parte_real;
if parte_imaginaria > "0" then
parte_real <= parte_imaginaria;
parte_imaginaria <= resize(((not temp_parte_real) + to_sfixed(1, 4, -27)),4,-27); --negativo
acc_phase_rads <= resize(((not pi_2) + to_sfixed(1, 4, -27)),4,-27);--negativo
else
parte_real <= resize(((not parte_imaginaria) + to_sfixed(1, 4, -27)),4,-27); --negativo
parte_imaginaria <= temp_parte_real;
acc_phase_rads <= pi_2;
end if;
else
acc_phase_rads <= (others => '0');
end if;
finish_quadrante <= '1';
when calcula_cordic =>
K <= to_sfixed(ganho_indice, 4, -27);
acc_phase <= to_sfixed(angulo_indice, 4, -27);
temp_parte_real <= parte_real;
if parte_imaginaria >= "0" then
tmp_mult_re_k <= temp_parte_real * K;
tmp_mult_im_k <= parte_imaginaria * K;
parte_real <= resize((parte_real + tmp_mult_im_k),4,-27);
parte_imaginaria <= resize((parte_imaginaria - tmp_mult_re_k),4,-27);
acc_phase_rads <= resize((acc_phase_rads - acc_phase),4,-27);
else
tmp_mult_re_k <= temp_parte_real * K;
tmp_mult_im_k <= parte_imaginaria * K;
parte_real <= resize((parte_real - tmp_mult_im_k),4,-27);
parte_imaginaria <= resize((parte_imaginaria + tmp_mult_re_k),4,-27);
acc_phase_rads <= resize((acc_phase_rads + acc_phase),4,-27);
end if;
if indice < 24 then finish_calc <= '1'; end if;
if indice = 24 then
finish_calc <= '0';
finish_cordic <= '1';
fase_o_r <= resize((not acc_phase_rads) + to_sfixed(1, 4, -27),4,-27) ;
magnitude_o_r <= resize(parte_real * to_sfixed(0.60723, 4, -27),4,-27);
end if;
when incrementa_cont =>
indice <= indice + 1;
finish_calc <= '0';
when fim =>
fase_o <= to_slv(fase_o_r);
magnitude_o <= to_slv(magnitude_o_r);
working <= '0';
end case;
end process;
end rtl;
and my gain/angle blocks declarations
component angulo_atan is
port(
indice_i : in std_logic_vector (5 downto 0);
angulo_o : out std_logic_vector (31 downto 0) );
end component;
component ganho_k is
port(
indice_i : in std_logic_vector (5 downto 0);
ganho_o : out std_logic_vector (31 downto 0) );
end component;
angulo_inst : angulo_atan
port map(
indice_i => std_logic_vector(indice),
angulo_o => angulo_indice);
ganho_inst : ganho_k
port map(
indice_i => std_logic_vector(indice),
ganho_o => ganho_indice);
ANY HELP IS rEALLY apreciated
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Some question immediatly arrise:
Why is pi and pi_2 a signal and not a constant? Why have you not clocked the second process? the way it is currently, you are going to get a LOT of latches (which are bad) because you have not assigned every signal in every branch. You also have an incomplete sensitivity list (all of the signals that drive other signals MUST be in the sensitivity list, otherwise the firmware will not match the simulation). For the error - I can only only assume you have assigned angulo_indece more than once. Basically, there are many many problems with this code.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, I just spotted the problem. You have angulo_indece driven from the 2nd process and the output of the atan block.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
And a 3rd thing - With the atan and ganho_k modules- you appear to have created an asynchronous rom. This is not a very good idea (as all your logic is going to dissapear). You are going to get very very poor Fmax performance.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tricky thanks so much for your really good help.
To do a synchronous rom i have to drive the clock signal and my mux will only happen in the clk signal right? I didnt clock the second process because it's a moore state machine and the 2nd process says it's only sensitive to the state. How can i solve this lach issue with a moore sm- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
for the rom - take the clock into the separate modules and make the process inside the modules sensitive to clock in the normal way.
For your second issue, to solve the latch problem you need to do what I said, you need to make sure every signal is given an output in EVERY branch AND you put ALL the signals (that are used to assign other signals) in the sensitivity list. This will probably completly change the behaviour you've seen in simulation, but it will reflect what will happen on the real chip. As for meely/more, it will still be a moore state machine if you clock it - its just delayed by 1 clock cycle. But it will actually work like you intended (and simulation will match hardware). And you wont have to put every signal in every branch.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Okay i will make some adjusments.
Thanks for the knowledge share, seriously :)- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please see the next post, this one is already old (i've changed the implementation):)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My final version of the RTL code
--=============================
-- Cordic
-- Implementacao do algoritmo de cordic para obter magnitude e angulo a partir de um numero complexo
--=============================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.all;
use work.fixed_float_types.all;
use work.fixed_pkg.all;
-- entity declaration
entity cordic is
port(
clk_i : in std_logic;
rst_i_n : in std_logic;
ena_i : in std_logic;
real_i : in std_logic_vector(31 downto 0);
imag_i : in std_logic_vector(31 downto 0);
fase_o : out std_logic_vector(31 downto 0);
magnitude_o : out std_logic_vector(31 downto 0)
);
end cordic;
architecture rtl of cordic is
-- Build an enumerated type for the state machine
type state_type is (init, corrige_q_p1, corrige_q_p2, calcula_cordic_p1, calcula_cordic_p2, incrementa_cont, fim);
-- Register to hold the current state
signal state : state_type;
signal next_state : state_type;
-- Registers to control the state machine flow
signal finish_quadrante : std_logic;
signal finish_cordic : std_logic;
signal finish_calc : std_logic;
-- Internal signals
signal parte_real,parte_imaginaria, temp_parte_real : sfixed (4 downto -27);
constant pi : sfixed (4 downto -27) := to_sfixed (3.1416, 4, -27);
constant pi_2 : sfixed (4 downto -27) := to_sfixed (1.57, 4, -27);
signal fase_o_r, magnitude_o_r : sfixed (4 downto -27);
signal acc_phase, acc_phase_rads, K : sfixed (4 downto -27);
signal indice : unsigned (5 downto 0);
signal working : std_logic;
signal variavel_nova : std_logic;
signal indice2 : unsigned (5 downto 0);
signal angulo_indice : std_logic_vector(31 downto 0);
signal ganho_indice : std_logic_vector(31 downto 0);
signal tmp_mult_im_k: sfixed (sfixed_high ( 4, -27, '*', 4, -27) downto sfixed_low ( 4, -27, '*', 4, -27));
signal tmp_mult_re_k: sfixed (sfixed_high ( 4, -27, '*', 4, -27) downto sfixed_low ( 4, -27, '*', 4, -27));
signal corrige_q_p1_end : std_logic;
-- Instantiation of other modules
component angulo_atan is
port(
clk_i : in std_logic;
rst_i_n : in std_logic;
indice_i : in std_logic_vector (5 downto 0);
angulo_o : out std_logic_vector (31 downto 0) );
end component;
component ganho_k is
port(
clk_i : in std_logic;
rst_i_n : in std_logic;
indice_i : in std_logic_vector (5 downto 0);
ganho_o : out std_logic_vector (31 downto 0) );
end component;
begin
angulo_inst : angulo_atan
port map(
clk_i => clk_i,
rst_i_n => rst_i_n,
indice_i => std_logic_vector(indice),
angulo_o => angulo_indice);
ganho_inst : ganho_k
port map(
clk_i => clk_i,
rst_i_n => rst_i_n,
indice_i => std_logic_vector(indice2),
ganho_o => ganho_indice);
-- Output depends solely on the current state
process (clk_i, rst_i_n, state)
begin
if rst_i_n = '0' then
next_state <= init;
elsif (rising_edge(clk_i)) then
state <= next_state;
case state is
when init =>
indice2 <=(others => '0');
parte_real <= (others => '0');
parte_imaginaria <= (others => '0');
temp_parte_real <= (others => '0');
acc_phase <= (others => '0');
acc_phase_rads <= (others => '0');
K <= (others => '0');
indice <= (others => '0');
tmp_mult_im_k <= (others => '0');
tmp_mult_re_k <= (others => '0');
magnitude_o_r <= (others => '0');
fase_o_r <= (others => '0');
finish_quadrante <= '0';
finish_cordic <= '0';
finish_calc <= '0';
working <= '0';
corrige_q_p1_end <= '0';
next_state <= corrige_q_p1;
when corrige_q_p1 =>
working <= '1';
parte_real <= to_sfixed(real_i, 4, -27);
parte_imaginaria <= to_sfixed(imag_i, 4, -27);
next_state <= corrige_q_p2;
when corrige_q_p2 =>
if parte_real < "0" then
temp_parte_real <= parte_real;
if parte_imaginaria > "0" then
parte_real <= parte_imaginaria;
parte_imaginaria <= resize(((not temp_parte_real) + to_sfixed(1, 4, -27)),4,-27); --negativo
acc_phase_rads <= resize(((not pi_2) + to_sfixed(1, 4, -27)),4,-27);--negativo
else
parte_real <= resize(((not parte_imaginaria) + to_sfixed(1, 4, -27)),4,-27); --negativo
parte_imaginaria <= temp_parte_real;
acc_phase_rads <= pi_2;
end if;
else
acc_phase_rads <= (others => '0');
end if;
next_state <= calcula_cordic_p1;
when calcula_cordic_p1 =>
K <= to_sfixed(ganho_indice, 4, -27);
acc_phase <= to_sfixed(angulo_indice, 4, -27);
temp_parte_real <= parte_real;
next_state <= calcula_cordic_p2;
variavel_nova <= '1';
when calcula_cordic_p2 =>
if parte_imaginaria >= "0" then
tmp_mult_re_k <= temp_parte_real * K;
tmp_mult_im_k <= parte_imaginaria * K;
parte_real <= resize((parte_real + tmp_mult_im_k),4,-27);
parte_imaginaria <= resize((parte_imaginaria - tmp_mult_re_k),4,-27);
acc_phase_rads <= resize((acc_phase_rads - acc_phase),4,-27);
else
tmp_mult_re_k <= temp_parte_real * K;
tmp_mult_im_k <= parte_imaginaria * K;
parte_real <= resize((parte_real - tmp_mult_im_k),4,-27);
parte_imaginaria <= resize((parte_imaginaria + tmp_mult_re_k),4,-27);
acc_phase_rads <= resize((acc_phase_rads + acc_phase),4,-27);
end if;
if indice < 24 then next_state <= incrementa_cont;
elsif indice = 24 then
next_state <= fim ;
fase_o_r <= resize((not acc_phase_rads) + to_sfixed(1, 4, -27),4,-27) ;
magnitude_o_r <= resize(parte_real * to_sfixed(0.60723, 4, -27),4,-27);
end if;
when incrementa_cont =>
next_state <= calcula_cordic_p1;
if variavel_nova = '1' then
variavel_nova <= '0';
indice <= indice + 1;
indice2 <= indice2 + 1;
end if;
when fim =>
fase_o <= to_slv(fase_o_r);
magnitude_o <= to_slv(magnitude_o_r);
next_state <= init;
end case;
end if;
end process;
end rtl;
It isnt working.. i am having the following problem in modelsim. I have circled the parts of my simualtion with problems.. the signals in this part of my code when corrige_q_p2 =>
if parte_real < "0" then
temp_parte_real <= parte_real;
if parte_imaginaria > "0" then
parte_real <= parte_imaginaria;
parte_imaginaria <= resize(((not temp_parte_real) + to_sfixed(1, 4, -27)),4,-27); --negativo
acc_phase_rads <= resize(((not pi_2) + to_sfixed(1, 4, -27)),4,-27);--negativo
are changing way too fast.. and i am having the following warning Error: :work:fixed_pkg: Unbounded number passed, was a literal used?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
how do you mean they are changing way too fast?

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page