From 1f4d3639349efbd5a571f3dd5680587146d39e5b Mon Sep 17 00:00:00 2001 From: KirupaNithi Date: Mon, 9 Feb 2026 14:52:18 +0530 Subject: [PATCH] Add CORDIC accelerator peripheral and Wishbone wrapper Signed-off-by: KirupaNithi --- peripherals/cordic/cordic.vhdl | 113 ++++++++++++++++++++++++++++++ peripherals/cordic/cordic_wb.vhdl | 86 +++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 peripherals/cordic/cordic.vhdl create mode 100644 peripherals/cordic/cordic_wb.vhdl diff --git a/peripherals/cordic/cordic.vhdl b/peripherals/cordic/cordic.vhdl new file mode 100644 index 0000000..9fe8e0b --- /dev/null +++ b/peripherals/cordic/cordic.vhdl @@ -0,0 +1,113 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity cordic is + generic ( + DATA_WIDTH : integer := 16; + ANGLE_WIDTH : integer := 32; + ITER : integer := 16 + ); + port ( + clk : in std_logic; + angle : in signed(ANGLE_WIDTH-1 downto 0); + Xin : in signed(DATA_WIDTH-1 downto 0); + Yin : in signed(DATA_WIDTH-1 downto 0); + Xout : out signed(DATA_WIDTH downto 0); + Yout : out signed(DATA_WIDTH downto 0) + ); +end entity; + +architecture rtl of cordic is + + type vec_data is array (0 to ITER-1) of signed(DATA_WIDTH downto 0); + type vec_angle is array (0 to ITER-1) of signed(ANGLE_WIDTH-1 downto 0); + + signal X : vec_data := (others => (others => '0')); + signal Y : vec_data := (others => (others => '0')); + signal Z : vec_angle := (others => (others => '0')); + + + -- π/2 = 2^(ANGLE_WIDTH-2) + constant PI_OVER_2 : signed(ANGLE_WIDTH-1 downto 0) + := to_signed(1, ANGLE_WIDTH) sll (ANGLE_WIDTH-2); + + -- Arctan LUT + type lut_t is array (0 to 15) of signed(ANGLE_WIDTH-1 downto 0); + constant atan_lut : lut_t := ( + to_signed(16#20000000#, ANGLE_WIDTH), + to_signed(16#12B4040D#, ANGLE_WIDTH), + to_signed(16#09FB180B#, ANGLE_WIDTH), + to_signed(16#05110875#, ANGLE_WIDTH), + to_signed(16#028B0D43#, ANGLE_WIDTH), + to_signed(16#0142BBF1#, ANGLE_WIDTH), + to_signed(16#00A159CE#, ANGLE_WIDTH), + to_signed(16#0050AC15#, ANGLE_WIDTH), + to_signed(16#00285653#, ANGLE_WIDTH), + to_signed(16#00142F8E#, ANGLE_WIDTH), + to_signed(16#000A17C8#, ANGLE_WIDTH), + to_signed(16#00050BE4#, ANGLE_WIDTH), + to_signed(16#000285F3#, ANGLE_WIDTH), + to_signed(16#000142FB#, ANGLE_WIDTH), + to_signed(16#0000A17D#, ANGLE_WIDTH), + to_signed(16#000050BE#, ANGLE_WIDTH) + ); + +begin + + -- Stage 0 (safe assignments using explicit resize) + stage0: process(clk) + -- temporaries with the target widths so we never assign unknown sized vectors + variable Xin_ext : signed(DATA_WIDTH downto 0); + variable Yin_ext : signed(DATA_WIDTH downto 0); + variable angle_ext: signed(ANGLE_WIDTH-1 downto 0); + begin + if rising_edge(clk) then + -- make explicit widths + Xin_ext := resize(Xin, DATA_WIDTH + 1); + Yin_ext := resize(Yin, DATA_WIDTH + 1); + angle_ext := resize(angle, ANGLE_WIDTH); + + -- quadrant handling (same semantics as before) + if angle_ext > PI_OVER_2 then + X(0) <= -Xin_ext; -- note: rotate by +90 (X <- -Y) + Y(0) <= Xin_ext; -- rotate inputs intentionally preserved style + Z(0) <= angle_ext - PI_OVER_2; + elsif angle_ext < -PI_OVER_2 then + X(0) <= Yin_ext; + Y(0) <= -Xin_ext; + Z(0) <= angle_ext + PI_OVER_2; + else + X(0) <= Xin_ext; + Y(0) <= Yin_ext; + Z(0) <= angle_ext; + end if; + end if; + end process stage0; + -- Iterative pipeline + gen: for i in 0 to ITER-2 generate + process(clk) + variable X_shr, Y_shr : signed(DATA_WIDTH downto 0); + begin + if rising_edge(clk) then + X_shr := X(i) sra i; + Y_shr := Y(i) sra i; + + if Z(i)(ANGLE_WIDTH-1) = '1' then + X(i+1) <= X(i) + Y_shr; + Y(i+1) <= Y(i) - X_shr; + Z(i+1) <= Z(i) + atan_lut(i); + else + X(i+1) <= X(i) - Y_shr; + Y(i+1) <= Y(i) + X_shr; + Z(i+1) <= Z(i) - atan_lut(i); + end if; + end if; + end process; + end generate; + + Xout <= X(ITER-1); + Yout <= Y(ITER-1); + +end architecture; + diff --git a/peripherals/cordic/cordic_wb.vhdl b/peripherals/cordic/cordic_wb.vhdl new file mode 100644 index 0000000..dd51837 --- /dev/null +++ b/peripherals/cordic/cordic_wb.vhdl @@ -0,0 +1,86 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity cordic_wb is + port( + clk : in std_ulogic; + rst : in std_ulogic; + + -- Wishbone IO interface (Microwatt) + wb_adr_i : in std_ulogic_vector(29 downto 0); + wb_dat_i : in std_ulogic_vector(31 downto 0); + wb_dat_o : out std_ulogic_vector(31 downto 0); + wb_we_i : in std_ulogic; + wb_stb_i : in std_ulogic; + wb_cyc_i : in std_ulogic; + wb_ack_o : out std_ulogic; + + -- CORDIC core interface + cordic_x : out std_ulogic_vector(31 downto 0); + cordic_y : out std_ulogic_vector(31 downto 0); + cordic_start : out std_ulogic; + cordic_done : in std_ulogic; + cordic_result : in std_ulogic_vector(31 downto 0) + ); +end entity cordic_wb; + +architecture rtl of cordic_wb is + + signal x_reg : std_ulogic_vector(31 downto 0) := (others => '0'); + signal y_reg : std_ulogic_vector(31 downto 0) := (others => '0'); + signal start_reg : std_ulogic := '0'; + +begin + + -- Drive CORDIC core + cordic_x <= x_reg; + cordic_y <= y_reg; + cordic_start <= start_reg; + + -- Wishbone slave + process(clk) + variable addr : std_ulogic_vector(2 downto 0); + begin + if rising_edge(clk) then + wb_ack_o <= '0'; + + if rst = '1' then + x_reg <= (others => '0'); + y_reg <= (others => '0'); + start_reg <= '0'; + wb_dat_o <= (others => '0'); + + elsif wb_cyc_i = '1' and wb_stb_i = '1' then + wb_ack_o <= '1'; + addr := wb_adr_i(4 downto 2); -- word offsets + + if wb_we_i = '1' then + -- WRITE + case addr is + when "000" => x_reg <= wb_dat_i; -- 0x00 + when "001" => y_reg <= wb_dat_i; -- 0x04 + when "010" => start_reg <= wb_dat_i(0); -- 0x08 + when others => null; + end case; + else + -- READ + case addr is + when "000" => wb_dat_o <= x_reg; -- 0x00 + when "001" => wb_dat_o <= y_reg; -- 0x04 + when "011" => wb_dat_o <= (31 downto 1 => '0') & cordic_done; -- 0x0C + when "100" => wb_dat_o <= cordic_result; -- 0x10 + when others => wb_dat_o <= (others => '0'); + end case; + end if; + end if; + + -- Auto-clear start when done + if cordic_done = '1' then + start_reg <= '0'; + end if; + end if; + end process; + +end architecture rtl; +