OpenCores
URL https://opencores.org/ocsvn/lxp32/lxp32/trunk

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_alu.vhd] - Rev 2

Go to most recent revision | Compare with Previous | Blame | View Log

---------------------------------------------------------------------
-- Arithmetic logic unit
--
-- Part of the LXP32 CPU
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Performs arithmetic and logic operations.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity lxp32_alu is
	generic(
		DIVIDER_EN: boolean;
		MUL_ARCH: string
	);
	port(
		clk_i: in std_logic;
		rst_i: in std_logic;
 
		valid_i: in std_logic;
 
		cmd_signed_i: in std_logic;
		cmd_addsub_i: in std_logic;
		cmd_mul_i: in std_logic;
		cmd_div_i: in std_logic;
		cmd_div_mod_i: in std_logic;
		cmd_cmp_i: in std_logic;
		cmd_negate_op2_i: in std_logic;
		cmd_and_i: in std_logic;
		cmd_or_i: in std_logic;
		cmd_xor_i: in std_logic;
		cmd_shift_i: in std_logic;
		cmd_shift_right_i: in std_logic;
 
		op1_i: in std_logic_vector(31 downto 0);
		op2_i: in std_logic_vector(31 downto 0);
 
		result_o: out std_logic_vector(31 downto 0);
 
		cmp_eq_o: out std_logic;
		cmp_ug_o: out std_logic;
		cmp_sg_o: out std_logic;
 
		we_o: out std_logic;
		busy_o: out std_logic
	);
end entity;
 
architecture rtl of lxp32_alu is
 
signal addend1: unsigned(31 downto 0);
signal addend2: unsigned(31 downto 0);
signal adder_result: unsigned(32 downto 0);
signal adder_we: std_logic;
 
signal cmp_eq: std_logic;
signal cmp_carry: std_logic;
signal cmp_s1: std_logic;
signal cmp_s2: std_logic;
 
signal and_result: std_logic_vector(31 downto 0);
signal and_we: std_logic;
signal or_result: std_logic_vector(31 downto 0);
signal or_we: std_logic;
signal xor_result: std_logic_vector(31 downto 0);
signal xor_we: std_logic;
 
signal mul_result: std_logic_vector(31 downto 0);
signal mul_ce: std_logic;
signal mul_we: std_logic;
 
signal div_quotient: std_logic_vector(31 downto 0);
signal div_remainder: std_logic_vector(31 downto 0);
signal div_ce: std_logic;
signal div_we: std_logic;
signal div_select_remainder: std_logic;
 
signal shift_result: std_logic_vector(31 downto 0);
signal shift_ce: std_logic;
signal shift_we: std_logic;
 
signal result_mux: std_logic_vector(31 downto 0);
signal result_we: std_logic;
 
signal busy: std_logic:='0';
 
begin
 
assert MUL_ARCH="dsp" or MUL_ARCH="seq" or MUL_ARCH="opt"
	report "Invalid MUL_ARCH generic value: dsp, opt or seq expected"
	severity failure;
 
-- Add/subtract
 
