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

Subversion Repositories lxp32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /lxp32/trunk/rtl
    from Rev 2 to Rev 6
    Reverse comparison

Rev 2 → Rev 6

/lxp32_alu.vhd
31,7 → 31,6
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;
62,22 → 61,16
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 logic_result: std_logic_vector(31 downto 0);
signal logic_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_result: 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;
97,7 → 90,11
-- Add/subtract
 
addend1<=unsigned(op1_i);
addend2<=unsigned(op2_i) when cmd_negate_op2_i='0' else not unsigned(op2_i);
 
addend2_gen: for i in addend2'range generate
addend2(i)<=op2_i(i) xor cmd_negate_op2_i;
end generate;
 
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;
 
126,15 → 123,16
(not cmp_s1 and not cmp_s2 and cmp_carry) or
(not cmp_s1 and cmp_s2)) and not cmp_eq;
 
-- Logical functions
-- Bitwise operations (and, or, xor)
-- Note: (a or b) = (a and b) or (a xor b)
 
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;
logic_result_gen: for i in logic_result'range generate
logic_result(i)<=((op1_i(i) and op2_i(i)) and cmd_and_i) or
((op1_i(i) xor op2_i(i)) and cmd_xor_i);
end generate;
 
logic_we<=(cmd_and_i or cmd_xor_i) and valid_i;
 
-- Multiplier
 
mul_ce<=cmd_mul_i and valid_i;
191,27 → 189,17
op1_i=>op1_i,
op2_i=>op2_i,
signed_i=>cmd_signed_i,
rem_i=>cmd_div_mod_i,
ce_o=>div_we,
quotient_o=>div_quotient,
remainder_o=>div_remainder
result_o=>div_result
);
end generate;
 
gen_no_divider: if not DIVIDER_EN generate
div_we<=div_ce;
div_quotient<=(others=>'0');
div_remainder<=(others=>'0');
div_result<=(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;
233,18 → 221,15
 
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
(logic_result(i) and logic_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
(div_result(i) and div_we) 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;
result_we<=adder_we or logic_we or mul_we or div_we or shift_we;
we_o<=result_we;
 
-- Pipeline control
252,15 → 237,10
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
if rst_i='1' or result_we='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;
elsif shift_ce='1' or mul_ce='1' or div_ce='1' then
busy<='1';
end if;
end if;
end process;
/lxp32_cpu.vhd
14,7 → 14,7
DBUS_RMW: boolean;
DIVIDER_EN: boolean;
MUL_ARCH: string;
START_ADDR: std_logic_vector(29 downto 0)
START_ADDR: std_logic_vector(31 downto 0)
);
port(
clk_i: in std_logic;
42,6 → 42,7
 
signal fetch_word: std_logic_vector(31 downto 0);
signal fetch_next_ip: std_logic_vector(29 downto 0);
signal fetch_current_ip: std_logic_vector(29 downto 0);
signal fetch_valid: std_logic;
signal fetch_jump_ready: std_logic;
 
61,7 → 62,6
signal decode_cmd_jump: std_logic;
signal decode_cmd_negate_op2: std_logic;
signal decode_cmd_and: std_logic;
signal decode_cmd_or: std_logic;
signal decode_cmd_xor: std_logic;
signal decode_cmd_shift: std_logic;
signal decode_cmd_shift_right: std_logic;
89,8 → 89,6
signal interrupt_vector: std_logic_vector(2 downto 0);
signal interrupt_ready: std_logic;
signal interrupt_return: std_logic;
signal interrupts_enabled: std_logic_vector(7 downto 0);
signal interrupts_blocked: std_logic_vector(7 downto 0);
 
begin
 
109,6 → 107,7
word_o=>fetch_word,
next_ip_o=>fetch_next_ip,
current_ip_o=>fetch_current_ip,
valid_o=>fetch_valid,
ready_i=>decode_ready,
124,6 → 123,7
word_i=>fetch_word,
next_ip_i=>fetch_next_ip,
current_ip_i=>fetch_current_ip,
valid_i=>fetch_valid,
jump_valid_i=>execute_jump_valid,
ready_o=>decode_ready,
153,7 → 153,6
cmd_jump_o=>decode_cmd_jump,
cmd_negate_op2_o=>decode_cmd_negate_op2,
cmd_and_o=>decode_cmd_and,
cmd_or_o=>decode_cmd_or,
cmd_xor_o=>decode_cmd_xor,
cmd_shift_o=>decode_cmd_shift,
cmd_shift_right_o=>decode_cmd_shift_right,
189,7 → 188,6
cmd_jump_i=>decode_cmd_jump,
cmd_negate_op2_i=>decode_cmd_negate_op2,
cmd_and_i=>decode_cmd_and,
cmd_or_i=>decode_cmd_or,
cmd_xor_i=>decode_cmd_xor,
cmd_shift_i=>decode_cmd_shift,
cmd_shift_right_i=>decode_cmd_shift_right,
221,9 → 219,7
jump_dst_o=>execute_jump_dst,
jump_ready_i=>fetch_jump_ready,
interrupt_return_o=>interrupt_return,
interrupts_enabled_o=>interrupts_enabled,
interrupts_blocked_o=>interrupts_blocked
interrupt_return_o=>interrupt_return
);
 
scratchpad_inst: entity work.lxp32_scratchpad(rtl)
247,13 → 243,14
irq_i=>irq_i,
interrupts_enabled_i=>interrupts_enabled,
interrupts_blocked_i=>interrupts_blocked,
interrupt_valid_o=>interrupt_valid,
interrupt_vector_o=>interrupt_vector,
interrupt_ready_i=>interrupt_ready,
interrupt_return_i=>interrupt_return
interrupt_return_i=>interrupt_return,
sp_waddr_i=>sp_waddr,
sp_we_i=>sp_we,
sp_wdata_i=>sp_wdata
);
 
end architecture;
/lxp32_dbus.vhd
54,6 → 54,7
signal sig: std_logic;
signal rmw_mode: std_logic;
 
signal dbus_rdata: std_logic_vector(31 downto 0);
signal selected_byte: std_logic_vector(7 downto 0);
 
begin
64,6 → 65,13
if rst_i='1' then
we_out<='0';
strobe<='0';
sig<='-';
byte_mode<='-';
sel<=(others=>'-');
we<='-';
rmw_mode<='-';
dbus_adr_o<=(others=>'-');
dbus_dat_o<=(others=>'-');
else
we_out<='0';
if strobe='0' then
72,10 → 80,10
sig<=cmd_signed_i;
dbus_adr_o<=addr_i(31 downto 2);
dbus_dat_o<=wdata_i;
if cmd_dbus_byte_i='0' then
byte_mode<='0';
dbus_dat_o<=wdata_i;
sel<="1111";
-- synthesis translate_off
85,11 → 93,14
-- synthesis translate_on
else
byte_mode<='1';
dbus_dat_o<=wdata_i(7 downto 0)&wdata_i(7 downto 0)&
wdata_i(7 downto 0)&wdata_i(7 downto 0);
case addr_i(1 downto 0) is
when "00" => sel<="0001"; dbus_dat_o(7 downto 0)<=wdata_i(7 downto 0);
when "01" => sel<="0010"; dbus_dat_o(15 downto 8)<=wdata_i(7 downto 0);
when "10" => sel<="0100"; dbus_dat_o(23 downto 16)<=wdata_i(7 downto 0);
when "11" => sel<="1000"; dbus_dat_o(31 downto 24)<=wdata_i(7 downto 0);
when "00" => sel<="0001";
when "01" => sel<="0010";
when "10" => sel<="0100";
when "11" => sel<="1000";
when others =>
end case;
end if;
136,27 → 147,24
dbus_sel_o<=(others=>'1');
end generate;
 
selected_byte_gen: for i in selected_byte'range generate
selected_byte(i)<=(dbus_dat_i(i) and sel(0)) or
(dbus_dat_i(i+8) and sel(1)) or
(dbus_dat_i(i+16) and sel(2)) or
(dbus_dat_i(i+24) and sel(3));
end generate;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if byte_mode='0' then
rdata_o<=dbus_dat_i;
else
rdata_o(7 downto 0)<=selected_byte;
for i in rdata_o'high downto 8 loop
rdata_o(i)<=selected_byte(selected_byte'high) and sig;
end loop;
end if;
dbus_rdata<=dbus_dat_i;
end if;
end process;
 
selected_byte_gen: for i in selected_byte'range generate
selected_byte(i)<=(dbus_rdata(i) and sel(0)) or
(dbus_rdata(i+8) and sel(1)) or
(dbus_rdata(i+16) and sel(2)) or
(dbus_rdata(i+24) and sel(3));
end generate;
 
rdata_o<=dbus_rdata when byte_mode='0' else
X"000000"&selected_byte when selected_byte(selected_byte'high)='0' or sig='0' else
X"FFFFFF"&selected_byte;
 
we_o<=we_out;
busy_o<=strobe or we_out;
 
/lxp32_decode.vhd
19,6 → 19,7
word_i: in std_logic_vector(31 downto 0);
next_ip_i: in std_logic_vector(29 downto 0);
current_ip_i: in std_logic_vector(29 downto 0);
valid_i: in std_logic;
jump_valid_i: in std_logic;
ready_o: out std_logic;
48,7 → 49,6
cmd_jump_o: out std_logic;
cmd_negate_op2_o: out std_logic;
cmd_and_o: out std_logic;
cmd_or_o: out std_logic;
cmd_xor_o: out std_logic;
cmd_shift_o: out std_logic;
cmd_shift_right_o: out std_logic;
78,8 → 78,6
signal rd1: std_logic_vector(7 downto 0);
signal rd2: std_logic_vector(7 downto 0);
 
signal current_ip: unsigned(next_ip_i'range);
 
-- Signals related to pipeline control
 
signal downstream_busy: std_logic;
119,8 → 117,6
downstream_busy<=valid_out and not ready_i;
busy<=downstream_busy or self_busy;
 
current_ip<=unsigned(next_ip_i)-1;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
129,6 → 125,29
self_busy<='0';
state<=Regular;
interrupt_ready<='0';
cmd_loadop3_o<='-';
cmd_signed_o<='-';
cmd_dbus_o<='-';
cmd_dbus_store_o<='-';
cmd_dbus_byte_o<='-';
cmd_addsub_o<='-';
cmd_negate_op2_o<='-';
cmd_mul_o<='-';
cmd_div_o<='-';
cmd_div_mod_o<='-';
cmd_cmp_o<='-';
cmd_jump_o<='-';
cmd_and_o<='-';
cmd_xor_o<='-';
cmd_shift_o<='-';
cmd_shift_right_o<='-';
rd1_select<='-';
rd1_direct<=(others=>'-');
rd2_select<='-';
rd2_direct<=(others=>'-');
op3_o<=(others=>'-');
jump_type_o<=(others=>'-');
dst_out<=(others=>'-');
else
interrupt_ready<='0';
if jump_valid_i='1' then
136,34 → 155,36
self_busy<='0';
state<=Regular;
elsif downstream_busy='0' then
op3_o<=(others=>'-');
rd1_direct<=std_logic_vector(resize(signed(rd1),rd1_direct'length));
rd2_direct<=std_logic_vector(resize(signed(rd2),rd2_direct'length));
cmd_signed_o<=opcode(0);
cmd_div_mod_o<=opcode(1);
cmd_shift_right_o<=opcode(1);
cmd_dbus_byte_o<=opcode(1);
cmd_dbus_store_o<=opcode(2);
case state is
when Regular =>
cmd_loadop3_o<='0';
cmd_signed_o<='0';
cmd_dbus_o<='0';
cmd_dbus_store_o<='0';
cmd_dbus_byte_o<='0';
cmd_addsub_o<='0';
cmd_negate_op2_o<='0';
cmd_mul_o<='0';
cmd_div_o<='0';
cmd_div_mod_o<='0';
cmd_cmp_o<='0';
cmd_jump_o<='0';
cmd_and_o<='0';
cmd_or_o<='0';
cmd_xor_o<='0';
cmd_shift_o<='0';
cmd_shift_right_o<='0';
op3_o<=(others=>'-');
jump_type_o<=opcode(3 downto 0);
if interrupt_valid_i='1' and valid_i='1' then
cmd_jump_o<='1';
cmd_loadop3_o<='1';
op3_o<=std_logic_vector(current_ip)&"01"; -- LSB indicates interrupt return
op3_o<=current_ip_i&"01"; -- LSB indicates interrupt return
dst_out<=X"FD"; -- interrupt return pointer
rd1_select<='1';
rd2_select<='0';
172,19 → 193,17
self_busy<='1';
state<=ContinueInterrupt;
else
if opcode="000001" then
if opcode(5 downto 3)="101" or opcode="000001" then -- lc or lcs
cmd_loadop3_o<='1';
-- Setting op3_o here only affects the lcs instruction
op3_o<=std_logic_vector(resize(signed(opcode(2 downto 0)&
t1&t2&rd1&rd2),op3_o'length));
end if;
cmd_signed_o<=opcode(0);
if opcode(5 downto 3)="001" then
cmd_dbus_o<='1';
end if;
cmd_dbus_store_o<=opcode(2);
cmd_dbus_byte_o<=opcode(1);
if opcode(5 downto 1)="01000" then
cmd_addsub_o<='1';
end if;
199,27 → 218,20
cmd_div_o<='1';
end if;
cmd_div_mod_o<=opcode(1);
if opcode="100000" then
if opcode(5 downto 3)="100" then -- jump or call
cmd_jump_o<='1';
end if;
if opcode="100001" then
cmd_jump_o<='1';
cmd_loadop3_o<='1';
cmd_loadop3_o<=opcode(0);
-- Setting op3_o here only affects the call instruction
op3_o<=next_ip_i&"00";
end if;
if opcode="011000" then
-- Note: (a or b) = (a and b) or (a xor b)
if opcode(5 downto 1)="01100" then
cmd_and_o<='1';
end if;
if opcode="011001" then
cmd_or_o<='1';
end if;
if opcode="011010" then
if opcode="011010" or opcode="011001" then
cmd_xor_o<='1';
end if;
227,8 → 239,6
cmd_shift_o<='1';
end if;
cmd_shift_right_o<=opcode(1);
if opcode(5 downto 4)="11" then
cmd_cmp_o<='1';
cmd_negate_op2_o<='1';
235,9 → 245,7
end if;
rd1_select<=t1;
rd1_direct<=std_logic_vector(resize(signed(rd1),rd1_direct'length));
rd2_select<=t2;
rd2_direct<=std_logic_vector(resize(signed(rd2),rd2_direct'length));
dst_out<=destination;
/lxp32_divider.vhd
5,8 → 5,8
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Based on the NRD (Non Restoring Division) algorithm. One division
-- takes 37 cycles.
-- Based on the NRD (Non Restoring Division) algorithm. Takes
-- 36 cycles to calculate quotient (37 for remainder).
---------------------------------------------------------------------
 
library ieee;
21,9 → 21,9
op1_i: in std_logic_vector(31 downto 0);
op2_i: in std_logic_vector(31 downto 0);
signed_i: in std_logic;
rem_i: in std_logic;
ce_o: out std_logic;
quotient_o: out std_logic_vector(31 downto 0);
remainder_o: out std_logic_vector(31 downto 0)
result_o: out std_logic_vector(31 downto 0)
);
end entity;
 
31,15 → 31,11
 
-- Complementor signals
 
signal compl1_inv: std_logic;
signal compl2_inv: std_logic;
signal compl1_mux: std_logic_vector(31 downto 0);
signal compl2_mux: std_logic_vector(31 downto 0);
signal compl1_out: std_logic_vector(31 downto 0);
signal compl2_out: std_logic_vector(31 downto 0);
signal compl_inv: std_logic;
signal compl_mux: std_logic_vector(31 downto 0);
signal compl_out: std_logic_vector(31 downto 0);
 
signal inv_q: std_logic;
signal inv_r: std_logic;
signal inv_res: std_logic;
 
-- Divider FSM signals
 
47,6 → 43,7
 
signal dividend: unsigned(31 downto 0);
signal divisor: unsigned(32 downto 0);
signal want_remainder: std_logic;
 
signal partial_remainder: unsigned(32 downto 0);
signal addend: unsigned(32 downto 0);
61,43 → 58,39
-- Output restoration signals
 
signal remainder_corrector: unsigned(31 downto 0);
signal remainder_res: unsigned(31 downto 0);
signal quotient_res: unsigned(31 downto 0);
signal remainder_corrector_1: std_logic;
signal remainder_pos: unsigned(31 downto 0);
signal result_pos: unsigned(31 downto 0);
 
begin
 
compl1_inv<=op1_i(31) and signed_i when ce_i='1' else inv_q;
compl2_inv<=op2_i(31) and signed_i when ce_i='1' else inv_r;
compl_inv<=op1_i(31) and signed_i when ce_i='1' else inv_res;
compl_mux<=op1_i when ce_i='1' else std_logic_vector(result_pos);
 
compl1_mux<=op1_i when ce_i='1' else std_logic_vector(quotient_res);
compl2_mux<=op2_i when ce_i='1' else std_logic_vector(remainder_res);
 
compl_op1_inst: entity work.lxp32_compl(rtl)
port map(
clk_i=>clk_i,
compl_i=>compl1_inv,
d_i=>compl1_mux,
d_o=>compl1_out
compl_i=>compl_inv,
d_i=>compl_mux,
d_o=>compl_out
);
 
compl_op2_inst: entity work.lxp32_compl(rtl)
port map(
clk_i=>clk_i,
compl_i=>compl2_inv,
d_i=>compl2_mux,
d_o=>compl2_out
);
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
fsm_ce<='0';
want_remainder<='-';
inv_res<='-';
else
fsm_ce<=ce_i;
if ce_i='1' then
inv_q<=(op1_i(31) xor op2_i(31)) and signed_i;
inv_r<=op1_i(31) and signed_i;
want_remainder<=rem_i;
if rem_i='1' then
inv_res<=op1_i(31) and signed_i;
else
inv_res<=(op1_i(31) xor op2_i(31)) and signed_i;
end if;
end if;
end if;
end if;
112,7 → 105,7
sum<=partial_remainder+addend+(to_unsigned(0,32)&sum_subtract);
sum_positive<=not sum(32);
 
-- Divisor state machine
-- Divider state machine
 
process (clk_i) is
begin
120,26 → 113,38
if rst_i='1' then
cnt<=0;
ceo<='0';
divisor<=(others=>'-');
dividend<=(others=>'-');
partial_remainder<=(others=>'-');
sum_subtract<='-';
else
ceo<='0';
if cnt=1 then
ceo<='1';
else
ceo<='0';
end if;
if ce_i='1' then
divisor(31 downto 0)<=unsigned(op2_i);
divisor(32)<=op2_i(31) and signed_i;
end if;
if fsm_ce='1' then
dividend<=unsigned(compl1_out(30 downto 0)&"0");
divisor<=unsigned("0"&compl2_out);
partial_remainder<=to_unsigned(0,32)&compl1_out(31);
sum_subtract<='1';
cnt<=34;
elsif cnt>0 then
dividend<=unsigned(compl_out(30 downto 0)&"0");
partial_remainder<=to_unsigned(0,32)&compl_out(31);
sum_subtract<=not divisor(32);
if want_remainder='1' then
cnt<=34;
else
cnt<=33;
end if;
else
partial_remainder<=sum(31 downto 0)&dividend(31);
sum_subtract<=sum_positive;
sum_subtract<=sum_positive xor divisor(32);
dividend<=dividend(30 downto 0)&sum_positive;
if cnt=1 then
ceo<='1';
if cnt>0 then
cnt<=cnt-1;
end if;
cnt<=cnt-1;
else
dividend<=(others=>'-');
divisor<=(others=>'-');
partial_remainder<=(others=>'-');
end if;
end if;
end if;
151,15 → 156,17
begin
if rising_edge(clk_i) then
for i in remainder_corrector'range loop
remainder_corrector(i)<=divisor(i) and not sum_positive;
remainder_corrector(i)<=(divisor(i) xor divisor(32)) and not sum_positive;
end loop;
quotient_res<=dividend;
remainder_res<=partial_remainder(32 downto 1)+remainder_corrector;
remainder_corrector_1<=divisor(32) and not sum_positive;
remainder_pos<=partial_remainder(32 downto 1)+remainder_corrector+
(to_unsigned(0,31)&remainder_corrector_1);
end if;
end process;
 
quotient_o<=compl1_out;
remainder_o<=compl2_out;
result_pos<=remainder_pos when want_remainder='1' else dividend;
 
result_o<=compl_out;
ce_o<=ceo;
 
end architecture;
/lxp32_execute.vhd
34,7 → 34,6
cmd_jump_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;
66,9 → 65,7
jump_dst_o: out std_logic_vector(29 downto 0);
jump_ready_i: in std_logic;
interrupt_return_o: out std_logic;
interrupts_enabled_o: out std_logic_vector(7 downto 0);
interrupts_blocked_o: out std_logic_vector(7 downto 0)
interrupt_return_o: out std_logic
);
end entity;
 
116,8 → 113,6
-- Signals related to interrupt handling
 
signal interrupt_return: std_logic:='0';
signal interrupts_enabled: std_logic_vector(7 downto 0):=(others=>'0');
signal interrupts_blocked: std_logic_vector(7 downto 0):=(others=>'0');
 
begin
 
148,7 → 143,6
cmd_cmp_i=>cmd_cmp_i,
cmd_negate_op2_i=>cmd_negate_op2_i,
cmd_and_i=>cmd_and_i,
cmd_or_i=>cmd_or_i,
cmd_xor_i=>cmd_xor_i,
cmd_shift_i=>cmd_shift_i,
cmd_shift_right_i=>cmd_shift_right_i,
182,11 → 176,12
if rst_i='1' then
jump_valid<='0';
interrupt_return<='0';
jump_dst<=(others=>'-');
else
if jump_valid='0' then
jump_dst<=op1_i(31 downto 2);
if can_execute='1' and cmd_jump_i='1' and jump_condition='1' then
jump_valid<='1';
jump_dst<=op1_i(31 downto 2);
interrupt_return<=op1_i(0);
end if;
elsif jump_ready_i='1' then
262,22 → 257,4
sp_waddr_o<=result_regaddr;
sp_wdata_o<=result_mux;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
interrupts_enabled<=(others=>'0');
interrupts_blocked<=(others=>'0');
else
if result_valid='1' and result_regaddr=X"FC" then
interrupts_enabled<=result_mux(7 downto 0);
interrupts_blocked<=result_mux(15 downto 8);
end if;
end if;
end if;
end process;
 
interrupts_enabled_o<=interrupts_enabled;
interrupts_blocked_o<=interrupts_blocked;
 
end architecture;
/lxp32_fetch.vhd
14,7 → 14,7
 
entity lxp32_fetch is
generic(
START_ADDR: std_logic_vector(29 downto 0)
START_ADDR: std_logic_vector(31 downto 0)
);
port(
clk_i: in std_logic;
26,6 → 26,7
lli_busy_i: in std_logic;
word_o: out std_logic_vector(31 downto 0);
current_ip_o: out std_logic_vector(29 downto 0);
next_ip_o: out std_logic_vector(29 downto 0);
valid_o: out std_logic;
ready_i: in std_logic;
41,7 → 42,7
signal init: std_logic:='1';
signal init_cnt: unsigned(7 downto 0):=(others=>'0');
 
signal fetch_addr: std_logic_vector(29 downto 0):=START_ADDR;
signal fetch_addr: std_logic_vector(29 downto 0):=START_ADDR(31 downto 2);
 
signal next_word: std_logic;
signal suppress_re: std_logic:='0';
50,14 → 51,17
 
signal fifo_rst: std_logic;
signal fifo_we: std_logic;
signal fifo_din: std_logic_vector(61 downto 0);
signal fifo_din: std_logic_vector(31 downto 0);
signal fifo_re: std_logic;
signal fifo_dout: std_logic_vector(61 downto 0);
signal fifo_dout: std_logic_vector(31 downto 0);
signal fifo_empty: std_logic;
signal fifo_full: std_logic;
 
signal jr: std_logic:='0';
 
signal next_ip: std_logic_vector(fetch_addr'range);
signal current_ip: std_logic_vector(fetch_addr'range);
 
begin
 
-- INIT state machine (to initialize all registers)
96,10 → 100,11
begin
if rising_edge(clk_i) then
if rst_i='1' then
fetch_addr<=START_ADDR;
fetch_addr<=START_ADDR(31 downto 2);
requested<='0';
jr<='0';
suppress_re<='0';
next_ip<=(others=>'-');
else
jr<='0';
-- Suppress LLI request if jump signal is active but will not be processed
112,6 → 117,13
requested<=re and not (jump_valid_i and not jr);
end if;
if next_word='1' then
-- It's not immediately obvious why, but current_ip and next_ip will contain
-- the addresses of the current instruction and the next instruction to be
-- fetched, respectively, by the time the instruction is passed to the decode
-- stage. Basically, this is because when either the decoder or the IBUS
-- stalls, the fetch_addr counter will also stop incrementing.
next_ip<=fetch_addr;
current_ip<=next_ip;
if jump_valid_i='1' and jr='0' then
fetch_addr<=jump_dst_i;
jr<='1';
134,12 → 146,12
 
fifo_rst<=rst_i or (jump_valid_i and not jr);
fifo_we<=requested and not lli_busy_i;
fifo_din<=fetch_addr&lli_dat_i;
fifo_din<=lli_dat_i;
fifo_re<=ready_i and not fifo_empty;
 
ubuf_inst: entity work.lxp32_ubuf(rtl)
generic map(
DATA_WIDTH=>62
DATA_WIDTH=>32
)
port map(
clk_i=>clk_i,
154,9 → 166,61
full_o=>fifo_full
);
 
next_ip_o<=fifo_dout(61 downto 32);
 
word_o<=fifo_dout(31 downto 0) when init='1' else X"40"&std_logic_vector(init_cnt)&X"0000";
next_ip_o<=next_ip;
current_ip_o<=current_ip;
word_o<=fifo_dout when init='1' else X"40"&std_logic_vector(init_cnt)&X"0000";
valid_o<=not fifo_empty or not init;
 
-- Note: the following code contains a few simulation-only assertions
-- to check that current_ip and next_ip signals, used in procedure calls
-- and interrupts, are correct.
-- This code should be ignored by a synthesizer since it doesn't drive
-- any signals, but we also surround it by metacomments, just in case.
 
-- synthesis translate_off
 
process (clk_i) is
type Pair is record
addr: std_logic_vector(fetch_addr'range);
data: std_logic_vector(31 downto 0);
end record;
type Pairs is array (7 downto 0) of Pair;
variable buf: Pairs;
variable count: integer range buf'range:=0;
variable current_pair: Pair;
begin
if rising_edge(clk_i) then
if fifo_rst='1' then -- jump
count:=0;
elsif fifo_we='1' then -- LLI returned data
current_pair.data:=fifo_din;
buf(count):=current_pair;
count:=count+1;
end if;
if re='1' and lli_busy_i='0' then -- data requested
current_pair.addr:=fetch_addr;
end if;
if fifo_empty='0' and fifo_rst='0' then -- fetch output is valid
assert count>0
report "Fetch: buffer should be empty"
severity failure;
assert buf(0).data=fifo_dout
report "Fetch: incorrect data"
severity failure;
assert buf(0).addr=current_ip
report "Fetch: incorrect current_ip"
severity failure;
assert std_logic_vector(unsigned(buf(0).addr)+1)=next_ip
report "Fetch: incorrect next_ip"
severity failure;
if ready_i='1' then
buf(buf'high-1 downto 0):=buf(buf'high downto 1); -- we don't care about the highest item
count:=count-1;
end if;
end if;
end if;
end process;
 
-- synthesis translate_on
 
end architecture;
/lxp32_icache.vhd
111,12 → 111,12
 
ram_inst: entity work.lxp32_ram256x32(rtl)
port map(
wclk_i=>clk_i,
clk_i=>clk_i,
we_i=>ram_we,
waddr_i=>ram_waddr,
wdata_i=>wbm_dat_i,
rclk_i=>clk_i,
re_i=>ram_re,
raddr_i=>ram_raddr,
rdata_o=>lli_dat_o
202,6 → 202,22
burst_cnt<=0;
wb_stb<='0';
wrap_cnt<=0;
wb_cti<=(others=>'-');
burst1<='-';
current_offset<=(others=>'-');
start_offset<=(others=>'-');
current_base<=(others=>'-');
next_base<=(others=>'-');
prev_base<=(others=>'-');
-- To suppress numeric_std warnings
-- synthesis translate_off
current_offset<=(others=>'0');
start_offset<=(others=>'0');
current_base<=(others=>'0');
next_base<=(others=>'0');
prev_base<=(others=>'0');
-- synthesis translate_on
else
if burst_cnt=0 and init='1' then
if miss='1' and near_miss='0' then
/lxp32_interrupt_mux.vhd
20,13 → 20,14
irq_i: in std_logic_vector(7 downto 0);
interrupts_enabled_i: in std_logic_vector(7 downto 0);
interrupts_blocked_i: in std_logic_vector(7 downto 0);
interrupt_valid_o: out std_logic;
interrupt_vector_o: out std_logic_vector(2 downto 0);
interrupt_ready_i: in std_logic;
interrupt_return_i: in std_logic
interrupt_return_i: in std_logic;
sp_waddr_i: in std_logic_vector(7 downto 0);
sp_we_i: in std_logic;
sp_wdata_i: in std_logic_vector(31 downto 0)
);
end entity;
 
41,6 → 42,9
 
signal interrupt_valid: std_logic:='0';
 
signal interrupts_enabled: std_logic_vector(7 downto 0):=(others=>'0');
signal interrupts_blocked: std_logic_vector(7 downto 0):=(others=>'0');
 
begin
 
-- Note: "disabled" interrupts (i.e. for which interrupts_enabled_i(i)='0')
57,17 → 61,18
pending_interrupts<=(others=>'0');
state<=Ready;
interrupt_valid<='0';
interrupt_vector_o<=(others=>'-');
else
irq_reg<=irq_i;
pending_interrupts<=(pending_interrupts or
(irq_i and not irq_reg)) and
interrupts_enabled_i;
interrupts_enabled;
case state is
when Ready =>
for i in pending_interrupts'reverse_range loop -- lower interrupts have priority
if pending_interrupts(i)='1' and interrupts_blocked_i(i)='0' then
if pending_interrupts(i)='1' and interrupts_blocked(i)='0' then
pending_interrupts(i)<='0';
interrupt_valid<='1';
interrupt_vector_o<=std_logic_vector(to_unsigned(i,3));
91,4 → 96,17
 
interrupt_valid_o<=interrupt_valid;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_i='1' then
interrupts_enabled<=(others=>'0');
interrupts_blocked<=(others=>'0');
elsif sp_we_i='1' and sp_waddr_i=X"FC" then
interrupts_enabled<=sp_wdata_i(7 downto 0);
interrupts_blocked<=sp_wdata_i(15 downto 8);
end if;
end if;
end process;
 
end architecture;
/lxp32_mul_dsp.vhd
28,9 → 28,9
 
architecture rtl of lxp32_mul_dsp is
 
signal pp00: unsigned(31 downto 0);
signal pp01: unsigned(31 downto 0);
signal pp10: unsigned(31 downto 0);
signal pp00: std_logic_vector(31 downto 0);
signal pp01: std_logic_vector(31 downto 0);
signal pp10: std_logic_vector(31 downto 0);
 
signal product: unsigned(31 downto 0);
 
43,7 → 43,7
clk_i=>clk_i,
a_i=>op1_i(15 downto 0),
b_i=>op2_i(15 downto 0),
unsigned(p_o)=>pp00
p_o=>pp00
);
 
mul01_inst: entity work.lxp32_mul16x16
51,7 → 51,7
clk_i=>clk_i,
a_i=>op1_i(15 downto 0),
b_i=>op2_i(31 downto 16),
unsigned(p_o)=>pp01
p_o=>pp01
);
 
mul10_inst: entity work.lxp32_mul16x16
59,11 → 59,11
clk_i=>clk_i,
a_i=>op1_i(31 downto 16),
b_i=>op2_i(15 downto 0),
unsigned(p_o)=>pp10
p_o=>pp10
);
 
product(31 downto 16)<=pp00(31 downto 16)+pp01(15 downto 0)+pp10(15 downto 0);
product(15 downto 0)<=pp00(15 downto 0);
product(31 downto 16)<=unsigned(pp00(31 downto 16))+unsigned(pp01(15 downto 0))+unsigned(pp10(15 downto 0));
product(15 downto 0)<=unsigned(pp00(15 downto 0));
result_o<=std_logic_vector(product);
 
process (clk_i) is
/lxp32_mul_opt.vhd
65,6 → 65,7
 
signal cnt: integer range 0 to 4:=0;
 
signal result: std_logic_vector(result_o'range);
signal ceo: std_logic:='0';
 
begin
109,8 → 110,17
if rst_i='1' then
ceo<='0';
cnt<=0;
reg1<=(others=>'-');
reg2<=(others=>'-');
acc_sum<=(others=>'-');
acc_carry<=(others=>'-');
else
ceo<='0';
if cnt=1 then
ceo<='1';
else
ceo<='0';
end if;
if ce_i='1' then
cnt<=4;
reg1<=unsigned(op1_i);
117,14 → 127,13
reg2<=unsigned(op2_i);
acc_sum<=(others=>'0');
acc_carry<=(others=>'0');
elsif cnt>0 then
else
acc_sum<=pp_sum(7);
acc_carry<=pp_carry(7)(acc_carry'range);
reg1<=reg1(reg1'high-8 downto 0)&X"00";
reg2<=X"00"&reg2(reg2'high downto 8);
cnt<=cnt-1;
if cnt=1 then
ceo<='1';
if cnt>0 then
cnt<=cnt-1;
end if;
end if;
end if;
131,7 → 140,29
end if;
end process;
 
result_o<=std_logic_vector(acc_sum+acc_carry);
result<=std_logic_vector(acc_sum+acc_carry);
 
result_o<=result;
ce_o<=ceo;
 
-- A simulation-time multiplication check
 
-- synthesis translate_off
 
process (clk_i) is
variable p: unsigned(op1_i'length+op2_i'length-1 downto 0);
begin
if rising_edge(clk_i) then
if ce_i='1' then
p:=unsigned(op1_i)*unsigned(op2_i);
elsif ceo='1' then
assert result=std_logic_vector(p(result'range))
report "Incorrect multiplication result"
severity failure;
end if;
end if;
end process;
 
-- synthesis translate_on
 
end architecture;
/lxp32_mul_seq.vhd
44,20 → 44,27
if rst_i='1' then
ceo<='0';
cnt<=0;
reg1<=(others=>'-');
reg2<=(others=>'-');
acc_sum<=(others=>'-');
else
ceo<='0';
if cnt=1 then
ceo<='1';
else
ceo<='0';
end if;
if ce_i='1' then
cnt<=32;
reg1<=unsigned(op1_i);
reg2<=unsigned(op2_i);
acc_sum<=(others=>'0');
elsif cnt>0 then
else
acc_sum<=acc_sum+pp;
reg1<=reg1(reg1'high-1 downto 0)&"0";
reg2<="0"&reg2(reg2'high downto 1);
cnt<=cnt-1;
if cnt=1 then
ceo<='1';
if cnt>0 then
cnt<=cnt-1;
end if;
end if;
end if;
/lxp32_ram256x32.vhd
17,12 → 17,12
 
entity lxp32_ram256x32 is
port(
wclk_i: in std_logic;
clk_i: in std_logic;
we_i: in std_logic;
waddr_i: in std_logic_vector(7 downto 0);
wdata_i: in std_logic_vector(31 downto 0);
rclk_i: in std_logic;
re_i: in std_logic;
raddr_i: in std_logic_vector(7 downto 0);
rdata_o: out std_logic_vector(31 downto 0)
35,7 → 35,7
signal ram: ram_type:=(others=>(others=>'0')); -- zero-initialize for SRAM-based FPGAs
 
attribute syn_ramstyle: string;
attribute syn_ramstyle of ram: signal is "block_ram,no_rw_check";
attribute syn_ramstyle of ram: signal is "no_rw_check";
attribute ram_style: string; -- for Xilinx
attribute ram_style of ram: signal is "block";
 
43,9 → 43,9
 
-- Write port
 
process (wclk_i) is
process (clk_i) is
begin
if rising_edge(wclk_i) then
if rising_edge(clk_i) then
if we_i='1' then
ram(to_integer(unsigned(waddr_i)))<=wdata_i;
end if;
54,11 → 54,15
 
-- Read port
 
process (rclk_i) is
process (clk_i) is
begin
if rising_edge(rclk_i) then
if rising_edge(clk_i) then
if re_i='1' then
rdata_o<=ram(to_integer(to_01(unsigned(raddr_i))));
if is_x(raddr_i) then -- to avoid numeric_std warnings during simulation
rdata_o<=(others=>'X');
else
rdata_o<=ram(to_integer(unsigned(raddr_i)));
end if;
end if;
end if;
end process;
/lxp32_scratchpad.vhd
42,12 → 42,12
 
ram_inst1: entity work.lxp32_ram256x32(rtl)
port map(
wclk_i=>clk_i,
clk_i=>clk_i,
we_i=>we_i,
waddr_i=>waddr_i,
wdata_i=>wdata_i,
rclk_i=>clk_i,
re_i=>'1',
raddr_i=>raddr1_i,
rdata_o=>ram1_rdata
57,12 → 57,12
 
ram_inst2: entity work.lxp32_ram256x32(rtl)
port map(
wclk_i=>clk_i,
clk_i=>clk_i,
we_i=>we_i,
waddr_i=>waddr_i,
wdata_i=>wdata_i,
rclk_i=>clk_i,
re_i=>'1',
raddr_i=>raddr2_i,
rdata_o=>ram2_rdata
/lxp32_shifter.vhd
68,6 → 68,10
if rising_edge(clk_i) then
if rst_i='1' then
ceo<='0';
stage2_data<=(others=>'-');
stage2_s<=(others=>'-');
stage2_fill<='-';
stage2_right<='-';
else
ceo<=ce_i;
stage2_data<=cascades(2);
/lxp32_ubuf.vhd
42,8 → 42,6
signal regs: regs_type;
signal regs_mux: regs_type;
 
signal wpointer: std_logic_vector(2 downto 0):="001";
 
begin
 
we<=we_i and not full;
53,23 → 51,23
begin
if rising_edge(clk_i) then
if rst_i='1' then
wpointer<="001";
empty<='1';
full<='0';
regs<=(others=>(others=>'-'));
else
if re='0' then
regs<=regs_mux;
regs(0)<=regs_mux(0);
else
regs(0)<=regs_mux(1);
end if;
regs(1)<=regs_mux(1);
if we='1' and re='0' then
wpointer<=wpointer(1 downto 0)&"0";
empty<='0';
full<=wpointer(1);
full<=not empty;
elsif we='0' and re='1' then
wpointer<="0"&wpointer(2 downto 1);
empty<=wpointer(1);
empty<=not full;
full<='0';
end if;
end if;
76,9 → 74,8
end if;
end process;
 
mux: for i in regs_mux'range generate
regs_mux(i)<=regs(i) when we='0' or wpointer(i)='0' else d_i;
end generate;
regs_mux(0)<=regs(0) when we='0' or empty='0' else d_i;
regs_mux(1)<=regs(1) when we='0' or empty='1' else d_i;
 
d_o<=regs(0);
empty_o<=empty;
/lxp32c_top.vhd
32,7 → 32,7
IBUS_BURST_SIZE: integer:=16;
IBUS_PREFETCH_SIZE: integer:=32;
MUL_ARCH: string:="dsp";
START_ADDR: std_logic_vector(29 downto 0):=(others=>'0')
START_ADDR: std_logic_vector(31 downto 0):=(others=>'0')
);
port(
clk_i: in std_logic;
/lxp32u_top.vhd
27,7 → 27,7
DBUS_RMW: boolean:=false;
DIVIDER_EN: boolean:=true;
MUL_ARCH: string:="dsp";
START_ADDR: std_logic_vector(29 downto 0):=(others=>'0')
START_ADDR: std_logic_vector(31 downto 0):=(others=>'0')
);
port(
clk_i: in std_logic;

powered by: WebSVN 2.1.0

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