Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

SINE and COSINE calculations using COiRDIC Algorithm

Status
Not open for further replies.

devika v kurup

Newbie level 6
Joined
May 23, 2011
Messages
11
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,303
Location
India/Kerala
Activity points
1,383
SINE and COSINE calculations using CORDIC Algorithm

Hai,
I am new in this world of fpga. I am trying to code cordic algorithm in vhdl. i want to divide a signed number by a power of 2. i know it can be implement using a shift operation. i searched about syntax of arithmetic shift and got

<signed_sig> sra <shift_amount_in_integer>.

is this a correct one?

please give me an example

- - - Updated - - -

anyone used OpenCore cordic core successfully?
 

no need to use any function for this.

suppose its divide by 8. then simply use a(a'high downto 3) to skip the lsb 3 bits. you may have to pad some zeros at the end. This you can do by using the concatenation operator.
 
i want to divide a signed number by a power of 2

Since it's signed binary...

In the case of a negative number, then its MSB is 1.

Strange things will happen if you right shift all bits.

(Unless the cordic algorithm has a routine to handle this.)
 
Strange things will happen if you right shift all bits.
No strange things should happen with sra. Do you know the difference between arithmetic and logical shift?

The other suggestions are achieving the same, however.
 
No strange things should happen with sra. Do you know the difference between arithmetic and logical shift?

I gather the vhdl (or Cordic) routines are able to handle the MSB in signed binary.
Whether the format is signed magnitude, or One's Complement, or Two's complement.

From the brevity of the replies, it wasn't clear. No one touched on it.

Apparently my remark is superfluous, and there is no need to write a routine to convert a negative number to positive, prior to right shifting.
 
Here is the code.
Code:
--MAIN PROGRAM
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity mycordic is
    Port ( clk : in  STD_LOGIC;
           ena : in  STD_LOGIC;
           ain : in  signed(15 downto 0);
           sin : out  signed(15 downto 0);
           cos : out  signed(15 downto 0));
end mycordic;

architecture Behavioral of mycordic is


constant pipelength:natural:=15;
constant p: signed(15 downto 0):=x"4dba"; --define constant

component core is
generic( pipeline:integer:=15; width:integer:=16);
			
			port(clk:in std_logic;
			ena:in std_logic;
			
			xi: in signed(width -1 downto 0);
			yi: in signed (width -1 downto 0):=(others=>'0');
			zi: in signed (width -1 downto 0);
			
			xo: out signed(width -1 downto 0);
			yo:out signed(width -1 downto 0));
end component;
			
begin
u1: core
				generic map(pipeline=>pipelength, width => 16)
				port map(clk=>clk,ena=>ena,xi=>p,zi=>ain,xo=>cos,yo=>sin);



end Behavioral;

--SECTION 2

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;





entity core is
	Generic(pipeline:integer:=15; width:integer:=16);
   Port ( clk : in  STD_LOGIC;
           ena : in  STD_LOGIC;
           xi : in  signed(width -1 downto 0);
           yi : in  signed(width -1 downto 0):=(others=>'0');
           zi : in  signed(width -1 downto 0);
           xo : out signed(width -1 downto 0);
           yo : out signed(width -1 downto 0));
end core;

architecture Behavioral of core is

type xyvector is array(pipeline downto 0) of signed (width -1 downto 0);
type zvector is array(pipeline downto 0) of signed (19 downto 0);

component cordicpipe
	Generic( width:natural:=16; pipeid:natural:=1);
	Port(clk:in std_logic;
			ena:in std_logic;
			xi:in signed(width -1 downto 0);
			yi:in signed(width -1 downto 0);
			zi:in signed(19 downto 0);
			xo:out signed(width -1 downto 0);
			yo:out signed(width -1 downto 0);
			zo:out signed(19 downto 0));
end component;
			
signal x,y:xyvector;
signal z:zvector;
			
begin

x(0)<=xi;
y(0)<=yi;
z(0)(19 downto 4)<=zi;
z(0)(3 downto 0)<=(others=>'0');

gen_pipe:
for n in 1 to pipeline generate
pipe:cordicpipe
		generic map(width=>width,
						pipeid=>n-1)
		port map(clk,ena,x(n-1),y(n-1),z(n-1),x(n),y(n),z(n));
end generate gen_Pipe;

xo<=x(pipeline);
yo<=y(pipeline);		


end Behavioral;
--SECTION 3

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use  IEEE.numeric_std.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;


entity cordicpipe is
    Generic(width:natural:=16;
			   pipeid: natural:=1);
    Port ( clk : in  STD_LOGIC;
           ena : in  STD_LOGIC;
           xi : in  signed(width -1 downto 0);
           yi : in  signed(width -1 downto 0);
           zi : in signed(19 downto 0);
           xo : out  signed(width -1 downto 0);
           yo : out  signed(width -1 downto 0);
           zo : out  signed(19 downto 0));
end cordicpipe;

architecture Behavioral of cordicpipe is

function CATAN(n:natural) return integer is
	variable result:integer;
	begin
	case n is
						when 0=> result:= 16#020000#;
						when 1=> result:= 16#012E40#;
						when 2=> result:= 16#09FB4#;
						when 3=> result:= 16#05111#;
					   when 4=> result:= 16#028B1#;
						when 5=> result:= 16#0145D#;
						when 6=> result:= 16#0A2F#;
					   when 7=> result:= 16#0518#;
						when 8=> result:= 16#028C#;
						when 9=> result:= 16#0146#;
					   when 10=> result:= 16#0A3#;
						when 11=> result:= 16#051#;
						when 12=> result:= 16#029#;
						when 13=> result:= 16#014#;
						when 14=> result:= 16#0A#;
				   	when 15=> result:= 16#05#;
					   when 16=> result:= 16#03#;
						when 17=> result:= 16#01#;
					   when OTHERS=> result:= 16#0#;
	end case;
	return result;
end catan;



function delta(arg:signed;cnt:natural) return signed is
	variable tmp:signed(arg'range);
	constant lo:integer:= arg'high -cnt +1;

	begin
	for n in arg'high downto lo loop
   tmp(n):=arg(arg'high);
	end loop;
	for n in arg'high -cnt downto 0 loop
	tmp(n):=arg(n +cnt);
	end loop;
	return tmp;
end function delta;



function addsub(dataa,datab:in signed; add_sub:in std_logic) return signed is 

	begin
	if(add_sub='1')then
		return dataa+datab;
	else
		return dataa-datab;
	end if;
end;
	
signal dx,xresult:signed(width-1 downto 0);
signal dy,yresult:signed(width-1 downto 0);
signal atan,zresult:signed(19 downto 0);
signal zneg,zpos:std_logic;

begin
dx<=delta(xi,pipeid);
dy<=delta(yi,pipeid);
atan<= conv_signed(catan(pipeid),20);
zneg<=zi(19);
zpos<=not zi(19);

xresult<= addsub(xi,dy,zneg);
yresult<=addsub(yi,dx,zpos);
zresult<=addsub(zi,atan,zneg);

process(clk)
begin
	if(clk'event and clk='1')then
	if(ena='1')then
	xo<=xresult;
	yo<=yresult;
	zo<=zresult;
	end if;
	end if;
	end process;

end Behavioral;
The cordic pipe contain a delta function.Function delta is actually an arithmetic shift right.
OpenCore explains that , this strange construction is needed for compatibility with Xilinx Webpack.
but i want to eleminate that to avoid complexity.i tried with SRA but it shows error messages. Could you please help me?
 
Last edited:

You need to review the available functions of the used libraries. For STD_LOGIC_ARITH SHR() performs an arithmetic right shift of signed signals.

I don't follow your statement about complexity caused by the delta() function. It's not much different from a SHR() or SRA() implementation in other libraries. A fixed shift doesn't consume any logic elements, it's just a way to wire bits, the same as the methods suggested in post #2 and #3.
 
Code:
--SECTION 3

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use  IEEE.numeric_std.all;


Hi Devika,

I think its not good to use the STD_LOGIC_UNSIGNED and the NUMERIC_STD together in the SECTION 3, because the NUMERIC_STD both unsigned and signed operation, then if you are using the STD_LOGIC_UNSIGNED there is a possibility of crashing the functions with NUMERIC_STD...

So better you use NUMERIC_STD or STD_LOGIC_UNSIGNED...

Also using the function delta for SHR wont make any problem too..
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top