使用cordic算法生成正弦

时间:2017-09-19 06:32:46

标签: algorithm vhdl cordic

我想为这个+流行的问题道歉,但我在vhdl上找不到具体的实现。我从头开始编写算法,我的数学实现有问题。输出无效。什么都不重要,但只显示1个值。如果有人知道我需要做什么,如何解决它,将非常感谢任何帮助。

数学部分

    library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; 

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--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 massive is
    port ( 
                clk         : in std_logic;
                reset   : in std_logic;
                sinus   : out std_logic_vector (15 downto 0));
end massive;

architecture Behavioral of massive is

type my_type is array (0 to 16) of signed (15 downto 0);
signal x : my_type;
signal y : my_type;
signal z : my_type;
signal j : my_type := ("1010111111001000", "0110011111000101", "0011011011010100", "0001101111010101", "0000110111111000", 
                                                                    "0000011011111110", "0000001101111111", "0000000111000000", "0000000011100000", "0000000001110000",
                                                                     "0000000000111000", "0000000000011100", "0000000000001110", "0000000000000111", "0000000000000100",
                                                                      "0000000000000010", "0000000000000001");
begin

process(clk)

begin
x(0) <= "0000010100000110";
y(0) <= "0000000000000000";
z(0) <= "0000000000000000";
    if rising_edge(clk) then
        if reset <= '1' then
    For n in 0 to 15 loop
        if (z(n) >= 0) then 
            x(n+1) <= x(n) - (y(n)/2**n);
            y(n+1) <= y(n) + (x(n)/2**n);
            z(n+1) <= z(n) + j(n);
        else
            x(n+1) <= x(n) +(y(n)/2**n);
            y(n+1) <= y(n) -(x(n)/2**n);
            z(n+1) <= z(n) - j(n);
        end if;
    end loop;
            sinus <= std_logic_vector(y(16));
    end if;
end if;     
end process;
end Behavioral;

旋转部分

  entity step_control is
    generic (
            first : integer := 0;                           
            second : integer := 1;
            third : integer := 2;
            fourth : integer := 3;                              
    );
    Port ( clk : in  STD_LOGIC;                                 
           Angle : out  STD_LOGIC_VECTOR (12 downto 0);         
           quarter_in : out  STD_LOGIC_VECTOR (1 downto 0));    
end step_control;

architecture Behavioral of step_control is
    signal Ang : std_logic_vector (12 downto 0) := (others => '0');
    signal state : unsigned (1 downto 0) := to_unsigned(first,2);
    signal count_ang : std_logic_vector (11 downto 0) := (others => '0');
begin
process (clk)
begin
    if (rising_edge(clk)) then
        case(state) is
            when to_unsigned(first,2) => if (count_ang >= 3999) then        --00
                            state <= to_unsigned(second,2);
                            count_ang <= "000000010000";
                            quarter_in <= "01";
                            Ang <= Ang - 16;
                        else 
                            state <= to_unsigned(first,2);
                            quarter_in <= "00";
                            Ang <= Ang + 16;
                            count_ang <= count_ang + 16;
                        end if;
            when to_unsigned(second,2) => if (count_ang >= 3999) then       --01
                            state <= to_unsigned(third,2);
                            count_ang <= "000000010000";
                            quarter_in <= "10";
                            Ang <= Ang + 16;
                        else
                            state <= to_unsigned(second,2);
                            quarter_in <= "01";
                            Ang <= Ang - 16;
                            count_ang <= count_ang + 16;
                            end if;
            when to_unsigned(third,2) => if (count_ang >= 3999) then
                            state <= to_unsigned(fourth,2);
                            count_ang <= "000000010000";
                            quarter_in <= "11";
                            Ang <= Ang - 16;
                        else
                            state <= to_unsigned(third,2);
                            quarter_in <= "10";
                            Ang <= Ang + 16;
                            count_ang <= count_ang + 16;
                            end if;
            when to_unsigned(fourth,2) => if (count_ang >= 3999) then
                            state <= to_unsigned(first,2);
                            count_ang <= "000000010000";
                            quarter_in <= "00";
                            Ang <= Ang + 16;
                        else
                            state <= to_unsigned(fourth,2);
                            quarter_in <= "11";
                            Ang <= Ang - 16;
                            count_ang <= count_ang + 16;
                            end if;
            when others => count_ang <= (others => '0');
        end case;
    end if;
