⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cordic_controller_rtl1.vhd

📁 这是实现cordic算法的一些源程序
💻 VHD
字号:
	--
-- VHDL Architecture HDesign_lib.cordic_control.rtl
--
-- Created:
--          by - gening.UNKNOWN (APWORKS)
--          at - 09:01:02 2006-03-24
--
-- using Mentor Graphics HDL Designer(TM) 2005.2 (Build 37)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

ENTITY cordic_control IS
   PORT( 
      clk       : IN     std_logic;
      enable    : IN     std_logic;                        -- theta indication
      reset     : IN     std_logic;
      theta     : IN     std_logic_vector (15 DOWNTO 0);   -- input angle	 
	  
      x_data1   : IN     std_logic;                        -- Data from RAMX port 1, shifted of x
      x_value   : IN     std_logic;                        -- add/sub result from adder
      y_data1   : IN     std_logic;
      y_value   : IN     std_logic;
      z_value   : IN     std_logic;	
	  
      valid     : OUT    std_logic;                        -- sin value valid indication
      value     : OUT    std_logic_vector (15 DOWNTO 0);   -- value for sin(theta)	  
		  
      x_addend  : OUT    std_logic;                        -- addend selected from x_data1 or 0
      x_addr0   : OUT    std_logic_vector ( 3 DOWNTO 0 );  -- address for RAMX port 0, original data
      x_addr1   : OUT    std_logic_vector ( 3 DOWNTO 0 );  -- address for RAMX port1, shifted data
      x_data0   : OUT    std_logic;                        -- write back add/sub result
      x_op      : OUT    std_logic_vector ( 1 DOWNTO 0 );  -- operation control for adder
      x_re0     : OUT    std_logic;                        -- read enable for RAMX port0
      x_re1     : OUT    std_logic;                        -- read enable for RAMX port1
      x_we0     : OUT    std_logic;  
	  -- write enable for RAMX port0, never write to port1
		  
      y_addend  : OUT    std_logic;
      y_addr0   : OUT    std_logic_vector ( 3 DOWNTO 0 );
      y_addr1   : OUT    std_logic_vector ( 3 DOWNTO 0 );
      y_data0   : OUT    std_logic;
      y_op      : OUT    std_logic_vector ( 1 DOWNTO 0 );
      y_re0     : OUT    std_logic;
      y_re1     : OUT    std_logic;
      y_we0     : OUT    std_logic;				  
	  
	  z_addr0   : OUT    std_logic_vector ( 3 DOWNTO 0 );
      z_data0   : OUT    std_logic;
      z_data1   : OUT    std_logic;
      z_op      : OUT    std_logic_vector ( 1 DOWNTO 0 );
      z_re0     : OUT    std_logic;
      z_romdata : OUT    std_logic;                        -- stored rotated angle 
      z_we0     : OUT    std_logic
   );

-- Declarations

END cordic_control ;

--
ARCHITECTURE beh OF cordic_control IS
-- all are 2 complement signed 16bit
signal theta_shift_reg, value_shift_reg : std_logic_vector(15 downto 0);
signal zsign : std_logic;
signal clear_addend : std_logic;
constant initx : std_logic_vector(15 downto 0) :="0100110110111010"; --0.6073 初始的X值; 	 