addend1<=unsigned(op1_i);
addend2<=unsigned(op2_i) when cmd_negate_op2_i='0' else not unsigned(op2_i);
adder_result<=("0"&addend1)+("0"&addend2)+(to_unsigned(0,adder_result'length-1)&cmd_negate_op2_i);
adder_we<=cmd_addsub_i and valid_i;
 
-- Comparator (needs cmd_negate_op2_i to work correctly)
 
process (clk_i) is
begin
	if rising_edge(clk_i) then
		if valid_i='1' and cmd_cmp_i='1' then
			if op1_i=op2_i then
				cmp_eq<='1';
			else
				cmp_eq<='0';
			end if;
 
			cmp_carry<=adder_result(adder_result'high);
			cmp_s1<=op1_i(op1_i'high);
			cmp_s2<=op2_i(op2_i'high);
		end if;
	end if;
end process;
 
cmp_eq_o<=cmp_eq;
cmp_ug_o<=cmp_carry and not cmp_eq;
cmp_sg_o<=((cmp_s1 and cmp_s2 and cmp_carry) or
	(not cmp_s1 and not cmp_s2 and cmp_carry) or
	(not cmp_s1 and cmp_s2)) and not cmp_eq;
 
-- Logical functions
 
and_result<=op1_i and op2_i;
and_we<=cmd_and_i and valid_i;
or_result<=op1_i or op2_i;
or_we<=cmd_or_i and valid_i;
xor_result<=op1_i xor op2_i;
xor_we<=cmd_xor_i and valid_i;
 
-- Multiplier
 
mul_ce<=cmd_mul_i and valid_i;
 
gen_mul_dsp: if MUL_ARCH="dsp" generate
	mul_inst: entity work.lxp32_mul_dsp(rtl)
		port map(
			clk_i=>clk_i,
			rst_i=>rst_i,
			ce_i=>mul_ce,
			op1_i=>op1_i,
			op2_i=>op2_i,
			ce_o=>mul_we,
			result_o=>mul_result
		);
end generate;
 
gen_mul_opt: if MUL_ARCH="opt" generate
	mul_inst: entity work.lxp32_mul_opt(rtl)
		port map(
			clk_i=>clk_i,
			rst_i=>rst_i,
			ce_i=>mul_ce,
			op1_i=>op1_i,
			op2_i=>op2_i,
			ce_o=>mul_we,
			result_o=>mul_result
		);
end generate;
 
gen_mul_seq: if MUL_ARCH="seq" generate
	mul_inst: entity work.lxp32_mul_seq(rtl)
		port map(
			clk_i=>clk_i,
			rst_i=>rst_i,
			ce_i=>mul_ce,
			op1_i=>op1_i,
			op2_i=>op2_i,
			ce_o=>mul_we,
			result_o=>mul_result
		);
end generate;
 
-- Divider
 
div_ce<=cmd_div_i and valid_i;
 
gen_divider: if DIVIDER_EN generate
	divider_inst: entity work.lxp32_divider(rtl)
		port map(
			clk_i=>clk_i,
			rst_i=>rst_i,
			ce_i=>div_ce,
			op1_i=>op1_i,
			op2_i=>op2_i,
			signed_i=>cmd_signed_i,
			ce_o=>div_we,
			quotient_o=>div_quotient,
			remainder_o=>div_remainder
		);
end generate;
 
gen_no_divider: if not DIVIDER_EN generate
	div_we<=div_ce;
	div_quotient<=(others=>'0');
	div_remainder<=(others=>'0');
end generate;
 
process (clk_i) is
begin
	if rising_edge(clk_i) then
		if div_ce='1' then
			div_select_remainder<=cmd_div_mod_i;
		end if;
	end if;
end process;
 
-- Shifter
 
shift_ce<=cmd_shift_i and valid_i;
 
shifter_inst: entity work.lxp32_shifter(rtl)
	port map(
		clk_i=>clk_i,
		rst_i=>rst_i,
		ce_i=>shift_ce,
		d_i=>op1_i,
		s_i=>op2_i(4 downto 0),
		right_i=>cmd_shift_right_i,
		sig_i=>cmd_signed_i,
		ce_o=>shift_we,
		d_o=>shift_result
	);
 
-- Result multiplexer
 
result_mux_gen: for i in result_mux'range generate
	result_mux(i)<=(adder_result(i) and adder_we) or
		(and_result(i) and and_we) or
		(or_result(i) and or_we) or
		(xor_result(i) and xor_we) or
		(mul_result(i) and mul_we) or
		(div_quotient(i) and div_we and not div_select_remainder) or
		(div_remainder(i) and div_we and div_select_remainder) or
		(shift_result(i) and shift_we);
end generate;
 
result_o<=result_mux;
 
result_we<=adder_we or and_we or or_we or xor_we or mul_we or div_we or shift_we;
we_o<=result_we;
 
-- Pipeline control
 
process (clk_i) is
begin
	if rising_edge(clk_i) then
		if rst_i='1' then
			busy<='0';
		else
			if shift_ce='1' or mul_ce='1' or div_ce='1' then
				busy<='1';
			end if;
			if result_we='1' then
				busy<='0';
			end if;
		end if;
	end if;
end process;
 
busy_o<=busy;
 
end architecture;
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.