123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- -- altera vhdl_input_version vhdl_2008
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
- library lpm;
- use lpm.lpm_components.all;
- use work.fifo_pkg.all;
- entity ci_div is
- port (
- clk : in std_logic;
- clk_en : in std_logic;
- reset : in std_logic;
-
- dataa : in std_logic_vector(31 downto 0);
- datab : in std_logic_vector(31 downto 0);
- result : out std_logic_vector(31 downto 0);
- start : in std_logic;
- done : out std_logic;
-
- n : in std_logic_vector(0 downto 0)
- );
- end entity;
- architecture arch of ci_div is
- constant CAPACITY : integer := 64;
- constant SHORT_ZERO : std_logic_vector(15 downto 0) := (others => '0');
- constant LONG_ZERO : std_logic_vector(47 downto 0) := (others => '0');
- component lpm_div
- port (
- clken : in std_logic;
- clock : in std_logic;
- denom : in std_logic_vector(31 downto 0);
- numer : in std_logic_vector(47 downto 0);
- quotient : out std_logic_vector(47 downto 0);
- remain : out std_logic_vector(31 downto 0)
- );
- end component;
- signal reg_shift_request : std_logic_vector(47 downto 0) := LONG_ZERO;
- signal reg_next_shift_request : std_logic_vector(47 downto 0);
- signal enqueue : std_logic := '0';
- signal dequeue : std_logic := '0';
- signal reg_queued : integer range 0 to CAPACITY := 0;
- signal reg_next_queued : integer range 0 to CAPACITY := 0;
- signal capacity_available : std_logic := '0';
- signal reg_dequeue_pending : std_logic := '0';
- signal reg_next_dequeue_pending : std_logic := '0';
- signal reg_enqueue_pending : std_logic := '0';
- signal reg_next_enqueue_pending : std_logic := '0';
- signal lpm_div_done : std_logic := '0';
- signal div_read : std_logic := '0';
- signal div_write : std_logic := '0';
-
- signal fifo_in : fifo_in_t := FIFO_IN_NOP;
- signal fifo_out : fifo_out_t;
- type lpm_in_t is
- record
- denom : std_logic_vector(31 downto 0);
- numer : std_logic_vector(47 downto 0);
- end record;
- constant LPM_IN_NOP : lpm_in_t := (ZERO, LONG_ZERO);
- type lpm_out_t is
- record
- quotient : std_logic_vector(47 downto 0);
- remain : std_logic_vector(31 downto 0);
- end record;
- signal lpm_in : lpm_in_t := LPM_IN_NOP;
- signal lpm_out : lpm_out_t;
- begin
- alt_fwft_fifo_inst : entity work.alt_fwft_fifo
- generic map (
- DATA_WIDTH => 32,
- NUM_ELEMENTS => CAPACITY
- )
- port map (
- aclr => reset,
- clock => clk,
- data => fifo_in.data,
- rdreq => fifo_in.rdreq,
- wrreq => fifo_in.wrreq,
- empty => fifo_out.empty,
- full => fifo_out.full,
- q => fifo_out.q
- );
- lpm_div_inst : component lpm_div
- port map (
- clken => clk_en,
- clock => clk,
- numer => lpm_in.numer,
- denom => lpm_in.denom,
- quotient => lpm_out.quotient,
- remain => lpm_out.remain
- );
- result <= fifo_out.q;
- enqueue <= (not n(0)) and start;
- dequeue <= n(0) and start;
- done <= div_read or div_write;
- capacity_available <= '1' when reg_queued < CAPACITY else '0';
- lpm_div_done <= reg_shift_request(47);
- div_read <= (dequeue or reg_dequeue_pending) and not fifo_out.empty;
- div_write <= (enqueue or reg_enqueue_pending) and capacity_available;
- fifo_in.wrreq <= lpm_div_done;
- fifo_in.data <= lpm_out.quotient(31 downto 0);
- fifo_in.rdreq <= div_read;
- sync : process(clk, clk_en, reset)
- begin
- if reset = '1' then
- -- reset values
- reg_shift_request <= LONG_ZERO;
- reg_enqueue_pending <= '0';
- reg_dequeue_pending <= '0';
- reg_queued <= 0;
- elsif clk_en = '1' and rising_edge(clk) then
- -- register transfer
- reg_shift_request <= reg_next_shift_request;
- reg_enqueue_pending <= reg_next_enqueue_pending;
- reg_dequeue_pending <= reg_next_dequeue_pending;
- reg_queued <= reg_next_queued;
- end if;
- end process;
- async : process(all)
- begin
- -- implement shift register for enqueue operations (to know when lpm_div is done)
- reg_next_shift_request(0) <= div_write;
- reg_next_shift_request(reg_shift_request'high downto 1) <= reg_shift_request(reg_shift_request'high - 1 downto 0);
- -- keep track of started enqueue operation if necessary
- if reg_enqueue_pending = '1' then
- -- deassert reg_enqueue_pending only once done is asserted
- reg_next_enqueue_pending <= not done;
- else
- reg_next_enqueue_pending <= enqueue and not capacity_available;
- end if;
- -- keep track of started dequeue operation if necessary
- if reg_dequeue_pending = '1' then
- -- deassert reg_dequeue_pending only once done is asserted
- reg_next_dequeue_pending <= not done;
- else
- reg_next_dequeue_pending <= dequeue and fifo_out.empty;
- end if;
- -- keep track of available capacity
- reg_next_queued <= reg_queued;
- if reg_queued > 0 and div_read = '1' then
- reg_next_queued <= reg_queued - 1;
- elsif reg_queued < CAPACITY and div_write = '1' then
- reg_next_queued <= reg_queued + 1;
- end if;
- -- extend dataa by 16 bits
- lpm_in.numer <= dataa & SHORT_ZERO;
- lpm_in.denom <= datab;
- end process;
- end architecture;
|