Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
21615 Discussions

Trying to develop my own Cordic core at VHDL.. problems

Altera_Forum
Honored Contributor II
2,027 Views

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
0 Kudos
9 Replies
Altera_Forum
Honored Contributor II
1,201 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
1,201 Views

Well, I just spotted the problem. You have angulo_indece driven from the 2nd process and the output of the atan block.

0 Kudos
Altera_Forum
Honored Contributor II
1,201 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
1,201 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
1,202 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
1,202 Views

Okay i will make some adjusments. 

Thanks for the knowledge share, seriously :)
0 Kudos
Altera_Forum
Honored Contributor II
1,202 Views

Please see the next post, this one is already old (i've changed the implementation):)

0 Kudos
Altera_Forum
Honored Contributor II
1,202 Views

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?
0 Kudos
Altera_Forum
Honored Contributor II
1,202 Views

how do you mean they are changing way too fast?

0 Kudos
Reply