subtype romword is std_logic_vector(15 downto 0);
type rom is array(0 to 11) of romword;
--constant zrom : rom :=(		               --角度寄存器;经试验查知该角度值存储的是不对的。
--"0100000000000000", 	--arctan(2^(-0))
--"0010010111001000", 	--arctan(2^(-1))
--"0001001111110110", 	--arctan(2^(-2))
--"0000101000100010", 	--arctan(2^(-3))
--"0000010100010110", 	--arctan(2^(-4))
--"0000001010001100", 	--arctan(2^(-5))
--"0000000101000110", 	--arctan(2^(-6))
--"0000000010100011", 	--arctan(2^(-7))
--"0000000001010001", 	--arctan(2^(-8))
--"0000000000101001", 	--arctan(2^(-9))
--"0000000000010100", 	--arctan(2^(-10))
--"0000000000001010" 	    --arctan(2^(-11))
--);
--
constant zrom : rom :=(		--正确的角度寄存器;
"0110010010000111", 	--arctan(2^(-0))
"0011101101011000", 	--arctan(2^(-1))
"0001111101011011", 	--arctan(2^(-2))
"0000111111101010", 	--arctan(2^(-3))
"0000011111111101", 	--arctan(2^(-4))
"0000001111111111", 	--arctan(2^(-5))
"0000000111111111", 	--arctan(2^(-6))
"0000000011111111", 	--arctan(2^(-7))
"0000000001111111", 	--arctan(2^(-8))
"0000000000111111", 	--arctan(2^(-9))
"0000000000011111", 	--arctan(2^(-10))
"0000000000001111" 	    --arctan(2^(-11))
);



signal start_inner_loop:std_logic:='0';	 --
signal m:integer:=0;
BEGIN
  main_prc: process(clk,reset)
  -- drivers method 
  procedure write_ramx (		   --给出地址,数据,写使能信号即可;
  data : in std_logic;
  addr : in integer
  ) is
  begin
    x_data0<=data;
    x_addr0<=std_logic_vector(to_unsigned(addr,4));
    x_we0<='1';
  end procedure;
  
  procedure write_ramy (
  data : in std_logic;
  addr : in integer
  ) is
  begin
    y_data0<=data;
    y_addr0<=std_logic_vector(to_unsigned(addr,4));
    y_we0<='1';
  end procedure;  
  
  procedure write_ramz (
  data : in std_logic;
  addr : in integer
  ) is
  begin
    z_data0<=data;
    z_addr0<=std_logic_vector(to_unsigned(addr,4));
    z_we0<='1';
  end procedure;  
  
  procedure read_ramx (				  --给出地址,读使能信号即可;
  addr0 : in integer;
  addr1 : in integer
  ) is
  begin
    x_addr0<=std_logic_vector(to_unsigned(addr0,4));
    x_addr1<=std_logic_vector(to_unsigned(addr1,4));
    x_re0<='1';
    x_re1<='1';
  end procedure;    
  procedure read_ramy (
  addr0 : in integer;
  addr1 : in integer
  ) is
  begin
    y_addr0<=std_logic_vector(to_unsigned(addr0,4));
    y_addr1<=std_logic_vector(to_unsigned(addr1,4));
    y_re0<='1';
    y_re1<='1';
  end procedure;   
  procedure read_ramz (
  addr0 : in integer
  ) is
  begin
    z_addr0<=std_logic_vector(to_unsigned(addr0,4));
    z_re0<='1';
  end procedure;  
  
  procedure default_all is	   --ram控制信号初始; 需要一个时钟周期;
  begin
    -- x part
    x_addr0<=(others=>'0');
    x_addr1<=(others=>'0');
    x_op<="00";
    x_data0<='Z';
    x_we0<='0';
    x_re0<='0';
    x_re1<='0';
    -- y part
    y_addr0<=(others=>'0');
    y_addr1<=(others=>'0');
    y_op<="00";
    y_data0<='Z';
    y_we0<='0';
    y_re0<='0';
    y_re1<='0';      
    -- z part
    z_addr0<=(others=>'0');
    z_op<="00";
    z_data0<='Z';
    z_we0<='0';
    z_re0<='0';
    z_romdata<='0';
    -- others   
    valid<='0';
    clear_addend<='0'; 
  end procedure; 
  
  
  
  procedure start_cordic is
  begin
    default_all;	-- 开始计算前,存储器ram控制信号的初始化:不读不写,地址指针指向第一个比特单元 ;
					-- 操作为00:保持状态,
  end procedure;  
  
