I have written the Verilog version of the below CORDIC VHDL code, however I'm always getting 0 output for the sine wave. Can anyone please tell where is the error/logic error in my code.
Thanks
Edit: I have updated the code after help from hamster_nz and it's working fine now. Thanks everyone.
The main difference was using >>> instead of >> (signed shift vs unsigned shift)
VHDL CODE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity sin_cos is
Port ( clk : in STD_LOGIC;
de_in : in std_logic; //not important, should be always 1
angle : in STD_LOGIC_VECTOR (19 downto 0);
de_out : out std_logic := '0'; //again, not important
sine : out STD_LOGIC_VECTOR (19 downto 0) := (others=>'0');
cosine : out STD_LOGIC_VECTOR (19 downto 0) := (others=>'0'));
end sin_cos;
architecture Behavioral of sin_cos is
type a_int is array(0 to 15) of integer;
constant angles : a_int := ( 77376, 40884, 20753, 10417,
5213, 2607, 1304, 652,
326, 163, 81, 41,
20, 10, 5, 3);
type a_value is array(0 to angles'high+1) of signed(19 downto 0);
signal de_sr : std_logic_vector(angles'high+1 downto 0) := (others => '0'); //not important
signal remainder : a_value := (others => (others => '0'));
signal x : a_value := (others => (others => '0'));
signal y : a_value := (others => (others => '0'));
begin
de_out <= de_sr(de_sr'high);
sine <= std_logic_vector(x(x'high));
cosine <= std_logic_vector(y(y'high));
process(clk)
begin
if rising_edge(clk) then
for i in 0 to angles'high loop
de_sr(i+1) <= de_sr(i);
if remainder(i) < 0 then
remainder(i+1) <= remainder(i) + angles(i);
x(i+1) <= x(i) + y(i)(19 downto i+1);
y(i+1) <= y(i) - x(i)(19 downto i+1);
else
remainder(i+1) <= remainder(i) - angles(i);
x(i+1) <= x(i) - y(i)(19 downto i+1);
y(i+1) <= y(i) + x(i)(19 downto i+1);
end if;
end loop;
de_sr(0) <= de_in;
if de_in = '1' then
case angle(angle'high downto angle'high-1) is
when "00" => x(0) <= to_signed( 300000,20); y(0) <= to_signed( 300000,20); remainder(0) <= signed(angle) - x"20000";
when "01" => x(0) <= to_signed(-300000,20); y(0) <= to_signed( 300000,20); remainder(0) <= signed(angle) - x"60000";
when "10" => x(0) <= to_signed(-300000,20); y(0) <= to_signed(-300000,20); remainder(0) <= signed(angle) - x"A0000";
when others => x(0) <= to_signed( 300000,20); y(0) <= to_signed(-300000,20); remainder(0) <= signed(angle) - x"E0000";
end case;
end if;
end if;
end process;
end Behavioral;
VERILOG CODE
module cordic(clk, angle, sine, cosine);
parameter N = 20;
input clk;
input signed [N-1:0] angle;
output [N-1:0] sine, cosine;
wire [N-1:0] angles [15:0];
assign angles[0] = 77376;
assign angles[1] = 40884;
assign angles[2] = 20753;
assign angles[3] = 10417;
assign angles[4] = 5213;
assign angles[5] = 2607;
assign angles[6] = 1304;
assign angles[7] = 652;
assign angles[8] = 326;
assign angles[9] = 163;
assign angles[10] = 81;
assign angles[11] = 41;
assign angles[12] = 20;
assign angles[13] = 10;
assign angles[14] = 5;
assign angles[15] = 3;
reg signed [N-1:0] remainder [15:0] = {default:0};
reg signed [N-1:0] x [15:0] = {default:0};
reg signed [N-1:0] y [15:0] = {default:0};
assign sine = x[15];
assign cosine = y[15];
integer i;
always @(posedge clk)
begin
for (i=0;i<15;i=i+1)
begin
if (remainder[i] < 0)
begin
remainder[i+1] <= remainder[i] + angles[i];
x[i+1] <= x[i] + (y[i] >>> (i+1));
y[i+1] <= y[i] - (x[i] >>> (i+1));
end
else
begin
remainder[i+1] <= remainder[i] - angles[i];
x[i+1] <= x[i] - (y[i] >>> (i+1));
y[i+1] <= y[i] + (x[i] >>> (i+1));
end
end
end
always @(posedge clk)
begin
case (angle[N-1:N-2])
2'b00:
begin
x[0] <= 20'b01001001001111100000;
y[0] <= 20'b01001001001111100000;
remainder[0] <= angle - 20'b00110000110101000000;
end
2'b01:
begin
x[0] <= ~20'b01001001001111100000 + 1'b1;
y[0] <= 20'b01001001001111100000;
remainder[0] <= angle - 20'b00110000110101000000;
end
2'b10:
begin
x[0] <= ~20'b01001001001111100000 + 1'b1;
y[0] <= ~20'b01001001001111100000 + 1'b1;
remainder[0] <= angle - 20'hA0000;
end
2'b11:
begin
x[0] <= 20'b01001001001111100000;
y[0] <= ~20'b01001001001111100000 + 1'b1;
remainder[0] <= angle - 20'hE0000;
end
endcase
end
endmodule