URL
https://opencores.org/ocsvn/mod_sim_exp/mod_sim_exp/trunk
Subversion Repositories mod_sim_exp
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 95 to Rev 94
- ↔ Reverse comparison
Rev 95 → Rev 94
/mod_sim_exp/trunk/rtl/vhdl/core/autorun_cntrl.vhd
70,17 → 70,19
signal bit_counter_0_i : std_logic; |
signal bit_counter_15_i : std_logic; |
signal next_bit_i : std_logic := '0'; |
|
|
signal start_cycle_i : std_logic := '0'; |
signal start_cycle_del_i : std_logic; |
|
|
signal done_i : std_logic; |
signal running_i : std_logic; |
|
|
signal start_multiplier_i : std_logic; |
signal start_multiplier_del_i : std_logic; |
signal mult_done_del_i : std_logic; |
|
|
signal e0_i : std_logic_vector(15 downto 0); |
signal e1_i : std_logic_vector(15 downto 0); |
signal e0_bit_i : std_logic; |
signal e1_bit_i : std_logic; |
signal e_bits_i : std_logic_vector(1 downto 0); |
88,113 → 90,96
signal cycle_counter_i : std_logic; |
signal op_sel_sel_i : std_logic; |
signal op_sel_i : std_logic_vector(1 downto 0); |
|
signal exponent_shift_i : std_logic_vector(31 downto 0); |
signal read_buffer_i : std_logic; |
signal read_buffer_i_d : std_logic; |
begin |
|
done <= done_i; |
read_buffer <= read_buffer_i; |
done <= done_i; |
|
-- the two exponents |
e0_i <= buffer_din(15 downto 0); |
e1_i <= buffer_din(31 downto 16); |
|
-- generate the index to select a single bit from the two exponents |
SYNC_BIT_COUNTER : process (clk, reset) |
begin |
if reset = '1' then |
bit_counter_i <= 15; |
elsif rising_edge(clk) then |
if start = '1' then -- make sure we start @ bit 0 |
bit_counter_i <= 15; |
elsif next_bit_i = '1' then -- count |
if bit_counter_i = 0 then |
bit_counter_i <= 15; |
else |
bit_counter_i <= bit_counter_i - 1; |
end if; |
end if; |
end if; |
end process SYNC_BIT_COUNTER; |
-- generate the index to select a single bit from the two exponents |
SYNC_BIT_COUNTER: process (clk, reset) |
begin |
if reset = '1' then |
bit_counter_i <= 15; |
elsif rising_edge(clk) then |
if start = '1' then -- make sure we start @ bit 0 |
bit_counter_i <= 15; |
elsif next_bit_i = '1' then -- count |
if bit_counter_i = 0 then |
bit_counter_i <= 15; |
else |
bit_counter_i <= bit_counter_i - 1; |
end if; |
end if; |
end if; |
end process SYNC_BIT_COUNTER; |
-- signal when bit_counter_i = 0 |
bit_counter_0_i <= '1' when bit_counter_i=0 else '0'; |
bit_counter_15_i <= '1' when bit_counter_i=15 else '0'; |
-- the bits... |
e0_bit_i <= e0_i(bit_counter_i); |
e1_bit_i <= e1_i(bit_counter_i); |
e_bits_i <= e0_bit_i & e1_bit_i; |
e_bits_0_i <= '1' when (e_bits_i = "00") else '0'; |
|
-- operand pre-select |
with e_bits_i select |
op_sel_i <= "00" when "10", -- gt0 |
"01" when "01", -- gt1 |
"10" when "11", -- gt01 |
"11" when others; |
|
-- select operands |
op_sel_sel_i <= '0' when e_bits_0_i = '1' else (cycle_counter_i); |
op_sel <= op_sel_i when op_sel_sel_i = '1' else "11"; |
|
-- process that drives running_i signal ('1' when in autorun, '0' when not) |
RUNNING_PROC: process(clk, reset) |
begin |
if reset = '1' then |
running_i <= '0'; |
elsif rising_edge(clk) then |
running_i <= start or (running_i and (not done_i)); |
end if; |
end process RUNNING_PROC; |
|
-- ctrl logic |
start_multiplier_i <= start_cycle_del_i or (mult_done_del_i and (cycle_counter_i) and (not e_bits_0_i)); |
read_buffer <= start_cycle_del_i and bit_counter_15_i and running_i; -- pop new word from fifo when bit_counter is back at '15' |
start_multiplier <= start_multiplier_del_i and running_i; |
|
-- start/stop logic |
start_cycle_i <= (start and (not buffer_empty)) or next_bit_i; -- start pulse (external or internal) |
done_i <= (start and buffer_empty) or (next_bit_i and bit_counter_0_i and buffer_empty); -- stop when buffer is empty |
next_bit_i <= (mult_done_del_i and e_bits_0_i) or (mult_done_del_i and (not e_bits_0_i) and (not cycle_counter_i)); |
|
-- process that implements the shift register for the exponents |
-- more performant than former mux implementation |
EXP_SHIFTER : process (clk, reset) |
begin |
if reset = '1' then |
exponent_shift_i <= (others => '0'); |
elsif rising_edge(clk) then |
read_buffer_i_d <= read_buffer_i; -- delay read_buffer signal one clock |
if read_buffer_i_d = '1' then -- after new buffer read, shift in new bits |
exponent_shift_i <= buffer_din; |
elsif next_bit_i = '1' then -- count |
exponent_shift_i(31 downto 1) <= exponent_shift_i(30 downto 0); |
end if; |
end if; |
end process EXP_SHIFTER; |
-- process for delaying signals with 1 clock cycle |
DEL_PROC: process(clk) |
begin |
if rising_edge(clk) then |
start_multiplier_del_i <= start_multiplier_i; |
start_cycle_del_i <= start_cycle_i; |
mult_done_del_i <= multiplier_done; |
end if; |
end process DEL_PROC; |
|
-- process for delaying signals with 1 clock cycle |
CYCLE_CNTR_PROC: process(clk, start, reset) |
begin |
if start = '1' or reset = '1' then |
cycle_counter_i <= '0'; |
elsif rising_edge(clk) then |
if (e_bits_0_i = '0') and (multiplier_done = '1') then |
cycle_counter_i <= not cycle_counter_i; |
elsif (e_bits_0_i = '1') and (multiplier_done = '1') then |
cycle_counter_i <= '0'; |
else |
cycle_counter_i <= cycle_counter_i; |
end if; |
end if; |
end process CYCLE_CNTR_PROC; |
|
end Behavioral; |
|
-- signal when bit_counter_i = 0 |
bit_counter_0_i <= '1' when bit_counter_i = 0 else '0'; |
bit_counter_15_i <= '1' when bit_counter_i = 15 else '0'; |
-- the bits... |
e0_bit_i <= exponent_shift_i(15); |
e1_bit_i <= exponent_shift_i(31); |
e_bits_i <= e0_bit_i & e1_bit_i; |
e_bits_0_i <= '1' when (e_bits_i = "00") else '0'; |
|
-- operand pre-select |
with e_bits_i select |
op_sel_i <= "00" when "10", -- gt0 |
"01" when "01", -- gt1 |
"10" when "11", -- gt01 |
"11" when others; |
|
-- select operands |
op_sel_sel_i <= '0' when e_bits_0_i = '1' else (cycle_counter_i); |
op_sel <= op_sel_i when op_sel_sel_i = '1' else "11"; |
|
-- process that drives running_i signal ('1' when in autorun, '0' when not) |
RUNNING_PROC : process(clk, reset) |
begin |
if reset = '1' then |
running_i <= '0'; |
elsif rising_edge(clk) then |
running_i <= start or (running_i and (not done_i)); |
end if; |
end process RUNNING_PROC; |
|
-- ctrl logic |
start_multiplier_i <= start_cycle_del_i or (mult_done_del_i and (cycle_counter_i) and (not e_bits_0_i)); |
read_buffer_i <= start_cycle_del_i and bit_counter_15_i and running_i; -- pop new word from fifo when bit_counter is back at '15' |
start_multiplier <= start_multiplier_del_i and running_i; |
|
-- start/stop logic |
start_cycle_i <= (start and (not buffer_empty)) or next_bit_i; -- start pulse (external or internal) |
done_i <= (start and buffer_empty) or (next_bit_i and bit_counter_0_i and buffer_empty); -- stop when buffer is empty |
next_bit_i <= (mult_done_del_i and e_bits_0_i) or (mult_done_del_i and (not e_bits_0_i) and (not cycle_counter_i)); |
|
-- process for delaying signals with 1 clock cycle |
DEL_PROC : process(clk) |
begin |
if rising_edge(clk) then |
start_multiplier_del_i <= start_multiplier_i; |
start_cycle_del_i <= start_cycle_i; |
mult_done_del_i <= multiplier_done; |
end if; |
end process DEL_PROC; |
|
-- process for cycle counter |
CYCLE_CNTR_PROC : process(clk, start, reset) |
begin |
if start = '1' or reset = '1' then |
cycle_counter_i <= '0'; |
elsif rising_edge(clk) then |
if (e_bits_0_i = '0') and (multiplier_done = '1') then |
cycle_counter_i <= not cycle_counter_i; |
elsif (e_bits_0_i = '1') and (multiplier_done = '1') then |
cycle_counter_i <= '0'; |
else |
cycle_counter_i <= cycle_counter_i; |
end if; |
end if; |
end process CYCLE_CNTR_PROC; |
|
end Behavioral; |
/mod_sim_exp/trunk/rtl/vhdl/core/mont_ctrl.vhd
79,11 → 79,11
|
|
architecture Behavioral of mont_ctrl is |
signal start_d : std_logic; -- delayed version of start input |
signal start_d : std_logic; -- delayed version of start input |
signal start_pulse : std_logic; |
signal auto_start_pulse : std_logic; |
signal start_multiplier_i : std_logic; |
signal start_up_counter : std_logic_vector(3 downto 0) := "1000"; -- used in op_sel at multiplier start |
signal start_multiplier_i : std_logic; |
signal start_up_counter : std_logic_vector(2 downto 0) := "100"; -- used in op_sel at multiplier start |
|
signal calc_time_i : std_logic; -- high ('1') during multiplication |
|
91,104 → 91,96
signal y_sel : std_logic_vector(1 downto 0); -- the operand used as y input |
signal x_sel_buffer : std_logic_vector(1 downto 0); -- x operand as specified by fifo buffer (autorun) |
|
signal auto_done : std_logic; |
signal start_auto : std_logic; |
signal auto_done : std_logic; |
signal start_auto : std_logic; |
signal auto_multiplier_done_i : std_logic; |
signal multiplier_ready_d : std_logic; |
|
begin |
|
----------------------------------------------------------------------------------- |
-- Processes related to starting and stopping the multiplier |
----------------------------------------------------------------------------------- |
-- generate a start pulse (duration 1 clock cycle) based on ext. start sig |
START_PULSE_PROC : process(clk) |
begin |
if rising_edge(clk) then |
start_d <= start; |
end if; |
end process START_PULSE_PROC; |
|
start_pulse <= start and (not start_d); |
start_auto <= start_pulse and run_auto; |
|
-- to start the multiplier we first need to select the x_operand and |
-- clock it in the x shift register |
-- the we select the y_operand and start the multiplier |
|
-- start_up_counter |
-- default state : "1000" |
-- at start pulse counter resets to 0 and counts up to "1000" |
START_MULT_PROC : process(clk, reset) |
begin |
if reset = '1' then |
start_up_counter <= "1000"; |
elsif rising_edge(clk) then |
if start_pulse = '1' or auto_start_pulse = '1' then |
start_up_counter <= "0000"; |
elsif start_up_counter(3) /= '1' then |
start_up_counter <= start_up_counter + '1'; |
else |
start_up_counter <= "1000"; |
end if; |
end if; |
end process; |
----------------------------------------------------------------------------------- |
-- Processes related to starting and stopping the multiplier |
----------------------------------------------------------------------------------- |
-- generate a start pulse (duration 1 clock cycle) based on ext. start sig |
START_PULSE_PROC: process(clk) |
begin |
if rising_edge(clk) then |
start_d <= start; |
end if; |
end process START_PULSE_PROC; |
start_pulse <= start and (not start_d); |
start_auto <= start_pulse and run_auto; |
|
-- select operands (autorun/single run) |
x_sel <= x_sel_buffer when (run_auto = '1') else x_sel_single; |
y_sel <= "11" when (run_auto = '1') else y_sel_single; -- y is operand3 in auto mode |
|
-- clock operands to operand_mem output (first x, then y) |
with start_up_counter(3 downto 2) select |
op_sel <= x_sel when "00", -- start_up_counter="00xx" (first 4 cycles) |
y_sel when others; -- |
load_x <= (not start_up_counter(2)) and start_up_counter(1) and start_up_counter(0); -- latch x operand if start_up_counter="x011" |
|
-- start multiplier when start_up_counter="x111" |
start_multiplier_i <= start_up_counter(2) and start_up_counter(1) and start_up_counter(0); |
start_multiplier <= start_multiplier_i; |
|
-- signal calc time is high during multiplication |
CALC_TIME_PROC : process(clk, reset) |
begin |
if reset = '1' then |
calc_time_i <= '0'; |
elsif rising_edge(clk) then |
if start_multiplier_i = '1' then |
calc_time_i <= '1'; |
elsif multiplier_ready = '1' then |
calc_time_i <= '0'; |
else |
calc_time_i <= calc_time_i; |
end if; |
end if; |
end process CALC_TIME_PROC; |
calc_time <= calc_time_i; |
|
-- what happens when a multiplication has finished |
-- delay result writeback |
RES_DEL_PROC : process(clk) |
begin |
if rising_edge(clk) then |
multiplier_ready_d <= multiplier_ready; |
load_result <= multiplier_ready_d; |
end if; |
end process; |
-- ignore multiplier_ready when in automode, the logic will assert auto_done when finished |
done <= ((not run_auto) and multiplier_ready) or auto_done; |
|
----------------------------------------------------------------------------------- |
-- Processes related to op_buffer cntrl and auto_run mode |
-- start_auto -> start autorun mode operation |
-- auto_start_pulse <- autorun logic starts the multiplier |
-- auto_done <- autorun logic signals when autorun operation has finished |
-- x_sel_buffer <- autorun logic determines which operand is used as x |
|
-- check buffer empty signal |
----------------------------------------------------------------------------------- |
|
-- multiplier_ready is only passed to autorun control when in autorun mode |
auto_multiplier_done_i <= (multiplier_ready and run_auto); |
-- to start the multiplier we first need to select the x_operand and |
-- clock it in the x shift register |
-- the we select the y_operand and start the multiplier |
|
-- start_up_counter |
-- default state : "100" |
-- at start pulse counter resets to 0 and counts up to "100" |
START_MULT_PROC: process(clk, reset) |
begin |
if reset = '1' then |
start_up_counter <= "100"; |
elsif rising_edge(clk) then |
if start_pulse = '1' or auto_start_pulse = '1' then |
start_up_counter <= "000"; |
elsif start_up_counter(2) /= '1' then |
start_up_counter <= start_up_counter + '1'; |
else |
start_up_counter <= "100"; |
end if; |
end if; |
end process; |
|
-- select operands (autorun/single run) |
x_sel <= x_sel_buffer when (run_auto = '1') else x_sel_single; |
y_sel <= "11" when (run_auto = '1') else y_sel_single; -- y is operand3 in auto mode |
|
-- clock operands to operand_mem output (first x, then y) |
with start_up_counter(2 downto 1) select |
op_sel <= x_sel when "00", -- start_up_counter="00x" (first 2 cycles) |
y_sel when others; -- |
load_x <= start_up_counter(0) and (not start_up_counter(1)); -- latch x operand if start_up_counter="x01" |
|
-- start multiplier when start_up_counter="x11" |
start_multiplier_i <= start_up_counter(1) and start_up_counter(0); |
start_multiplier <= start_multiplier_i; |
|
-- signal calc time is high during multiplication |
CALC_TIME_PROC: process(clk, reset) |
begin |
if reset = '1' then |
calc_time_i <= '0'; |
elsif rising_edge(clk) then |
if start_multiplier_i = '1' then |
calc_time_i <= '1'; |
elsif multiplier_ready = '1' then |
calc_time_i <= '0'; |
else |
calc_time_i <= calc_time_i; |
end if; |
end if; |
end process CALC_TIME_PROC; |
calc_time <= calc_time_i; |
|
-- what happens when a multiplication has finished |
load_result <= multiplier_ready; |
-- ignore multiplier_ready when in automode, the logic will assert auto_done when finished |
done <= ((not run_auto) and multiplier_ready) or auto_done; |
|
----------------------------------------------------------------------------------- |
-- Processes related to op_buffer cntrl and auto_run mode |
-- start_auto -> start autorun mode operation |
-- auto_start_pulse <- autorun logic starts the multiplier |
-- auto_done <- autorun logic signals when autorun operation has finished |
-- x_sel_buffer <- autorun logic determines which operand is used as x |
|
-- check buffer empty signal |
----------------------------------------------------------------------------------- |
|
-- multiplier_ready is only passed to autorun control when in autorun mode |
auto_multiplier_done_i <= (multiplier_ready and run_auto); |
|
autorun_control_logic : autorun_cntrl port map( |
clk => clk, |
reset => reset, |