URL
https://opencores.org/ocsvn/mlite/mlite/trunk
Subversion Repositories mlite
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 127 to Rev 128
- ↔ Reverse comparison
Rev 127 → Rev 128
/trunk/vhdl/pc_next.vhd
26,9 → 26,7
end; --pc_next |
|
architecture logic of pc_next is |
-- type pc_source_type is (from_inc4, from_opcode25_0, from_branch, |
-- from_lbranch); |
signal pc_reg : std_logic_vector(31 downto 2); --:= ZERO(31 downto 2); |
signal pc_reg : std_logic_vector(31 downto 2); |
begin |
|
pc_next: process(clk, reset_in, pc_new, take_branch, pause_in, |
38,16 → 36,18
pc_inc := bv_increment(pc_reg); --pc_reg+1 |
|
case pc_source is |
when from_inc4 => |
when FROM_INC4 => |
pc_next := pc_inc; |
when from_opcode25_0 => |
when FROM_OPCODE25_0 => |
pc_next := pc_reg(31 downto 28) & opcode25_0; |
when others => --from_branch | from_lbranch => |
when FROM_BRANCH | FROM_LBRANCH => |
if take_branch = '1' then |
pc_next := pc_new; |
else |
pc_next := pc_inc; |
end if; |
when others => |
pc_next := pc_inc; |
end case; |
|
if pause_in = '1' then |
/trunk/vhdl/mem_ctrl.vhd
44,7 → 44,7
|
architecture logic of mem_ctrl is |
--"00" = big_endian; "11" = little_endian |
constant little_endian : std_logic_vector(1 downto 0) := "00"; |
constant ENDIAN_MODE : std_logic_vector(1 downto 0) := "00"; |
signal opcode_reg : std_logic_vector(31 downto 0); |
signal next_opcode_reg : std_logic_vector(31 downto 0); |
|
92,8 → 92,14
|
GEN_REGS2: process(clk, address_data, write_next_sig, byte_sel_next_sig) |
begin |
if rising_edge(clk) then |
if reset_in = '1' then |
if ACCURATE_TIMING then |
address_reg <= ZERO; |
write_reg <= '0'; |
byte_sel_reg <= "0000"; |
end if; |
elsif rising_edge(clk) then |
if ACCURATE_TIMING then |
address_reg <= address_data; |
write_reg <= write_next_sig; |
byte_sel_reg <= byte_sel_next_sig; |
132,10 → 138,11
mem_data_w_v := ZERO; |
|
case mem_source is |
when mem_read32 => |
when MEM_READ32 => |
data := mem_data_r; |
when mem_read16 | mem_read16s => |
if address_reg(1) = little_endian(1) then |
|
when MEM_READ16 | MEM_READ16S => |
if address_reg(1) = ENDIAN_MODE(1) then |
data(15 downto 0) := mem_data_r(31 downto 16); |
else |
data(15 downto 0) := mem_data_r(15 downto 0); |
145,8 → 152,9
else |
data(31 downto 16) := ONES(31 downto 16); |
end if; |
when mem_read8 | mem_read8s => |
bits := address_reg(1 downto 0) xor little_endian; |
|
when MEM_READ8 | MEM_READ8s => |
bits := address_reg(1 downto 0) xor ENDIAN_MODE; |
case bits is |
when "00" => data(7 downto 0) := mem_data_r(31 downto 24); |
when "01" => data(7 downto 0) := mem_data_r(23 downto 16); |
153,28 → 161,31
when "10" => data(7 downto 0) := mem_data_r(15 downto 8); |
when others => data(7 downto 0) := mem_data_r(7 downto 0); |
end case; |
if mem_source = mem_read8 or data(7) = '0' then |
if mem_source = MEM_READ8 or data(7) = '0' then |
data(31 downto 8) := ZERO(31 downto 8); |
else |
data(31 downto 8) := ONES(31 downto 8); |
end if; |
when mem_write32 => |
|
when MEM_WRITE32 => |
write_next := '1'; |
mem_data_w_v := data_write; |
byte_sel_next := "1111"; |
when mem_write16 => |
|
when MEM_WRITE16 => |
write_next := '1'; |
mem_data_w_v := data_write(15 downto 0) & data_write(15 downto 0); |
if address_data(1) = little_endian(1) then |
if address_data(1) = ENDIAN_MODE(1) then |
byte_sel_next := "1100"; |
else |
byte_sel_next := "0011"; |
end if; |
when mem_write8 => |
|
when MEM_WRITE8 => |
write_next := '1'; |
mem_data_w_v := data_write(7 downto 0) & data_write(7 downto 0) & |
data_write(7 downto 0) & data_write(7 downto 0); |
bits := address_data(1 downto 0) xor little_endian; |
bits := address_data(1 downto 0) xor ENDIAN_MODE; |
case bits is |
when "00" => |
byte_sel_next := "1000"; |
185,8 → 196,10
when others => |
byte_sel_next := "0001"; |
end case; |
|
when others => |
end case; |
|
byte_sel_next_sig <= byte_sel_next; |
write_next_sig <= write_next; |
|
207,6 → 220,7
mem_state_next := STATE_ADDR; |
end if; |
end if; |
|
when STATE_ADDR => --address lines pre-hold |
address := address_reg; |
write_line := write_reg; |
223,6 → 237,7
mem_state_next := STATE_FETCH; --2 cycle access |
end if; |
end if; |
|
when STATE_WRITE => |
pause := '1'; |
address := address_reg; |
231,6 → 246,7
if pause_in = '0' then |
mem_state_next := STATE_PAUSE; |
end if; |
|
when OTHERS => --STATE_PAUSE address lines post-hold |
address := address_reg; |
write_line := write_reg; |
/trunk/vhdl/tbench.vhd
39,6 → 39,7
begin --architecture |
clk <= not clk after 50 ns; |
reset <= '0' after 500 ns; |
uart_read <= '0'; |
|
--Uncomment the line below to test interrupts |
-- interrupt <= '1' after 20 us when interrupt = '0' else '0' after 400 ns; |
/trunk/vhdl/shifter.vhd
32,7 → 32,7
signal fills : std_logic_vector(31 downto 16); |
|
begin |
fills <= "1111111111111111" when shift_func = shift_right_signed and value(31) = '1' else |
fills <= "1111111111111111" when shift_func = SHIFT_RIGHT_SIGNED and value(31) = '1' else |
"0000000000000000"; |
shift1L <= value(30 downto 0) & '0' when shift_amount(0) = '1' else value; |
shift2L <= shift1L(29 downto 0) & "00" when shift_amount(1) = '1' else shift1L; |
50,8 → 50,8
GENERIC_SHIFTER: if shifter_type = "GENERIC" generate |
-- synthesis translate_on |
|
c_shift <= shift16L when shift_func = shift_left_unsigned else |
shift16R when shift_func = shift_right_unsigned or shift_func = shift_right_signed else |
c_shift <= shift16L when shift_func = SHIFT_LEFT_UNSIGNED else |
shift16R when shift_func = SHIFT_RIGHT_UNSIGNED or shift_func = SHIFT_RIGHT_SIGNED else |
ZERO; |
|
-- synthesis translate_off |
62,10 → 62,10
|
AREA_OPTIMIZED_SHIFTER: if shifter_type = "AREA_OPTIMIZED" generate |
|
c_shift <= shift16L when shift_func = shift_left_unsigned else (others => 'Z'); |
c_shift <= shift16R when shift_func = shift_right_unsigned or |
shift_func = shift_right_signed else (others => 'Z'); |
c_shift <= ZERO when shift_func = shift_nothing else (others => 'Z'); |
c_shift <= shift16L when shift_func = SHIFT_LEFT_UNSIGNED else (others => 'Z'); |
c_shift <= shift16R when shift_func = SHIFT_RIGHT_UNSIGNED or |
shift_func = SHIFT_RIGHT_SIGNED else (others => 'Z'); |
c_shift <= ZERO when shift_func = SHIFT_NOTHING else (others => 'Z'); |
|
end generate; |
|
/trunk/vhdl/pipeline.vhd
64,9 → 64,9
variable pause_mult_clock : std_logic; |
variable freeze_pipeline : std_logic; |
begin |
if (pc_source /= from_inc4 and pc_source /= from_opcode25_0) or |
mem_source /= mem_fetch or |
(mult_func = mult_read_lo or mult_func = mult_read_hi) then |
if (pc_source /= FROM_INC4 and pc_source /= FROM_OPCODE25_0) or |
mem_source /= MEM_FETCH or |
(mult_func = MULT_READ_LO or mult_func = MULT_READ_HI) then |
pause_mult_clock := '1'; |
else |
pause_mult_clock := '0'; |
76,7 → 76,7
pause_pipeline <= pause_mult_clock and pause_enable_reg; |
rd_indexD <= rd_index_reg; |
|
if c_source_reg = c_from_alu then |
if c_source_reg = C_FROM_ALU then |
reg_dest_delay <= c_bus; --delayed by 1 clock cycle via a_busD & b_busD |
else |
reg_dest_delay <= reg_dest_reg; --need to delay 1 clock cycle from reg_dest |
84,12 → 84,19
reg_destD <= reg_dest_delay; |
|
if reset = '1' then |
pause_enable_reg <= '1'; |
a_busD <= ZERO; |
b_busD <= ZERO; |
alu_funcD <= ALU_NOTHING; |
shift_funcD <= SHIFT_NOTHING; |
mult_funcD <= MULT_NOTHING; |
reg_dest_reg <= ZERO; |
c_source_reg <= "000"; |
rd_index_reg <= "000000"; |
pause_enable_reg <= '0'; |
elsif rising_edge(clk) then |
if freeze_pipeline = '0' then |
if (rs_index = "000000" or rs_index /= rd_index_reg) or |
(a_source /= a_from_reg_source or pause_enable_reg = '0') then |
(a_source /= A_FROM_REG_SOURCE or pause_enable_reg = '0') then |
a_busD <= a_bus; |
else |
a_busD <= reg_dest_delay; --rs from previous operation (bypass stage) |
96,7 → 103,7
end if; |
|
if (rt_index = "000000" or rt_index /= rd_index_reg) or |
(b_source /= b_from_reg_target or pause_enable_reg = '0') then |
(b_source /= B_FROM_REG_TARGET or pause_enable_reg = '0') then |
b_busD <= b_bus; |
else |
b_busD <= reg_dest_delay; --rt from previous operation |
/trunk/vhdl/reg_bank.vhd
44,9 → 44,6
signal addr_a1, addr_a2, addr_b : std_logic_vector(4 downto 0); |
signal data_out1, data_out2 : std_logic_vector(31 downto 0); |
signal write_enable : std_logic; |
-- signal sig_false : std_logic := '0'; |
-- signal sig_true : std_logic := '1'; |
-- signal zero_sig : std_logic_vector(15 downto 0) := ZERO(15 downto 0); |
|
begin |
|
/trunk/vhdl/mlite_pack.vhd
21,97 → 21,82
constant HIGH_Z : std_logic_vector(31 downto 0) := |
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; |
|
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract, |
-- alu_less_than, alu_less_than_signed, |
-- alu_or, alu_and, alu_xor, alu_nor); |
subtype alu_function_type is std_logic_vector(3 downto 0); |
constant alu_nothing : alu_function_type := "0000"; |
constant alu_add : alu_function_type := "0001"; |
constant alu_subtract : alu_function_type := "0010"; |
constant alu_less_than : alu_function_type := "0011"; |
constant alu_less_than_signed : alu_function_type := "0100"; |
constant alu_or : alu_function_type := "0101"; |
constant alu_and : alu_function_type := "0110"; |
constant alu_xor : alu_function_type := "0111"; |
constant alu_nor : alu_function_type := "1000"; |
constant ALU_NOTHING : alu_function_type := "0000"; |
constant ALU_ADD : alu_function_type := "0001"; |
constant ALU_SUBTRACT : alu_function_type := "0010"; |
constant ALU_LESS_THAN : alu_function_type := "0011"; |
constant ALU_LESS_THAN_SIGNED : alu_function_type := "0100"; |
constant ALU_OR : alu_function_type := "0101"; |
constant ALU_AND : alu_function_type := "0110"; |
constant ALU_XOR : alu_function_type := "0111"; |
constant ALU_NOR : alu_function_type := "1000"; |
|
-- type shift_function_type is ( |
-- shift_nothing, shift_left_unsigned, |
-- shift_right_signed, do_right_unsigned); |
subtype shift_function_type is std_logic_vector(1 downto 0); |
constant shift_nothing : shift_function_type := "00"; |
constant shift_left_unsigned : shift_function_type := "01"; |
constant shift_right_signed : shift_function_type := "11"; |
constant shift_right_unsigned : shift_function_type := "10"; |
constant SHIFT_NOTHING : shift_function_type := "00"; |
constant SHIFT_LEFT_UNSIGNED : shift_function_type := "01"; |
constant SHIFT_RIGHT_SIGNED : shift_function_type := "11"; |
constant SHIFT_RIGHT_UNSIGNED : shift_function_type := "10"; |
|
-- type mult_function_type is ( |
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo, |
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide); |
subtype mult_function_type is std_logic_vector(3 downto 0); |
constant mult_nothing : mult_function_type := "0000"; |
constant mult_read_lo : mult_function_type := "0001"; |
constant mult_read_hi : mult_function_type := "0010"; |
constant mult_write_lo : mult_function_type := "0011"; |
constant mult_write_hi : mult_function_type := "0100"; |
constant mult_mult : mult_function_type := "0101"; |
constant mult_signed_mult : mult_function_type := "0110"; |
constant mult_divide : mult_function_type := "0111"; |
constant mult_signed_divide : mult_function_type := "1000"; |
constant MULT_NOTHING : mult_function_type := "0000"; |
constant MULT_READ_LO : mult_function_type := "0001"; |
constant MULT_READ_HI : mult_function_type := "0010"; |
constant MULT_WRITE_LO : mult_function_type := "0011"; |
constant MULT_WRITE_HI : mult_function_type := "0100"; |
constant MULT_MULT : mult_function_type := "0101"; |
constant MULT_SIGNED_MULT : mult_function_type := "0110"; |
constant MULT_DIVIDE : mult_function_type := "0111"; |
constant MULT_SIGNED_DIVIDE : mult_function_type := "1000"; |
|
-- type a_source_type is (from_reg_source, from_imm10_6); |
subtype a_source_type is std_logic_vector(1 downto 0); |
constant a_from_reg_source : a_source_type := "00"; |
constant a_from_imm10_6 : a_source_type := "01"; |
constant a_from_pc : a_source_type := "10"; |
constant A_FROM_REG_SOURCE : a_source_type := "00"; |
constant A_FROM_IMM10_6 : a_source_type := "01"; |
constant A_FROM_PC : a_source_type := "10"; |
|
-- type b_source_type is (from_reg_target, from_imm, from_signed_imm); |
subtype b_source_type is std_logic_vector(1 downto 0); |
constant b_from_reg_target : b_source_type := "00"; |
constant b_from_imm : b_source_type := "01"; |
constant b_from_signed_imm : b_source_type := "10"; |
constant b_from_immX4 : b_source_type := "11"; |
constant B_FROM_REG_TARGET : b_source_type := "00"; |
constant B_FROM_IMM : b_source_type := "01"; |
constant B_FROM_SIGNED_IMM : b_source_type := "10"; |
constant B_FROM_IMMX4 : b_source_type := "11"; |
|
-- type c_source_type is (from_null, from_alu, from_shift, |
-- from_mult, from_memory, from_pc, from_imm_shift16, |
-- from_reg_source_nez, from_reg_source_eqz); |
subtype c_source_type is std_logic_vector(2 downto 0); |
constant c_from_null : c_source_type := "000"; |
constant c_from_alu : c_source_type := "001"; |
constant c_from_shift : c_source_type := "001"; --same as alu |
constant c_from_mult : c_source_type := "001"; --same as alu |
constant c_from_memory : c_source_type := "010"; |
constant c_from_pc : c_source_type := "011"; |
constant c_from_pc_plus4 : c_source_type := "100"; |
constant c_from_imm_shift16: c_source_type := "101"; |
constant c_from_reg_sourcen: c_source_type := "110"; |
constant C_FROM_NULL : c_source_type := "000"; |
constant C_FROM_ALU : c_source_type := "001"; |
constant C_FROM_SHIFT : c_source_type := "001"; --same as alu |
constant C_FROM_MULT : c_source_type := "001"; --same as alu |
constant C_FROM_MEMORY : c_source_type := "010"; |
constant C_FROM_PC : c_source_type := "011"; |
constant C_FROM_PC_PLUS4 : c_source_type := "100"; |
constant C_FROM_IMM_SHIFT16: c_source_type := "101"; |
constant C_FROM_REG_SOURCEN: c_source_type := "110"; |
|
-- type pc_source_type is (from_inc4, from_opcode25_0, from_branch, from_lbranch); |
subtype pc_source_type is std_logic_vector(1 downto 0); |
constant from_inc4 : pc_source_type := "00"; |
constant from_opcode25_0 : pc_source_type := "01"; |
constant from_branch : pc_source_type := "10"; |
constant from_lbranch : pc_source_type := "11"; |
constant FROM_INC4 : pc_source_type := "00"; |
constant FROM_OPCODE25_0 : pc_source_type := "01"; |
constant FROM_BRANCH : pc_source_type := "10"; |
constant FROM_LBRANCH : pc_source_type := "11"; |
|
subtype branch_function_type is std_logic_vector(2 downto 0); |
constant branch_ltz : branch_function_type := "000"; |
constant branch_lez : branch_function_type := "001"; |
constant branch_eq : branch_function_type := "010"; |
constant branch_ne : branch_function_type := "011"; |
constant branch_gez : branch_function_type := "100"; |
constant branch_gtz : branch_function_type := "101"; |
constant branch_yes : branch_function_type := "110"; |
constant BRANCH_LTZ : branch_function_type := "000"; |
constant BRANCH_LEZ : branch_function_type := "001"; |
constant BRANCH_EQ : branch_function_type := "010"; |
constant BRANCH_NE : branch_function_type := "011"; |
constant BRANCH_GEZ : branch_function_type := "100"; |
constant BRANCH_GTZ : branch_function_type := "101"; |
constant BRANCH_YES : branch_function_type := "110"; |
|
-- mode(32=1,16=2,8=3), signed, write |
subtype mem_source_type is std_logic_vector(3 downto 0); |
constant mem_fetch : mem_source_type := "0000"; |
constant mem_read32 : mem_source_type := "0100"; |
constant mem_write32 : mem_source_type := "0101"; |
constant mem_read16 : mem_source_type := "1000"; |
constant mem_read16s : mem_source_type := "1010"; |
constant mem_write16 : mem_source_type := "1001"; |
constant mem_read8 : mem_source_type := "1100"; |
constant mem_read8s : mem_source_type := "1110"; |
constant mem_write8 : mem_source_type := "1101"; |
constant MEM_FETCH : mem_source_type := "0000"; |
constant MEM_READ32 : mem_source_type := "0100"; |
constant MEM_WRITE32 : mem_source_type := "0101"; |
constant MEM_READ16 : mem_source_type := "1000"; |
constant MEM_READ16s : mem_source_type := "1010"; |
constant MEM_WRITE16 : mem_source_type := "1001"; |
constant MEM_READ8 : mem_source_type := "1100"; |
constant MEM_READ8s : mem_source_type := "1110"; |
constant MEM_WRITE8 : mem_source_type := "1101"; |
|
function bv_to_integer(bv: in std_logic_vector) return integer; |
function bv_adder(a : in std_logic_vector(32 downto 0); |
339,6 → 324,7
mult_type : string := "GENERIC"); |
port ( |
clk : in std_logic; |
reset_in : in std_logic; |
a, b : in std_logic_vector(31 downto 0); |
mult_func : in mult_function_type; |
c_mult : out std_logic_vector(31 downto 0); |
/trunk/vhdl/ram.vhd
58,6 → 58,7
file load_file : text is in "code.txt"; |
variable hex_file_line : line; |
begin |
|
--load in the ram executable image |
if index = 0 then |
while not endfile(load_file) loop |
/trunk/vhdl/control.vhd
43,22 → 43,6
end; --entity control |
|
architecture logic of control is |
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract, |
-- alu_less_than, alu_less_than_signed, |
-- alu_or, alu_and, alu_xor, alu_nor); |
-- type shift_function_type is ( |
-- shift_nothing, shift_left_unsigned, |
-- shift_right_signed, shift_right_unsigned); |
-- type mult_function_type is ( |
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo, |
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide); |
-- type a_source_type is (from_reg_source, from_imm10_6); |
-- type b_source_type is (from_reg_target, from_imm, from_signed_imm); |
-- type c_source_type is (from_null, from_alu, from_shift, |
-- from_mult, from_memory, from_pc, from_imm_shift16, |
-- from_reg_source_nez, from_reg_source_eqz); |
-- type pc_source_type is (from_inc4, from_inc8, from_reg_source, |
-- from_opcode25_0, from_branch, from_lbranch); |
begin |
|
control_proc: process(opcode, intr_signal) |
76,15 → 60,15
variable branch_function: branch_function_type; |
variable mem_source : mem_source_type; |
begin |
alu_function := alu_nothing; |
shift_function := shift_nothing; |
mult_function := mult_nothing; |
a_source := a_from_reg_source; |
b_source := b_from_reg_target; |
c_source := c_from_null; |
pc_source := from_inc4; |
branch_function := branch_eq; |
mem_source := mem_fetch; |
alu_function := ALU_NOTHING; |
shift_function := SHIFT_NOTHING; |
mult_function := MULT_NOTHING; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_REG_TARGET; |
c_source := C_FROM_NULL; |
pc_source := FROM_INC4; |
branch_function := BRANCH_EQ; |
mem_source := MEM_FETCH; |
op := opcode(31 downto 26); |
rs := '0' & opcode(25 downto 21); |
rt := '0' & opcode(20 downto 16); |
97,94 → 81,124
when "000000" => --SPECIAL |
case func is |
when "000000" => --SLL r[rd]=r[rt]<<re; |
a_source := a_from_imm10_6; |
c_source := c_from_shift; |
shift_function := shift_left_unsigned; |
a_source := A_FROM_IMM10_6; |
c_source := C_FROM_SHIFT; |
shift_function := SHIFT_LEFT_UNSIGNED; |
|
when "000010" => --SRL r[rd]=u[rt]>>re; |
a_source := a_from_imm10_6; |
c_source := c_from_shift; |
shift_function := shift_right_unsigned; |
a_source := A_FROM_IMM10_6; |
c_source := C_FROM_shift; |
shift_function := SHIFT_RIGHT_UNSIGNED; |
|
when "000011" => --SRA r[rd]=r[rt]>>re; |
a_source := a_from_imm10_6; |
c_source := c_from_shift; |
shift_function := shift_right_signed; |
a_source := A_FROM_IMM10_6; |
c_source := C_FROM_SHIFT; |
shift_function := SHIFT_RIGHT_SIGNED; |
|
when "000100" => --SLLV r[rd]=r[rt]<<r[rs]; |
c_source := c_from_shift; |
shift_function := shift_left_unsigned; |
c_source := C_FROM_SHIFT; |
shift_function := SHIFT_LEFT_UNSIGNED; |
|
when "000110" => --SRLV r[rd]=u[rt]>>r[rs]; |
c_source := c_from_shift; |
shift_function := shift_right_unsigned; |
c_source := C_FROM_SHIFT; |
shift_function := SHIFT_RIGHT_UNSIGNED; |
|
when "000111" => --SRAV r[rd]=r[rt]>>r[rs]; |
c_source := c_from_shift; |
shift_function := shift_right_signed; |
c_source := C_FROM_SHIFT; |
shift_function := SHIFT_RIGHT_SIGNED; |
|
when "001000" => --JR s->pc_next=r[rs]; |
pc_source := from_branch; |
alu_function := alu_add; |
branch_function := branch_yes; |
pc_source := FROM_BRANCH; |
alu_function := ALU_ADD; |
branch_function := BRANCH_YES; |
|
when "001001" => --JALR r[rd]=s->pc_next; s->pc_next=r[rs]; |
c_source := c_from_pc_plus4; |
pc_source := from_branch; |
alu_function := alu_add; |
branch_function := branch_yes; |
c_source := C_FROM_PC_PLUS4; |
pc_source := FROM_BRANCH; |
alu_function := ALU_ADD; |
branch_function := BRANCH_YES; |
|
when "001010" => --MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/ |
-- c_source := c_from_reg_source_eqz; |
-- c_source := C_FROM_REG_SOURCE_EQZ; |
|
when "001011" => --MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/ |
-- c_source := from_reg_source_nez; |
-- c_source := FROM_REG_SOURCE_NEZ; |
|
when "001100" => --SYSCALL |
-- if(r[4]==0) printf("0x%8.8lx ",r[5]); |
|
when "001101" => --BREAK s->wakeup=1; |
when "001111" => --SYNC s->wakeup=1; |
when "010000" => --MFHI r[rd]=s->hi; |
c_source := c_from_mult; |
mult_function := mult_read_hi; |
c_source := C_FROM_MULT; |
mult_function := MULT_READ_HI; |
|
when "010001" => --FTHI s->hi=r[rs]; |
mult_function := mult_write_hi; |
mult_function := MULT_WRITE_HI; |
|
when "010010" => --MFLO r[rd]=s->lo; |
c_source := c_from_mult; |
mult_function := mult_read_lo; |
c_source := C_FROM_MULT; |
mult_function := MULT_READ_LO; |
|
when "010011" => --MTLO s->lo=r[rs]; |
mult_function := mult_write_lo; |
mult_function := MULT_WRITE_LO; |
|
when "011000" => --MULT s->lo=r[rs]*r[rt]; s->hi=0; |
mult_function := mult_signed_mult; |
mult_function := MULT_SIGNED_MULT; |
|
when "011001" => --MULTU s->lo=r[rs]*r[rt]; s->hi=0; |
mult_function := mult_mult; |
mult_function := MULT_MULT; |
|
when "011010" => --DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; |
mult_function := mult_signed_divide; |
mult_function := MULT_SIGNED_DIVIDE; |
|
when "011011" => --DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; |
mult_function := mult_divide; |
mult_function := MULT_DIVIDE; |
|
when "100000" => --ADD r[rd]=r[rs]+r[rt]; |
c_source := c_from_alu; |
alu_function := alu_add; |
c_source := C_FROM_ALU; |
alu_function := ALU_ADD; |
|
when "100001" => --ADDU r[rd]=r[rs]+r[rt]; |
c_source := c_from_alu; |
alu_function := alu_add; |
c_source := C_FROM_ALU; |
alu_function := ALU_ADD; |
|
when "100010" => --SUB r[rd]=r[rs]-r[rt]; |
c_source := c_from_alu; |
alu_function := alu_subtract; |
c_source := C_FROM_ALU; |
alu_function := ALU_SUBTRACT; |
|
when "100011" => --SUBU r[rd]=r[rs]-r[rt]; |
c_source := c_from_alu; |
alu_function := alu_subtract; |
c_source := C_FROM_ALU; |
alu_function := ALU_SUBTRACT; |
|
when "100100" => --AND r[rd]=r[rs]&r[rt]; |
c_source := c_from_alu; |
alu_function := alu_and; |
c_source := C_FROM_ALU; |
alu_function := ALU_AND; |
|
when "100101" => --OR r[rd]=r[rs]|r[rt]; |
c_source := c_from_alu; |
alu_function := alu_or; |
c_source := C_FROM_ALU; |
alu_function := ALU_OR; |
|
when "100110" => --XOR r[rd]=r[rs]^r[rt]; |
c_source := c_from_alu; |
alu_function := alu_xor; |
c_source := C_FROM_ALU; |
alu_function := ALU_XOR; |
|
when "100111" => --NOR r[rd]=~(r[rs]|r[rt]); |
c_source := c_from_alu; |
alu_function := alu_nor; |
c_source := C_FROM_ALU; |
alu_function := ALU_NOR; |
|
when "101010" => --SLT r[rd]=r[rs]<r[rt]; |
c_source := c_from_alu; |
alu_function := alu_less_than_signed; |
c_source := C_FROM_ALU; |
alu_function := ALU_LESS_THAN_SIGNED; |
|
when "101011" => --SLTU r[rd]=u[rs]<u[rt]; |
c_source := c_from_alu; |
alu_function := alu_less_than; |
c_source := C_FROM_ALU; |
alu_function := ALU_LESS_THAN; |
|
when "101101" => --DADDU r[rd]=r[rs]+u[rt]; |
c_source := c_from_alu; |
alu_function := alu_add; |
c_source := C_FROM_ALU; |
alu_function := ALU_ADD; |
|
when "110001" => --TGEU |
when "110010" => --TLT |
when "110011" => --TLTU |
192,113 → 206,138
when "110110" => --TNE |
when others => |
end case; |
|
when "000001" => --REGIMM |
rt := "000000"; |
rd := "011111"; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_gtz; |
a_source := A_FROM_PC; |
b_source := B_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_BRANCH; |
branch_function := BRANCH_GTZ; |
--if(test) pc=pc+imm*4 |
|
case rtx is |
when "10000" => --BLTZAL r[31]=s->pc_next; branch=r[rs]<0; |
c_source := c_from_pc_plus4; |
branch_function := branch_ltz; |
c_source := C_FROM_PC_PLUS4; |
branch_function := BRANCH_LTZ; |
|
when "00000" => --BLTZ branch=r[rs]<0; |
branch_function := branch_ltz; |
branch_function := BRANCH_LTZ; |
|
when "10001" => --BGEZAL r[31]=s->pc_next; branch=r[rs]>=0; |
c_source := c_from_pc_plus4; |
branch_function := branch_gez; |
c_source := C_FROM_PC_PLUS4; |
branch_function := BRANCH_GEZ; |
|
when "00001" => --BGEZ branch=r[rs]>=0; |
branch_function := branch_gez; |
branch_function := BRANCH_GEZ; |
|
when "10010" => --BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0; |
c_source := c_from_pc_plus4; |
pc_source := from_lbranch; |
branch_function := branch_ltz; |
c_source := C_FROM_PC_PLUS4; |
pc_source := FROM_LBRANCH; |
branch_function := BRANCH_LTZ; |
|
when "00010" => --BLTZL lbranch=r[rs]<0; |
pc_source := from_lbranch; |
branch_function := branch_ltz; |
pc_source := FROM_LBRANCH; |
branch_function := BRANCH_LTZ; |
|
when "10011" => --BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0; |
c_source := c_from_pc_plus4; |
pc_source := from_lbranch; |
branch_function := branch_gez; |
c_source := C_FROM_PC_PLUS4; |
pc_source := FROM_LBRANCH; |
branch_function := BRANCH_GEZ; |
|
when "00011" => --BGEZL lbranch=r[rs]>=0; |
pc_source := from_lbranch; |
branch_function := branch_gez; |
pc_source := FROM_LBRANCH; |
branch_function := BRANCH_GEZ; |
|
when others => |
end case; |
|
when "000011" => --JAL r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target; |
c_source := c_from_pc_plus4; |
c_source := C_FROM_PC_PLUS4; |
rd := "011111"; |
pc_source := from_opcode25_0; |
pc_source := FROM_OPCODE25_0; |
|
when "000010" => --J s->pc_next=(s->pc&0xf0000000)|target; |
pc_source := from_opcode25_0; |
pc_source := FROM_OPCODE25_0; |
|
when "000100" => --BEQ branch=r[rs]==r[rt]; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_eq; |
a_source := A_FROM_PC; |
b_source := B_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_BRANCH; |
branch_function := BRANCH_EQ; |
|
when "000101" => --BNE branch=r[rs]!=r[rt]; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_ne; |
a_source := A_FROM_PC; |
b_source := B_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_BRANCH; |
branch_function := BRANCH_NE; |
|
when "000110" => --BLEZ branch=r[rs]<=0; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_lez; |
a_source := A_FROM_PC; |
b_source := b_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_BRANCH; |
branch_function := BRANCH_LEZ; |
|
when "000111" => --BGTZ branch=r[rs]>0; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_gtz; |
a_source := A_FROM_PC; |
b_source := B_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_BRANCH; |
branch_function := BRANCH_GTZ; |
|
when "001000" => --ADDI r[rt]=r[rs]+(short)imm; |
b_source := b_from_signed_imm; |
c_source := c_from_alu; |
b_source := B_FROM_SIGNED_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := alu_add; |
alu_function := ALU_ADD; |
|
when "001001" => --ADDIU u[rt]=u[rs]+(short)imm; |
b_source := b_from_signed_imm; |
c_source := c_from_alu; |
b_source := B_FROM_SIGNED_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := alu_add; |
alu_function := ALU_ADD; |
|
when "001010" => --SLTI r[rt]=r[rs]<(short)imm; |
b_source := b_from_signed_imm; |
c_source := c_from_alu; |
b_source := B_FROM_SIGNED_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := alu_less_than_signed; |
alu_function := ALU_LESS_THAN_SIGNED; |
|
when "001011" => --SLTIU u[rt]=u[rs]<(unsigned long)(short)imm; |
b_source := b_from_imm; |
c_source := c_from_alu; |
b_source := B_FROM_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := alu_less_than; |
alu_function := ALU_LESS_THAN; |
|
when "001100" => --ANDI r[rt]=r[rs]&imm; |
b_source := b_from_imm; |
c_source := c_from_alu; |
b_source := B_FROM_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := alu_and; |
alu_function := ALU_AND; |
|
when "001101" => --ORI r[rt]=r[rs]|imm; |
b_source := b_from_imm; |
c_source := c_from_alu; |
b_source := B_FROM_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := alu_or; |
alu_function := ALU_OR; |
|
when "001110" => --XORI r[rt]=r[rs]^imm; |
b_source := b_from_imm; |
c_source := c_from_alu; |
b_source := B_FROM_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := alu_xor; |
alu_function := ALU_XOR; |
|
when "001111" => --LUI r[rt]=(imm<<16); |
c_source := c_from_imm_shift16; |
c_source := C_FROM_IMM_SHIFT16; |
rd := rt; |
|
when "010000" => --COP0 |
alu_function := alu_or; |
c_source := c_from_alu; |
alu_function := ALU_OR; |
c_source := C_FROM_ALU; |
if opcode(23) = '0' then --move from CP0 |
rs := '1' & opcode(15 downto 11); |
rt := "000000"; |
307,96 → 346,111
rs := "000000"; |
rd(5) := '1'; |
end if; |
|
when "010001" => --COP1 |
when "010010" => --COP2 |
when "010011" => --COP3 |
when "010100" => --BEQL lbranch=r[rs]==r[rt]; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_lbranch; |
branch_function := branch_eq; |
a_source := A_FROM_PC; |
b_source := B_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_LBRANCH; |
branch_function := BRANCH_EQ; |
|
when "010101" => --BNEL lbranch=r[rs]!=r[rt]; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_lbranch; |
branch_function := branch_ne; |
a_source := A_FROM_PC; |
b_source := B_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_LBRANCH; |
branch_function := BRANCH_NE; |
|
when "010110" => --BLEZL lbranch=r[rs]<=0; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_lbranch; |
branch_function := branch_lez; |
a_source := A_FROM_PC; |
b_source := B_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_LBRANCH; |
branch_function := BRANCH_LEZ; |
|
when "010111" => --BGTZL lbranch=r[rs]>0; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_lbranch; |
branch_function := branch_gtz; |
a_source := A_FROM_PC; |
b_source := B_FROM_IMMX4; |
alu_function := ALU_ADD; |
pc_source := FROM_LBRANCH; |
branch_function := BRANCH_GTZ; |
|
when "100000" => --LB r[rt]=*(signed char*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read8s; --address=(short)imm+r[rs]; |
c_source := C_FROM_MEMORY; |
mem_source := MEM_READ8S; --address=(short)imm+r[rs]; |
|
when "100001" => --LH r[rt]=*(signed short*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read16s; --address=(short)imm+r[rs]; |
c_source := C_FROM_MEMORY; |
mem_source := MEM_READ16S; --address=(short)imm+r[rs]; |
|
when "100010" => --LWL //Not Implemented |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read32; |
c_source := C_FROM_MEMORY; |
mem_source := MEM_READ32; |
|
when "100011" => --LW r[rt]=*(long*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read32; |
c_source := C_FROM_MEMORY; |
mem_source := MEM_READ32; |
|
when "100100" => --LBU r[rt]=*(unsigned char*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read8; --address=(short)imm+r[rs]; |
c_source := C_FROM_MEMORY; |
mem_source := MEM_READ8; --address=(short)imm+r[rs]; |
|
when "100101" => --LHU r[rt]=*(unsigned short*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read16; --address=(short)imm+r[rs]; |
c_source := C_FROM_MEMORY; |
mem_source := MEM_READ16; --address=(short)imm+r[rs]; |
|
when "100110" => --LWR //Not Implemented |
when "101000" => --SB *(char*)ptr=(char)r[rt]; |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
mem_source := mem_write8; --address=(short)imm+r[rs]; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
mem_source := MEM_WRITE8; --address=(short)imm+r[rs]; |
|
when "101001" => --SH *(short*)ptr=(short)r[rt]; |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
mem_source := mem_write16; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
mem_source := MEM_WRITE16; |
|
when "101010" => --SWL //Not Implemented |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
mem_source := mem_write32; --address=(short)imm+r[rs]; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
mem_source := MEM_WRITE32; --address=(short)imm+r[rs]; |
|
when "101011" => --SW *(long*)ptr=r[rt]; |
a_source := a_from_reg_source; |
b_source := b_from_signed_imm; |
alu_function := alu_add; |
mem_source := mem_write32; --address=(short)imm+r[rs]; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_SIGNED_IMM; |
alu_function := ALU_ADD; |
mem_source := MEM_WRITE32; --address=(short)imm+r[rs]; |
|
when "101110" => --SWR //Not Implemented |
when "101111" => --CACHE |
when "110000" => --LL r[rt]=*(long*)ptr; |
416,7 → 470,7
when others => |
end case; |
|
if c_source = c_from_null then |
if c_source = C_FROM_NULL then |
rd := "000000"; |
end if; |
|
424,15 → 478,15
rs := "111111"; --interrupt vector |
rt := "000000"; |
rd := "101110"; --save PC in EPC |
alu_function := alu_or; |
shift_function := shift_nothing; |
mult_function := mult_nothing; |
branch_function := branch_yes; |
a_source := a_from_reg_source; |
b_source := b_from_reg_target; |
c_source := c_from_pc; |
pc_source := from_lbranch; |
mem_source := mem_fetch; |
alu_function := ALU_OR; |
shift_function := SHIFT_NOTHING; |
mult_function := MULT_NOTHING; |
branch_function := BRANCH_YES; |
a_source := A_FROM_REG_SOURCE; |
b_source := B_FROM_REG_TARGET; |
c_source := C_FROM_pc; |
pc_source := FROM_LBRANCH; |
mem_source := MEM_FETCH; |
end if; |
|
rs_index <= rs; |
/trunk/vhdl/mult.vhd
44,6 → 44,7
generic(adder_type : string := "GENERIC"; |
mult_type : string := "GENERIC"); |
port(clk : in std_logic; |
reset_in : in std_logic; |
a, b : in std_logic_vector(31 downto 0); |
mult_func : in mult_function_type; |
c_mult : out std_logic_vector(31 downto 0); |
52,9 → 53,6
|
architecture logic of mult is |
|
-- type mult_function_type is ( |
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo, |
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide); |
signal do_mult_reg : std_logic; |
signal do_signed_reg : std_logic; |
signal count_reg : std_logic_vector(5 downto 0); |
63,19 → 61,13
signal answer_reg : std_logic_vector(31 downto 0); |
signal aa, bb : std_logic_vector(33 downto 0); |
signal sum : std_logic_vector(33 downto 0); |
signal sum2 : std_logic_vector(67 downto 0); |
signal reg_a_times3 : std_logic_vector(33 downto 0); |
signal sign_extend_sig : std_logic; |
signal a_neg_sig : std_logic_vector(31 downto 0); |
signal b_neg_sig : std_logic_vector(31 downto 0); |
|
--Used in Xilinx tri-state area optimizated version |
signal SUB_Y, A_PROCESSED, B_PROCESSED, A_REG, B_REG : std_logic_vector(31 downto 0); |
signal DIV_Y, DIV_Y_IN, DIV_Y_IN_CALC, DIV_Y_IN_INIT, Y_IN, Y_IN2, MULT_Y, Y : std_logic_vector(63 downto 0) := (others => '0'); |
signal SAVE_Y, SAVE_DIV_Y, MULT_ND, MULT_RDY, DO_SIGNED, DIV_ND : std_logic; |
signal DIV_COUNT, INVERT_A, INVERT_B, INVERT_Y, DIV_RDY : std_logic; |
signal DIV_COUNTER : std_logic_vector(4 downto 0); |
signal PAUSE_IN, SAVE_PAUSE, PAUSE : std_logic := '0'; |
signal MULT_RFD : std_logic; |
signal a_temp_sig, a_neg_sig, b_neg_sig : std_logic_vector(31 downto 0); |
signal a_temp_sig : std_logic_vector(31 downto 0); |
signal b_temp_sig : std_logic_vector(63 downto 0); |
signal a_msb, b_msb : std_logic; |
signal answer_temp_sig : std_logic_vector(31 downto 0); |
84,7 → 76,7
signal a_select : std_logic_vector(4 downto 0); |
signal b_select : std_logic_vector(11 downto 0); |
signal answer_select : std_logic_vector(2 downto 0); |
|
|
begin |
|
--sum = aa + bb |
116,15 → 108,15
sign_extend_sig <= do_signed_reg and do_mult_reg; |
|
-- Result |
c_mult <= reg_b(31 downto 0) when mult_func=mult_read_lo else |
reg_b(63 downto 32) when mult_func=mult_read_hi else |
c_mult <= reg_b(31 downto 0) when mult_func = MULT_READ_LO else |
reg_b(63 downto 32) when mult_func = MULT_READ_HI else |
ZERO; |
|
|
GENERIC_MULT: if MULT_TYPE="GENERIC" generate |
GENERIC_MULT: if MULT_TYPE = "GENERIC" generate |
|
--multiplication/division unit |
mult_proc: process(clk, a, b, mult_func, |
mult_proc: process(clk, reset_in, a, b, mult_func, |
do_mult_reg, do_signed_reg, count_reg, |
reg_a, reg_b, answer_reg, sum, reg_a_times3) |
variable do_mult_temp : std_logic; |
151,27 → 143,27
do_hi := '0'; |
|
case mult_func is |
when mult_read_lo => |
when mult_read_hi => |
when MULT_READ_LO => |
when MULT_READ_HI => |
do_hi := '1'; |
when mult_write_lo => |
when MULT_WRITE_LO => |
do_write := '1'; |
when mult_write_hi => |
when MULT_WRITE_HI => |
do_write := '1'; |
do_hi := '1'; |
when mult_mult => |
when MULT_MULT => |
start := '1'; |
do_mult_temp := '1'; |
do_signed_temp := '0'; |
when mult_signed_mult => |
when MULT_SIGNED_MULT => |
start := '1'; |
do_mult_temp := '1'; |
do_signed_temp := '1'; |
when mult_divide => |
when MULT_DIVIDE => |
start := '1'; |
do_mult_temp := '0'; |
do_signed_temp := '0'; |
when mult_signed_divide => |
when MULT_SIGNED_DIVIDE => |
start := '1'; |
do_mult_temp := '0'; |
do_signed_temp := a(31) xor b(31); |
183,12 → 175,12
answer_temp := ZERO; |
if do_mult_temp = '0' then |
b_temp(63) := '0'; |
if mult_func /= mult_signed_divide or a(31) = '0' then |
if mult_func /= MULT_SIGNED_DIVIDE or a(31) = '0' then |
a_temp := a; |
else |
a_temp := a_neg_sig; |
end if; |
if mult_func /= mult_signed_divide or b(31) = '0' then |
if mult_func /= MULT_SIGNED_DIVIDE or b(31) = '0' then |
b_temp(62 downto 31) := b; |
else |
b_temp(62 downto 31) := b_neg_sig; |
266,7 → 258,15
end if; |
end if; |
|
if rising_edge(clk) then |
if reset_in = '1' then |
do_mult_reg <= '0'; |
do_signed_reg <= '0'; |
count_reg <= "000000"; |
reg_a <= ZERO; |
reg_b <= ZERO & ZERO; |
answer_reg <= ZERO; |
reg_a_times3 <= "00" & ZERO; |
elsif rising_edge(clk) then |
do_mult_reg <= do_mult_temp; |
do_signed_reg <= do_signed_temp; |
count_reg <= count_temp; |
287,6 → 287,18
|
end process; |
|
--Only used in Xilinx tri-state area optimizated version |
a_temp_sig <= ZERO; |
b_temp_sig <= ZERO & ZERO; |
a_msb <= '0'; |
b_msb <= '0'; |
answer_temp_sig <= ZERO; |
aa_select <= "0000"; |
bb_select <= "00"; |
a_select <= "00000"; |
b_select <= ZERO(11 downto 0); |
answer_select <= "000"; |
|
end generate; |
|
|
319,27 → 331,27
answer_select <= (others => '0'); |
|
case mult_func is |
when mult_read_lo => |
when mult_read_hi => |
when MULT_READ_LO => |
when MULT_READ_HI => |
do_hi := '1'; |
when mult_write_lo => |
when MULT_WRITE_LO => |
do_write := '1'; |
when mult_write_hi => |
when MULT_WRITE_HI => |
do_write := '1'; |
do_hi := '1'; |
when mult_mult => |
when MULT_MULT => |
start := '1'; |
do_mult_temp := '1'; |
do_signed_temp := '0'; |
when mult_signed_mult => |
when MULT_SIGNED_MULT => |
start := '1'; |
do_mult_temp := '1'; |
do_signed_temp := '1'; |
when mult_divide => |
when MULT_DIVIDE => |
start := '1'; |
do_mult_temp := '0'; |
do_signed_temp := '0'; |
when mult_signed_divide => |
when MULT_SIGNED_DIVIDE => |
start := '1'; |
do_mult_temp := '0'; |
do_signed_temp := a(31) xor b(31); |
352,7 → 364,7
--answer_temp := ZERO; |
if do_mult_temp = '0' then |
--b_temp(63) := '0'; |
if mult_func /= mult_signed_divide or a(31) = '0' then |
if mult_func /= MULT_SIGNED_DIVIDE or a(31) = '0' then |
a_select(0) <= '1'; |
--a_temp := a; |
else |
359,7 → 371,7
a_select(1) <= '1'; |
--a_temp := a_neg; |
end if; |
if mult_func /= mult_signed_divide or b(31) = '0' then |
if mult_func /= MULT_SIGNED_DIVIDE or b(31) = '0' then |
b_select(0) <= '1'; |
--b_temp(62 downto 31) := b; |
else |
461,17 → 473,25
end if; |
end if; |
|
if rising_edge(clk) then |
do_mult_reg <= do_mult_temp; |
do_signed_reg <= do_signed_temp; |
count_reg <= count_temp; |
reg_a <= a_temp_sig; |
reg_b <= b_temp_sig; |
answer_reg <= answer_temp_sig; |
if start = '1' then |
reg_a_times3 <= ((a_temp_sig(31) and do_signed_temp) & a_temp_sig & '0') + |
((a_temp_sig(31) and do_signed_temp) & (a_temp_sig(31) and do_signed_temp) & a_temp_sig); |
end if; |
if reset_in = '1' then |
do_mult_reg <= '0'; |
do_signed_reg <= '0'; |
count_reg <= "000000"; |
reg_a <= ZERO; |
reg_b <= ZERO & ZERO; |
answer_reg <= ZERO; |
reg_a_times3 <= "00" & ZERO; |
elsif rising_edge(clk) then |
do_mult_reg <= do_mult_temp; |
do_signed_reg <= do_signed_temp; |
count_reg <= count_temp; |
reg_a <= a_temp_sig; |
reg_b <= b_temp_sig; |
answer_reg <= answer_temp_sig; |
if start = '1' then |
reg_a_times3 <= ((a_temp_sig(31) and do_signed_temp) & a_temp_sig & '0') + |
((a_temp_sig(31) and do_signed_temp) & (a_temp_sig(31) and do_signed_temp) & a_temp_sig); |
end if; |
end if; |
|
if count_reg(5) = '0' and mult_func/= mult_nothing and start = '0' then |
/trunk/vhdl/mlite_cpu.vhd
147,7 → 147,7
pause_any <= (mem_pause or pause_ctrl) or (pause_mult or pause_pipeline); |
pause_non_ctrl <= (mem_pause or pause_mult) or pause_pipeline; |
pause_bank <= (mem_pause or pause_ctrl or pause_mult) and not pause_pipeline; |
nullify_op <= '1' when (pc_source = from_lbranch and take_branch = '0') |
nullify_op <= '1' when (pc_source = FROM_LBRANCH and take_branch = '0') |
or intr_signal = '1' |
else '0'; |
c_bus <= c_alu or c_shift or c_mult; |
285,6 → 285,7
mult_type => mult_type) |
port map ( |
clk => clk, |
reset_in => reset, |
a => a_busD, |
b => b_busD, |
mult_func => mult_funcD, |
/trunk/vhdl/alu.vhd
23,30 → 23,26
end; --alu |
|
architecture logic of alu is |
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract, |
-- alu_less_than, alu_less_than_signed, |
-- alu_or, alu_and, alu_xor, alu_nor); |
|
signal aa, bb, sum : std_logic_vector(32 downto 0); |
signal do_add : std_logic; |
signal sign_ext : std_logic; |
begin |
|
do_add <= '1' when alu_function = alu_add else '0'; |
sign_ext <= '0' when alu_function = alu_less_than else '1'; |
do_add <= '1' when alu_function = ALU_ADD else '0'; |
sign_ext <= '0' when alu_function = ALU_LESS_THAN else '1'; |
aa <= (a_in(31) and sign_ext) & a_in; |
bb <= (b_in(31) and sign_ext) & b_in; |
|
-- synthesis translate_off |
GENERIC_ALU: if alu_type="GENERIC" generate |
GENERIC_ALU: if alu_type = "GENERIC" generate |
-- synthesis translate_on |
|
c_alu <= sum(31 downto 0) when alu_function=alu_add or alu_function=alu_subtract else |
ZERO(31 downto 1) & sum(32) when alu_function=alu_less_than or alu_function=alu_less_than_signed else |
a_in or b_in when alu_function=alu_or else |
a_in and b_in when alu_function=alu_and else |
a_in xor b_in when alu_function=alu_xor else |
a_in nor b_in when alu_function=alu_nor else |
c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or alu_function=ALU_SUBTRACT else |
ZERO(31 downto 1) & sum(32) when alu_function=ALU_LESS_THAN or alu_function=ALU_LESS_THAN_SIGNED else |
a_in or b_in when alu_function=ALU_OR else |
a_in and b_in when alu_function=ALU_AND else |
a_in xor b_in when alu_function=ALU_XOR else |
a_in nor b_in when alu_function=ALU_NOR else |
ZERO; |
|
-- synthesis translate_off |
57,13 → 53,13
|
AREA_OPTIMIZED_ALU: if alu_type="AREA_OPTIMIZED" generate |
|
c_alu <= sum(31 downto 0) when alu_function=alu_add or alu_function=alu_subtract else (others => 'Z'); |
c_alu <= ZERO(31 downto 1) & sum(32) when alu_function=alu_less_than or alu_function=alu_less_than_signed else (others => 'Z'); |
c_alu <= a_in or b_in when alu_function=alu_or else (others => 'Z'); |
c_alu <= a_in and b_in when alu_function=alu_and else (others => 'Z'); |
c_alu <= a_in xor b_in when alu_function=alu_xor else (others => 'Z'); |
c_alu <= a_in nor b_in when alu_function=alu_nor else (others => 'Z'); |
c_alu <= ZERO when alu_function=alu_nothing else (others => 'Z'); |
c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or alu_function=ALU_SUBTRACT else (others => 'Z'); |
c_alu <= ZERO(31 downto 1) & sum(32) when alu_function=ALU_LESS_THAN or alu_function=ALU_LESS_THAN_SIGNED else (others => 'Z'); |
c_alu <= a_in or b_in when alu_function=ALU_OR else (others => 'Z'); |
c_alu <= a_in and b_in when alu_function=ALU_AND else (others => 'Z'); |
c_alu <= a_in xor b_in when alu_function=ALU_XOR else (others => 'Z'); |
c_alu <= a_in nor b_in when alu_function=ALU_NOR else (others => 'Z'); |
c_alu <= ZERO when alu_function=ALU_NOTHING else (others => 'Z'); |
|
end generate; |
|
/trunk/vhdl/bus_mux.vhd
42,21 → 42,18
|
architecture logic of bus_mux is |
begin |
-- type a_source_type is (a_from_reg_source, a_from_imm10_6); |
-- type b_source_type is (b_from_reg_target, b_from_imm, b_from_signed_imm); |
-- type c_source_type is (c_from_null, c_from_alu, c_from_shift, |
-- c_from_mult, c_from_memory, c_from_pc, c_from_imm_shift16, |
-- c_from_reg_source_nez, c_from_reg_source_eqz); |
|
amux: process(reg_source, imm_in, a_mux, c_pc) |
begin |
case a_mux is |
when a_from_reg_source => |
when A_FROM_REG_SOURCE => |
a_out <= reg_source; |
when a_from_imm10_6 => |
a_out(31 downto 5) <= ZERO(31 downto 5); |
a_out(4 downto 0) <= imm_in(10 downto 6); |
when others => --a_from_pc |
when A_FROM_IMM10_6 => |
a_out <= ZERO(31 downto 5) & imm_in(10 downto 6); |
when A_FROM_PC => |
a_out <= c_pc; |
when others => |
a_out <= c_pc; |
end case; |
end process; |
|
63,11 → 60,11
bmux: process(reg_target, imm_in, b_mux) |
begin |
case b_mux is |
when b_from_reg_target => |
when B_FROM_REG_TARGET => |
b_out <= reg_target; |
when b_from_imm => |
when B_FROM_IMM => |
b_out <= ZERO(31 downto 16) & imm_in; |
when b_from_signed_imm => |
when B_FROM_SIGNED_IMM => |
if imm_in(15) = '0' then |
b_out(31 downto 16) <= ZERO(31 downto 16); |
else |
74,7 → 71,7
b_out(31 downto 16) <= "1111111111111111"; |
end if; |
b_out(15 downto 0) <= imm_in; |
when others => --b_from_immX4 |
when B_FROM_IMMX4 => |
if imm_in(15) = '0' then |
b_out(31 downto 18) <= "00000000000000"; |
else |
81,6 → 78,8
b_out(31 downto 18) <= "11111111111111"; |
end if; |
b_out(17 downto 0) <= imm_in & "00"; |
when others => |
b_out <= reg_target; |
end case; |
end process; |
|
87,20 → 86,16
cmux: process(c_bus, c_memory, c_pc, c_pc_plus4, imm_in, c_mux) |
begin |
case c_mux is |
when c_from_alu => -- | c_from_shift | c_from_mult => |
when C_FROM_ALU => -- | C_FROM_SHIFT | C_FROM_MULT => |
reg_dest_out <= c_bus; |
when c_from_memory => |
when C_FROM_MEMORY => |
reg_dest_out <= c_memory; |
when c_from_pc => |
when C_FROM_PC => |
reg_dest_out <= c_pc(31 downto 3) & "000"; --backup one opcode |
when c_from_pc_plus4 => |
when C_FROM_PC_PLUS4 => |
reg_dest_out <= c_pc_plus4; |
when c_from_imm_shift16 => |
when C_FROM_IMM_SHIFT16 => |
reg_dest_out <= imm_in & ZERO(15 downto 0); |
-- when from_reg_source_nez => |
--???? |
-- when from_reg_source_eqz => |
--???? |
when others => |
reg_dest_out <= c_bus; |
end case; |
115,19 → 110,19
is_equal := '0'; |
end if; |
case branch_func is |
when branch_ltz => |
when BRANCH_LTZ => |
take_branch <= reg_source(31); |
when branch_lez => |
when BRANCH_LEZ => |
take_branch <= reg_source(31) or is_equal; |
when branch_eq => |
when BRANCH_EQ => |
take_branch <= is_equal; |
when branch_ne => |
when BRANCH_NE => |
take_branch <= not is_equal; |
when branch_gez => |
when BRANCH_GEZ => |
take_branch <= not reg_source(31); |
when branch_gtz => |
when BRANCH_GTZ => |
take_branch <= not reg_source(31) and not is_equal; |
when branch_yes => |
when BRANCH_YES => |
take_branch <= '1'; |
when others => |
take_branch <= is_equal; |