📄 cordic_controller_rtl1.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 + -