--  procedure load_theta is
--  begin
--    wait until rising_edge(clk);			   -- 等待enable 信号,在上升沿判断enable,若为1则进行后续计算;
--    waiten_loop: loop
--    if enable='1' then 
--      exit;
--    end if;
--    wait until rising_edge(clk);
--  end loop;
--  theta_shift_reg<=theta;				       --把 theta 装载到移位寄存器中; 
--  zsign<=theta(15);						   --判断初始输入角度的符号;
--  wait until rising_edge(clk);
--  for i in 0 to 15 loop			     -- 把初始x值写入到ramx中;(每个时钟周期写一个比特,一共耗费16个周期)
--    write_ramx(initx(i),i);		     --把初始0写入到ramy 中;
--    write_ramy('0',i);
--    write_ramz(theta_shift_reg(0),i);  --把初始输入角度theta写入到ramz中;
--    theta_shift_reg<='0'& theta_shift_reg(15 downto 1);       
--    wait until rising_edge(clk);
--  end loop;
--  default_all;			 		--在写ramx,ramy,ramz的时候改变了向ram模块提供的控制信号,现在写完了恢复过来;
--  end procedure;			  
--
--procedure calculate is			--计算;
--variable x1,y1,z1 : std_logic;  -- the other addend 
--begin
--  for i in 0 to 11 loop
--    default_all;
--    -- reset adder 01 :初始化加法器; 
--    x_op<="01";y_op<="01";z_op<="01";
--    wait until rising_edge(clk);
--    for j in 0 to 15 loop 
--      if j+i<=15 then
--        read_ramx(j,j+i);
--        read_ramy(j,j+i);
--      else
--        read_ramx(j,0);
--        read_ramy(j,0);
--      end if;
--      read_ramz(j);
--      wait until rising_edge(clk);
--      default_all;
--      x_op<='1' & zsign;
--      y_op<='1' & (not zsign);
--      z_op<='1' & zsign;
--      z_romdata<=zrom(i)(j);
--      if j+i>15 then
--        clear_addend<='1';
--      end if;
--      wait until rising_edge(clk);  
--      default_all;  
--      wait until rising_edge(clk); 
--      write_ramx(x_value,j);
--      write_ramy(y_value,j);
--      write_ramz(z_value,j);
--      if j=15 then
--        zsign<=z_value;
--      end if;
--      wait until rising_edge(clk);
--      default_all;
--    end loop;
--  end loop;
--end procedure;
--procedure load_result is
--begin
--  for i in 0 to 15 loop
--    read_ramy(0,i);
--    wait until rising_edge(clk);
--    value_shift_reg<=y_data1 & value_shift_reg(15 downto 1);
--  end loop;
--  default_all;
--  wait until rising_edge(clk);
--  value_shift_reg<=y_data1 & value_shift_reg(15 downto 1);
--  valid<='1';
--  wait until rising_edge(clk);
--  default_all;
--end procedure;
--




  --主控制进程;
variable count:integer:=0;
variable sts:integer;
variable i,j:integer:=0;  

