Line 86... |
Line 86... |
signal sub_res : std_ulogic_vector(data_width_c-1 downto 0);
|
signal sub_res : std_ulogic_vector(data_width_c-1 downto 0);
|
signal cmp_equal : std_ulogic;
|
signal cmp_equal : std_ulogic;
|
signal cmp_less : std_ulogic;
|
signal cmp_less : std_ulogic;
|
|
|
-- shifter --
|
-- shifter --
|
signal shift_cmd : std_ulogic;
|
type shifter_t is record
|
signal shift_cmd_ff : std_ulogic;
|
cmd : std_ulogic;
|
signal shift_start : std_ulogic;
|
cmd_ff : std_ulogic;
|
signal shift_run : std_ulogic;
|
start : std_ulogic;
|
signal shift_cnt : std_ulogic_vector(4 downto 0);
|
run : std_ulogic;
|
signal shift_sreg : std_ulogic_vector(data_width_c-1 downto 0);
|
cnt : std_ulogic_vector(4 downto 0);
|
|
sreg : std_ulogic_vector(data_width_c-1 downto 0);
|
|
end record;
|
|
signal shifter : shifter_t;
|
|
|
-- co-processor interface --
|
-- co-processor interface --
|
signal cp_cmd_ff : std_ulogic;
|
signal cp_cmd_ff : std_ulogic;
|
signal cp_run : std_ulogic;
|
signal cp_run : std_ulogic;
|
signal cp_start : std_ulogic;
|
signal cp_start : std_ulogic;
|
Line 108... |
Line 111... |
-- Operand Mux ----------------------------------------------------------------------------
|
-- Operand Mux ----------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
input_op_mux: process(ctrl_i, csr_i, pc2_i, rs1_i, rs2_i, imm_i)
|
input_op_mux: process(ctrl_i, csr_i, pc2_i, rs1_i, rs2_i, imm_i)
|
begin
|
begin
|
-- opa (first ALU input operand) --
|
-- opa (first ALU input operand) --
|
if (ctrl_i(ctrl_alu_opa_mux_msb_c) = '0') then
|
case ctrl_i(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) is
|
if (ctrl_i(ctrl_alu_opa_mux_lsb_c) = '0') then
|
when "00" => opa <= rs1_i;
|
opa <= rs1_i;
|
when "01" => opa <= pc2_i;
|
else
|
when others => opa <= csr_i;
|
opa <= pc2_i;
|
end case;
|
end if;
|
|
else
|
|
opa <= csr_i;
|
|
end if;
|
|
-- opb (second ALU input operand) --
|
-- opb (second ALU input operand) --
|
if (ctrl_i(ctrl_alu_opb_mux_msb_c) = '0') then
|
case ctrl_i(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) is
|
if (ctrl_i(ctrl_alu_opb_mux_lsb_c) = '0') then
|
when "00" => opb <= rs2_i;
|
opb <= rs2_i;
|
when "01" => opb <= imm_i;
|
else
|
when others => opb <= rs1_i;
|
opb <= imm_i;
|
end case;
|
end if;
|
|
else
|
|
opb <= rs1_i;
|
|
end if;
|
|
-- opc (second operand for comparison (and SUB)) --
|
-- opc (second operand for comparison (and SUB)) --
|
if (ctrl_i(ctrl_alu_opc_mux_c) = '0') then
|
if (ctrl_i(ctrl_alu_opc_mux_c) = '0') then
|
opc <= imm_i;
|
opc <= imm_i;
|
else
|
else
|
opc <= rs2_i;
|
opc <= rs2_i;
|
Line 164... |
Line 159... |
-- Iterative Shifter Unit -----------------------------------------------------------------
|
-- Iterative Shifter Unit -----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
shifter_unit: process(rstn_i, clk_i)
|
shifter_unit: process(rstn_i, clk_i)
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
shift_sreg <= (others => '0');
|
shifter.sreg <= (others => '0');
|
shift_cnt <= (others => '0');
|
shifter.cnt <= (others => '0');
|
shift_cmd_ff <= '0';
|
shifter.cmd_ff <= '0';
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
shift_cmd_ff <= shift_cmd;
|
shifter.cmd_ff <= shifter.cmd;
|
if (shift_start = '1') then -- trigger new shift
|
if (shifter.start = '1') then -- trigger new shift
|
shift_sreg <= opa; -- shift operand
|
shifter.sreg <= opa; -- shift operand
|
shift_cnt <= opb(index_size_f(data_width_c)-1 downto 0); -- shift amount
|
shifter.cnt <= opb(index_size_f(data_width_c)-1 downto 0); -- shift amount
|
elsif (shift_run = '1') then -- running shift
|
elsif (shifter.run = '1') then -- running shift
|
shift_cnt <= std_ulogic_vector(unsigned(shift_cnt) - 1);
|
-- coarse shift -> multiples of 4 --
|
|
if (or_all_f(shifter.cnt(shifter.cnt'left downto 2)) = '1') then -- shift amount >= 4
|
|
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 4);
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
|
shift_sreg <= shift_sreg(shift_sreg'left-1 downto 0) & '0';
|
shifter.sreg <= shifter.sreg(shifter.sreg'left-4 downto 0) & "0000";
|
else -- SRL: shift right logical / SRA: shift right arithmetical
|
else -- SRL: shift right logical / SRA: shift right arithmetical
|
shift_sreg <= (shift_sreg(shift_sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shift_sreg(shift_sreg'left downto 1);
|
shifter.sreg <= (shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
|
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
|
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
|
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 4);
|
|
end if;
|
|
-- fine shift -> 0..3 --
|
|
else
|
|
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 1);
|
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
|
|
shifter.sreg <= shifter.sreg(shifter.sreg'left-1 downto 0) & '0';
|
|
else -- SRL: shift right logical / SRA: shift right arithmetical
|
|
shifter.sreg <= (shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 1);
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process shifter_unit;
|
end process shifter_unit;
|
|
|
-- is shift operation? --
|
-- is shift operation? --
|
shift_cmd <= '1' when (ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) = alu_cmd_shift_c) else '0';
|
shifter.cmd <= '1' when (ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) = alu_cmd_shift_c) else '0';
|
shift_start <= '1' when (shift_cmd = '1') and (shift_cmd_ff = '0') else '0';
|
shifter.start <= '1' when (shifter.cmd = '1') and (shifter.cmd_ff = '0') else '0';
|
|
|
-- shift operation running? --
|
-- shift operation running? --
|
shift_run <= '1' when (or_all_f(shift_cnt) = '1') or (shift_start = '1') else '0';
|
shifter.run <= '1' when (or_all_f(shifter.cnt) = '1') or (shifter.start = '1') else '0';
|
|
|
|
|
-- Coprocessor Interface ------------------------------------------------------------------
|
-- Coprocessor Interface ------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
cp_interface: process(rstn_i, clk_i)
|
cp_interface: process(rstn_i, clk_i)
|
Line 229... |
Line 238... |
cp_run <= cp_busy or cp_start;
|
cp_run <= cp_busy or cp_start;
|
|
|
|
|
-- ALU Function Select --------------------------------------------------------------------
|
-- ALU Function Select --------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
alu_function_mux: process(ctrl_i, opa, opb, add_res, sub_res, cmp_less, shift_sreg)
|
alu_function_mux: process(ctrl_i, opa, opb, add_res, sub_res, cmp_less, shifter)
|
begin
|
begin
|
case ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) is
|
case ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) is
|
when alu_cmd_bitc_c => alu_res <= opa and (not opb); -- bit clear (for CSR modifications only)
|
when alu_cmd_bitc_c => alu_res <= opa and (not opb); -- bit clear (for CSR modifications only)
|
when alu_cmd_xor_c => alu_res <= opa xor opb;
|
when alu_cmd_xor_c => alu_res <= opa xor opb;
|
when alu_cmd_or_c => alu_res <= opa or opb;
|
when alu_cmd_or_c => alu_res <= opa or opb;
|
when alu_cmd_and_c => alu_res <= opa and opb;
|
when alu_cmd_and_c => alu_res <= opa and opb;
|
when alu_cmd_sub_c => alu_res <= sub_res;
|
when alu_cmd_sub_c => alu_res <= sub_res;
|
when alu_cmd_add_c => alu_res <= add_res;
|
when alu_cmd_add_c => alu_res <= add_res;
|
when alu_cmd_shift_c => alu_res <= shift_sreg;
|
when alu_cmd_shift_c => alu_res <= shifter.sreg;
|
when alu_cmd_slt_c => alu_res <= (others => '0'); alu_res(0) <= cmp_less;
|
when alu_cmd_slt_c => alu_res <= (others => '0'); alu_res(0) <= cmp_less;
|
when others => alu_res <= (others => '0'); -- undefined
|
when others => alu_res <= (others => '0'); -- undefined
|
end case;
|
end case;
|
end process alu_function_mux;
|
end process alu_function_mux;
|
|
|
|
|
-- ALU Result -----------------------------------------------------------------------------
|
-- ALU Result -----------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
wait_o <= shift_run or cp_run; -- wait until iterative units have completed
|
wait_o <= shifter.run or cp_run; -- wait until iterative units have completed
|
res_o <= (cp0_data_i or cp1_data_i) when (cp_rb_ff1 = '1') else alu_res; -- FIXME
|
res_o <= (cp0_data_i or cp1_data_i) when (cp_rb_ff1 = '1') else alu_res; -- FIXME
|
|
|
|
|
end neorv32_cpu_cpu_rtl;
|
end neorv32_cpu_cpu_rtl;
|
|
|
No newline at end of file
|
No newline at end of file
|