end process;
Angle <= Ang;
end Behavioral;

和测试台(但我不知道,我有点在模块中询问。而且我的&#34;空的&#34; tesbench已经获得)

ENTITY testmass IS
END testmass;

ARCHITECTURE behavior OF testmass IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT massive
    PORT(
         clk : IN  std_logic;
         reset : IN  std_logic;
         sinus : OUT  std_logic_vector(15 downto 0)
        );
    END COMPONENT;


   --Inputs
   signal clk : std_logic := '0';
   signal reset : std_logic := '0';

    --Outputs
   signal sinus : std_logic_vector(15 downto 0);

   -- Clock period definitions
   constant clk_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: massive PORT MAP (
          clk => clk,
          reset => reset,
          sinus => sinus
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
      wait for 100 ns;  

      wait for clk_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;

1 个答案:

答案 0 :(得分:1)

您的问题不是Minimal, Complete and Verifiable example,而是无法验证:

  

描述问题。“它不起作用”不是问题陈述。告诉我们预期的行为应该是什么。告诉我们错误消息的确切措辞是什么,以及生成它的代码行。在问题的标题中简要介绍问题。

输出无效。什么都不重要,但只显示1个值。

一个值是多少?当有人试图复制你的问题时,我们看到的一件事是对实体大量过程中z(n)的每次评估的断言警告:

       if (z(n) >= 0) then 

这个问题是VHDL信号的基础问题。

您可以为流程中的信号分配值,并期望它们立即可用。那不会发生。在任何过程尚未恢复并随后在当前模拟循环中暂停时,不会更新任何信号。

对于投影输出波形(队列)中的每个模拟时间,只有一个条目。后续分配(此处不会发生)将导致仅排队最后一个值。

更重要的是,未来的值在当前的模拟周期中不可用。

x,y和z可以是在过程中声明的变量:

architecture foo of massive is
    -- not predefined before -2008:
    function to_string (inp: signed) return string is
        variable image_str: string (1 to inp'length);
        alias input_str:  signed (1 to inp'length) is inp;
    begin
        for i in input_str'range loop
            image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
        end loop;
        return image_str;
    end function;
begin

    process (clk)
        type my_type is array (0 to 16) of signed (15 downto 0);
        variable x:  my_type;
        variable y:  my_type;
        variable z:  my_type;
        constant j:  my_type := ("1010111111001000", "0110011111000101",
                                 "0011011011010100", "0001101111010101",
                                 "0000110111111000", "0000011011111110",
                                 "0000001101111111", "0000000111000000",
                                 "0000000011100000", "0000000001110000",
                                 "0000000000111000", "0000000000011100",
                                 "0000000000001110", "0000000000000111",   
                                 "0000000000000100", "0000000000000010",
                                 "0000000000000001");
    begin
        x(0) := "0000010100000110";
        y(0) := "0000000000000000";
        z(0) := "0000000000000000";
        if rising_edge(clk) then
            if reset = '0' then  -- reset not driven condition was <=
                report "init values:" & LF & HT &
                       "x(0) = " & to_string(x(0)) & LF & HT &
                       "y(0) = " & to_string(y(0)) & LF & HT &
                       "z(0) = " & to_string(z(0));
                for n in 0 to 15 loop
                    if z(n) >= 0 then 
                        x(n + 1) := x(n) - y(n) / 2 ** n;
                        y(n + 1) := y(n) + x(n) / 2 ** n;
                        z(n + 1) := z(n) + j(n);
                    else
                        x(n + 1) := x(n) + y(n) / 2 ** n;
                        y(n + 1) := y(n) - x(n) / 2 ** n;
                        z(n + 1) := z(n) - j(n);
                    end if;
                    report  "n = " & integer'image(n) & LF & HT &
                           "x(" & integer'image(n + 1) & ") = " & 
                                   to_string(x(n + 1)) & LF & HT &
                           "y(" & integer'image(n + 1) & ") = " & 
                                   to_string(y(n + 1)) & LF & HT &
                           "z(" & integer'image(n + 1) & ") = " & 
                                   to_string(z(n + 1));
                end loop;
                sinus <= std_logic_vector(y(16));
                report "sinus = " & to_string(y(16));
            end if;
        end if;     
    end process;
end architecture foo;

添加报告语句以允许将值输出到模拟控制台。没有连续分配变量之间的时间间隔,波形中的变量值没有用处。有些模拟器不会报告波形转储中的变量。

以上架构产生:

ghdl -a testmass.vhdl
ghdl -e testmass
ghdl -r testmass
testmass.vhdl:86:17:@5ns:(report note): init values:
  x(0) = 0000010100000110
  y(0) = 0000000000000000
  z(0) = 0000000000000000
testmass.vhdl:100:21:@5ns:(report note): n = 0
  x(1) = 0000010100000110
  y(1) = 0000010100000110
  z(1) = 1010111111001000
testmass.vhdl:100:21:@5ns:(report note): n = 1
  x(2) = 0000011110001001
  y(2) = 0000001010000011
  z(2) = 0100100000000011
testmass.vhdl:100:21:@5ns:(report note): n = 2
  x(3) = 0000011011101001
  y(3) = 0000010001100101
  z(3) = 0111111011010111
testmass.vhdl:100:21:@5ns:(report note): n = 3
  x(4) = 0000011001011101
  y(4) = 0000010101000010
  z(4) = 1001101010101100
testmass.vhdl:100:21:@5ns:(report note): n = 4
  x(5) = 0000011010110001
  y(5) = 0000010011011101
  z(5) = 1000110010110100
testmass.vhdl:100:21:@5ns:(report note): n = 5
  x(6) = 0000011011010111
  y(6) = 0000010010101000
  z(6) = 1000010110110110
testmass.vhdl:100:21:@5ns:(report note): n = 6
  x(7) = 0000011011101001
  y(7) = 0000010010001101
  z(7) = 1000001000110111
testmass.vhdl:100:21:@5ns:(report note): n = 7
  x(8) = 0000011011110010
  y(8) = 0000010010000000
  z(8) = 1000000001110111
testmass.vhdl:100:21:@5ns:(report note): n = 8
  x(9) = 0000011011110110
  y(9) = 0000010001111010
  z(9) = 0111111110010111
testmass.vhdl:100:21:@5ns:(report note): n = 9
  x(10) = 0000011011110100
  y(10) = 0000010001111101
  z(10) = 1000000000000111
testmass.vhdl:100:21:@5ns:(report note): n = 10
  x(11) = 0000011011110101
  y(11) = 0000010001111100
  z(11) = 0111111111001111
testmass.vhdl:100:21:@5ns:(report note): n = 11
  x(12) = 0000011011110101
  y(12) = 0000010001111100
  z(12) = 0111111111101011
testmass.vhdl:100:21:@5ns:(report note): n = 12
  x(13) = 0000011011110101
  y(13) = 0000010001111100
  z(13) = 0111111111111001
testmass.vhdl:100:21:@5ns:(report note): n = 13
  x(14) = 0000011011110101
  y(14) = 0000010001111100
  z(14) = 1000000000000000
testmass.vhdl:100:21:@5ns:(report note): n = 14
  x(15) = 0000011011110101
  y(15) = 0000010001111100
  z(15) = 0111111111111100
testmass.vhdl:100:21:@5ns:(report note): n = 15
  x(16) = 0000011011110101
  y(16) = 0000010001111100
  z(16) = 0111111111111110
testmass.vhdl:109:17:@5ns:(report note): sinus = 0000010001111100

我们看到你的数组元素的值正在改变,而不是通过在前一循环迭代中分配的加法(或z(n)<0时的减法)传播'X'。

另请注意,重置不会更改测试平台中的值,并且在原始大规模过程中使用关系运算符“&lt; =”对其值进行错误评估。

除了初始值之外,

j不会被分配,并且在上述架构中显示为常量。

我个人有点怀疑你可以执行这16个链式加法或减法,同时选择一个10 ns时钟中的哪个操作。