begin	
  if reset='1' then		   	  -- 异步复位,为计算做准备;
      start_cordic;	 
	  count:=-1;   -- count 用于整个流程控制;
	  i:=0;j:=0; sts:=1; start_inner_loop<='0'; 	   --i,j 用于计算时的内外循环变量; sts:内层循环状态;
	                                                   --start_inner_loop:指示开始内层循环;
	  
	  m<=-1; 										   --用于装载结果result计数器;								
  elsif rising_edge(clk) then
	    if enable='1' and count=-1 then
		      theta_shift_reg<=theta;				   --把 theta 装载到移位寄存器中; 
              zsign<=theta(15); 
		      count:=0;
	    end if;	
	
	    if count=0 then count:=1;  								--空闲一个时钟周期;
		elsif  count<17 then
		    write_ramx(initx(count-1),count-1);					--把初始X值initx写入到ramx 中;
     		write_ramy('0',count-1);							--把初始0写入到ramy 中;
   			write_ramz(theta_shift_reg(0),count-1); 		    --把初始输入角度theta写入到ramz中;
   			theta_shift_reg<='0'& theta_shift_reg(15 downto 1); 
			count:=count+1;
  		elsif count=17	 then
		  default_all;
		  count:=count+1;
		elsif count=18	 then	  --开始计算:含两层循环;外层i表示计算次数,越循环次数多,精度越大。
		 ---------------------------------------------------  
		  if i<12  then 		   	                 -- outer loop 12 times;  
			if j=0 and start_inner_loop='0' then
			   default_all; 
			   start_inner_loop<='1';
    		                                         -- reset adder 01 :初始化加法器; 
    		   x_op<="01";y_op<="01";z_op<="01";  	
			end if;
			
		  
		   if j<16 and start_inner_loop='1' then         --inner loop 16 times;	j=0---15; 计算各个位的结果;
			  case sts is	                  
				 when 1=>
			          if j+i<=15 then
        	            read_ramx(j,j+i);
        	            read_ramy(j,j+i);
      		           else
        	            read_ramx(j,0);
        	            read_ramy(j,0);
      		           end if;
      		          read_ramz(j);	 
					  sts:=2;
			    when 2=>
			          default_all;
                      x_op<='1' & zsign;
                      y_op<='1' & (not zsign);
                      z_op<='1' & zsign;
                         z_romdata<=zrom(i)(j);
                         if j+i>15 then
                         clear_addend<='1';
						 end if; 
					 sts:=3;
			   when 3=>
			        default_all;  
			        sts:=4;
			   when 4=>
			            write_ramx(x_value,j);
                        write_ramy(y_value,j);
                        write_ramz(z_value,j);
                     if j=15 then
                         zsign<=z_value;
					 end if; 	
				   sts:=5;
			  when 5=>
			       default_all;  
			  	   j:=j+1;                      -- 内循环计数器 
				   sts:=1;
			  when others=>
			  		   default_all;  
			end case;
		 end if;					-- end  for : j<16;
		
		 if j=16 then		  		            -- 内循环完毕,把内循环计数器清0,外循环计数器加1; 
			j:=0;
			i:=i+1;	 
			start_inner_loop<='0';             	--设为0是为了在开始新一轮内循环之前有一个时钟周期做加法器初始化;
		 end if;					    -- end for j==16; 
		
	   end	if;			    --end for i<12 
		
	   if i=12  then	                               --外循环结束,则转入 load result步骤;
		   count:=count+1; 
		   m<=0;                                       -- for  "load result"  计数器m  初始化 
	   end	if;				--end for i==12; 
	  --------------------------------------------------
	elsif count=19 then  ---------------load result  ; 
		if m=0 then
		 read_ramy(0,m);  
		 m<=m+1;
		elsif  m<16 then
			read_ramy(0,m);	
			value_shift_reg<=y_data1&value_shift_reg(15 downto 1) ; 
			m<=m+1;	--	 
		elsif m=16 then	 		--因为value_shift_reg比y_data1要晚两个时钟周期
			value_shift_reg<=y_data1&value_shift_reg(15 downto 1);
			m<=m+1;
		elsif m=17 then
			value_shift_reg<=y_data1&value_shift_reg(15 downto 1); 	
			valid<='1';			--指示此时的输出信号有效!!!!!!!!!!!!!!!!!
  			m<=m+1;
	    else
			default_all;  
			m<=0;
		end if;
		
	end	 if;      --end : for count;  
 end if;	  --end  for rising_edge(clk);
			
end process;

value<=value_shift_reg;	   --输出最后结果

x_addend<='0' when clear_addend='1' else y_data1;
y_addend<='0' when clear_addend='1' else x_data1;

END ARCHITECTURE beh;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -