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)÷nd(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"®2(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"®2(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; |