URL
https://opencores.org/ocsvn/plasma/plasma/trunk
Subversion Repositories plasma
Compare Revisions
- This comparison shows the changes necessary to convert path
/plasma/tags/V3_0/vhdl
- from Rev 350 to Rev 352
- ↔ Reverse comparison
Rev 350 → Rev 352
/pc_next.vhd
0,0 → 1,71
--------------------------------------------------------------------- |
-- TITLE: Program Counter Next |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/8/01 |
-- FILENAME: pc_next.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the Program Counter logic. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
entity pc_next is |
port(clk : in std_logic; |
reset_in : in std_logic; |
pc_new : in std_logic_vector(31 downto 2); |
take_branch : in std_logic; |
pause_in : in std_logic; |
opcode25_0 : in std_logic_vector(25 downto 0); |
pc_source : in pc_source_type; |
pc_future : out std_logic_vector(31 downto 2); |
pc_current : out std_logic_vector(31 downto 2); |
pc_plus4 : out std_logic_vector(31 downto 2)); |
end; --pc_next |
|
architecture logic of pc_next is |
signal pc_reg : std_logic_vector(31 downto 2); |
begin |
|
pc_select: process(clk, reset_in, pc_new, take_branch, pause_in, |
opcode25_0, pc_source, pc_reg) |
variable pc_inc : std_logic_vector(31 downto 2); |
variable pc_next : std_logic_vector(31 downto 2); |
begin |
pc_inc := bv_increment(pc_reg); --pc_reg+1 |
|
case pc_source is |
when FROM_INC4 => |
pc_next := pc_inc; |
when FROM_OPCODE25_0 => |
pc_next := pc_reg(31 downto 28) & opcode25_0; |
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 |
pc_next := pc_reg; |
end if; |
|
if reset_in = '1' then |
pc_reg <= ZERO(31 downto 2); |
pc_next := pc_reg; |
elsif rising_edge(clk) then |
pc_reg <= pc_next; |
end if; |
|
pc_future <= pc_next; |
pc_current <= pc_reg; |
pc_plus4 <= pc_inc; |
end process; |
|
end; --logic |
/mem_ctrl.vhd
0,0 → 1,182
--------------------------------------------------------------------- |
-- TITLE: Memory Controller |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 1/31/01 |
-- FILENAME: mem_ctrl.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Memory controller for the Plasma CPU. |
-- Supports Big or Little Endian mode. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
entity mem_ctrl is |
port(clk : in std_logic; |
reset_in : in std_logic; |
pause_in : in std_logic; |
nullify_op : in std_logic; |
address_pc : in std_logic_vector(31 downto 2); |
opcode_out : out std_logic_vector(31 downto 0); |
|
address_in : in std_logic_vector(31 downto 0); |
mem_source : in mem_source_type; |
data_write : in std_logic_vector(31 downto 0); |
data_read : out std_logic_vector(31 downto 0); |
pause_out : out std_logic; |
|
mem_address : out std_logic_vector(31 downto 2); |
mem_data_w : out std_logic_vector(31 downto 0); |
mem_data_r : in std_logic_vector(31 downto 0); |
mem_byte_we : out std_logic_vector(3 downto 0)); |
end; --entity mem_ctrl |
|
architecture logic of mem_ctrl is |
--"00" = big_endian; "11" = little_endian |
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); |
|
signal mem_state_reg : std_logic; |
constant STATE_ADDR : std_logic := '0'; |
constant STATE_ACCESS : std_logic := '1'; |
|
begin |
|
mem_proc: process(clk, reset_in, pause_in, nullify_op, |
address_pc, address_in, mem_source, data_write, |
mem_data_r, opcode_reg, next_opcode_reg, mem_state_reg) |
variable address_var : std_logic_vector(31 downto 2); |
variable data_read_var : std_logic_vector(31 downto 0); |
variable data_write_var : std_logic_vector(31 downto 0); |
variable opcode_next : std_logic_vector(31 downto 0); |
variable byte_sel_var : std_logic_vector(3 downto 0); |
variable mem_state_next : std_logic; |
variable pause_var : std_logic; |
variable bits : std_logic_vector(1 downto 0); |
begin |
byte_sel_var := "0000"; |
pause_var := '0'; |
data_read_var := ZERO; |
data_write_var := ZERO; |
mem_state_next := mem_state_reg; |
opcode_next := opcode_reg; |
|
case mem_source is |
when MEM_READ32 => |
data_read_var := mem_data_r; |
|
when MEM_READ16 | MEM_READ16S => |
if address_in(1) = ENDIAN_MODE(1) then |
data_read_var(15 downto 0) := mem_data_r(31 downto 16); |
else |
data_read_var(15 downto 0) := mem_data_r(15 downto 0); |
end if; |
if mem_source = MEM_READ16 or data_read_var(15) = '0' then |
data_read_var(31 downto 16) := ZERO(31 downto 16); |
else |
data_read_var(31 downto 16) := ONES(31 downto 16); |
end if; |
|
when MEM_READ8 | MEM_READ8S => |
bits := address_in(1 downto 0) xor ENDIAN_MODE; |
case bits is |
when "00" => data_read_var(7 downto 0) := mem_data_r(31 downto 24); |
when "01" => data_read_var(7 downto 0) := mem_data_r(23 downto 16); |
when "10" => data_read_var(7 downto 0) := mem_data_r(15 downto 8); |
when others => data_read_var(7 downto 0) := mem_data_r(7 downto 0); |
end case; |
if mem_source = MEM_READ8 or data_read_var(7) = '0' then |
data_read_var(31 downto 8) := ZERO(31 downto 8); |
else |
data_read_var(31 downto 8) := ONES(31 downto 8); |
end if; |
|
when MEM_WRITE32 => |
data_write_var := data_write; |
byte_sel_var := "1111"; |
|
when MEM_WRITE16 => |
data_write_var := data_write(15 downto 0) & data_write(15 downto 0); |
if address_in(1) = ENDIAN_MODE(1) then |
byte_sel_var := "1100"; |
else |
byte_sel_var := "0011"; |
end if; |
|
when MEM_WRITE8 => |
data_write_var := data_write(7 downto 0) & data_write(7 downto 0) & |
data_write(7 downto 0) & data_write(7 downto 0); |
bits := address_in(1 downto 0) xor ENDIAN_MODE; |
case bits is |
when "00" => |
byte_sel_var := "1000"; |
when "01" => |
byte_sel_var := "0100"; |
when "10" => |
byte_sel_var := "0010"; |
when others => |
byte_sel_var := "0001"; |
end case; |
|
when others => |
end case; |
|
if mem_source = MEM_FETCH then --opcode fetch |
address_var := address_pc; |
opcode_next := mem_data_r; |
mem_state_next := STATE_ADDR; |
else |
if mem_state_reg = STATE_ADDR then |
if pause_in = '0' then |
address_var := address_in(31 downto 2); |
mem_state_next := STATE_ACCESS; |
pause_var := '1'; |
else |
address_var := address_pc; |
byte_sel_var := "0000"; |
end if; |
else --STATE_ACCESS |
if pause_in = '0' then |
address_var := address_pc; |
opcode_next := next_opcode_reg; |
mem_state_next := STATE_ADDR; |
byte_sel_var := "0000"; |
else |
address_var := address_in(31 downto 2); |
byte_sel_var := "0000"; |
end if; |
end if; |
end if; |
|
if nullify_op = '1' and pause_in = '0' then |
opcode_next := ZERO; --NOP after beql |
end if; |
|
if reset_in = '1' then |
mem_state_reg <= STATE_ADDR; |
opcode_reg <= ZERO; |
next_opcode_reg <= ZERO; |
elsif rising_edge(clk) then |
if pause_in = '0' then |
mem_state_reg <= mem_state_next; |
opcode_reg <= opcode_next; |
if mem_state_reg = STATE_ADDR then |
next_opcode_reg <= mem_data_r; |
end if; |
end if; |
end if; |
|
mem_address <= address_var; |
opcode_out <= opcode_reg; |
data_read <= data_read_var; |
pause_out <= pause_var; |
mem_data_w <= data_write_var; |
mem_byte_we <= byte_sel_var; |
|
end process; --data_proc |
|
end; --architecture logic |
/tbench.vhd
0,0 → 1,69
--------------------------------------------------------------------- |
-- TITLE: Test Bench |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 4/21/01 |
-- FILENAME: tbench.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- This entity provides a test bench for testing the Plasma CPU core. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
entity tbench is |
end; --entity tbench |
|
architecture logic of tbench is |
constant memory_type : string := |
"TRI_PORT_X"; |
-- "DUAL_PORT_"; |
-- "ALTERA_LPM"; |
-- "XILINX_16X"; |
|
constant log_file : string := |
-- "UNUSED"; |
"output.txt"; |
|
signal clk : std_logic := '1'; |
signal reset : std_logic := '1'; |
signal interrupt : std_logic := '0'; |
signal mem_write : std_logic; |
signal mem_address : std_logic_vector(31 downto 2); |
signal mem_data : std_logic_vector(31 downto 0); |
signal mem_pause : std_logic := '0'; |
signal mem_byte_sel: std_logic_vector(3 downto 0); |
--signal uart_read : std_logic; |
signal uart_write : std_logic; |
signal data_read : std_logic_vector(31 downto 0); |
begin --architecture |
--Uncomment the line below to test interrupts |
interrupt <= '1' after 20 us when interrupt = '0' else '0' after 445 ns; |
|
clk <= not clk after 50 ns; |
reset <= '0' after 500 ns; |
--mem_pause <= not mem_pause after 100 ns; |
--uart_read <= '0'; |
data_read <= interrupt & ZERO(30 downto 0); |
|
u1_plasma: plasma |
generic map (memory_type => memory_type, |
log_file => log_file) |
PORT MAP ( |
clk => clk, |
reset => reset, |
uart_read => uart_write, |
uart_write => uart_write, |
|
address => mem_address, |
data_write => mem_data, |
data_read => data_read, |
write_byte_enable => mem_byte_sel, |
mem_pause_in => mem_pause, |
|
gpio0_out => open, |
gpioA_in => data_read); |
|
end; --architecture logic |
/shifter.vhd
0,0 → 1,65
--------------------------------------------------------------------- |
-- TITLE: Shifter Unit |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- Matthias Gruenewald |
-- DATE CREATED: 2/2/01 |
-- FILENAME: shifter.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the 32-bit shifter unit. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
entity shifter is |
generic(shifter_type : string := "DEFAULT"); |
port(value : in std_logic_vector(31 downto 0); |
shift_amount : in std_logic_vector(4 downto 0); |
shift_func : in shift_function_type; |
c_shift : out std_logic_vector(31 downto 0)); |
end; --entity shifter |
|
architecture logic of shifter is |
-- type shift_function_type is ( |
-- shift_nothing, shift_left_unsigned, |
-- shift_right_signed, shift_right_unsigned); |
|
signal shift1L, shift2L, shift4L, shift8L, shift16L : std_logic_vector(31 downto 0); |
signal shift1R, shift2R, shift4R, shift8R, shift16R : std_logic_vector(31 downto 0); |
signal fills : std_logic_vector(31 downto 16); |
|
begin |
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; |
shift4L <= shift2L(27 downto 0) & "0000" when shift_amount(2) = '1' else shift2L; |
shift8L <= shift4L(23 downto 0) & "00000000" when shift_amount(3) = '1' else shift4L; |
shift16L <= shift8L(15 downto 0) & ZERO(15 downto 0) when shift_amount(4) = '1' else shift8L; |
|
shift1R <= fills(31) & value(31 downto 1) when shift_amount(0) = '1' else value; |
shift2R <= fills(31 downto 30) & shift1R(31 downto 2) when shift_amount(1) = '1' else shift1R; |
shift4R <= fills(31 downto 28) & shift2R(31 downto 4) when shift_amount(2) = '1' else shift2R; |
shift8R <= fills(31 downto 24) & shift4R(31 downto 8) when shift_amount(3) = '1' else shift4R; |
shift16R <= fills(31 downto 16) & shift8R(31 downto 16) when shift_amount(4) = '1' else shift8R; |
|
GENERIC_SHIFTER: if shifter_type = "DEFAULT" generate |
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; |
end generate; |
|
AREA_OPTIMIZED_SHIFTER: if shifter_type /= "DEFAULT" 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'); |
end generate; |
|
end; --architecture logic |
|
/pipeline.vhd
0,0 → 1,129
--------------------------------------------------------------------- |
-- TITLE: Pipeline |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 6/24/02 |
-- FILENAME: pipeline.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Controls the three stage pipeline by delaying the signals: |
-- a_bus, b_bus, alu/shift/mult_func, c_source, and rs_index. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
--Note: sigD <= sig after rising_edge(clk) |
entity pipeline is |
port(clk : in std_logic; |
reset : in std_logic; |
a_bus : in std_logic_vector(31 downto 0); |
a_busD : out std_logic_vector(31 downto 0); |
b_bus : in std_logic_vector(31 downto 0); |
b_busD : out std_logic_vector(31 downto 0); |
alu_func : in alu_function_type; |
alu_funcD : out alu_function_type; |
shift_func : in shift_function_type; |
shift_funcD : out shift_function_type; |
mult_func : in mult_function_type; |
mult_funcD : out mult_function_type; |
reg_dest : in std_logic_vector(31 downto 0); |
reg_destD : out std_logic_vector(31 downto 0); |
rd_index : in std_logic_vector(5 downto 0); |
rd_indexD : out std_logic_vector(5 downto 0); |
|
rs_index : in std_logic_vector(5 downto 0); |
rt_index : in std_logic_vector(5 downto 0); |
pc_source : in pc_source_type; |
mem_source : in mem_source_type; |
a_source : in a_source_type; |
b_source : in b_source_type; |
c_source : in c_source_type; |
c_bus : in std_logic_vector(31 downto 0); |
pause_any : in std_logic; |
pause_pipeline : out std_logic); |
end; --entity pipeline |
|
architecture logic of pipeline is |
signal rd_index_reg : std_logic_vector(5 downto 0); |
signal reg_dest_reg : std_logic_vector(31 downto 0); |
signal reg_dest_delay : std_logic_vector(31 downto 0); |
signal c_source_reg : c_source_type; |
signal pause_enable_reg : std_logic; |
begin |
|
--When operating in three stage pipeline mode, the following signals |
--are delayed by one clock cycle: a_bus, b_bus, alu/shift/mult_func, |
--c_source, and rd_index. |
pipeline3: process(clk, reset, a_bus, b_bus, alu_func, shift_func, mult_func, |
rd_index, rd_index_reg, pause_any, pause_enable_reg, |
rs_index, rt_index, |
pc_source, mem_source, a_source, b_source, c_source, c_source_reg, |
reg_dest, reg_dest_reg, reg_dest_delay, c_bus) |
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 |
pause_mult_clock := '1'; |
else |
pause_mult_clock := '0'; |
end if; |
|
freeze_pipeline := not (pause_mult_clock and pause_enable_reg) and pause_any; |
pause_pipeline <= pause_mult_clock and pause_enable_reg; |
rd_indexD <= rd_index_reg; |
|
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 |
end if; |
reg_destD <= reg_dest_delay; |
|
if reset = '1' then |
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_busD <= a_bus; |
else |
a_busD <= reg_dest_delay; --rs from previous operation (bypass stage) |
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_busD <= b_bus; |
else |
b_busD <= reg_dest_delay; --rt from previous operation |
end if; |
|
alu_funcD <= alu_func; |
shift_funcD <= shift_func; |
mult_funcD <= mult_func; |
reg_dest_reg <= reg_dest; |
c_source_reg <= c_source; |
rd_index_reg <= rd_index; |
end if; |
|
if pause_enable_reg = '0' and pause_any = '0' then |
pause_enable_reg <= '1'; --enable pause_pipeline |
elsif pause_mult_clock = '1' then |
pause_enable_reg <= '0'; --disable pause_pipeline |
end if; |
end if; |
|
end process; --pipeline3 |
|
end; --logic |
/code.txt
0,0 → 1,657
3c1c0000 |
379c8a30 |
3c040000 |
34840a40 |
3c050000 |
34a50a44 |
3c1d0000 |
37bd0c40 |
ac800000 |
0085182a |
1460fffd |
24840004 |
0c0001d4 |
00000000 |
0800000e |
23bdff98 |
afa10010 |
afa20014 |
afa30018 |
afa4001c |
afa50020 |
afa60024 |
afa70028 |
afa8002c |
afa90030 |
afaa0034 |
afab0038 |
afac003c |
afad0040 |
afae0044 |
afaf0048 |
afb8004c |
afb90050 |
afbf0054 |
401a7000 |
235afffc |
afba0058 |
0000d810 |
afbb005c |
0000d812 |
afbb0060 |
3c052000 |
8ca40020 |
8ca60010 |
0c000209 |
00862024 |
8fa10010 |
8fa20014 |
8fa30018 |
8fa4001c |
8fa50020 |
8fa60024 |
8fa70028 |
8fa8002c |
8fa90030 |
8faa0034 |
8fab0038 |
8fac003c |
8fad0040 |
8fae0044 |
8faf0048 |
8fb8004c |
8fb90050 |
8fbf0054 |
8fba0058 |
8fbb005c |
03600011 |
8fbb0060 |
03600013 |
23bd0068 |
341b0001 |
03400008 |
409b6000 |
40026000 |
03e00008 |
40846000 |
3c050000 |
24a5015c |
8ca60000 |
ac06003c |
8ca60004 |
ac060040 |
8ca60008 |
ac060044 |
8ca6000c |
03e00008 |
ac060048 |
3c1a1000 |
375a003c |
03400008 |
00000000 |
ac900000 |
ac910004 |
ac920008 |
ac93000c |
ac940010 |
ac950014 |
ac960018 |
ac97001c |
ac9e0020 |
ac9c0024 |
ac9d0028 |
ac9f002c |
03e00008 |
34020000 |
8c900000 |
8c910004 |
8c920008 |
8c93000c |
8c940010 |
8c950014 |
8c960018 |
8c97001c |
8c9e0020 |
8c9c0024 |
8c9d0028 |
8c9f002c |
03e00008 |
34a20000 |
00850019 |
00001012 |
00002010 |
03e00008 |
acc40000 |
3c020000 |
24420a40 |
a0400008 |
24050007 |
00403825 |
3083000f |
2862000a |
10400003 |
00a73021 |
10000002 |
24620030 |
24620037 |
a0c20000 |
24a5ffff |
04a1fff6 |
00042102 |
3c020000 |
03e00008 |
24420a40 |
3c020000 |
24420a50 |
a040000a |
00803025 |
24050009 |
00404025 |
3c07cccc |
34e7cccd |
00c70019 |
00a82021 |
24a5ffff |
00004810 |
000918c2 |
00031080 |
00431021 |
00021040 |
00c21023 |
24420030 |
a0820000 |
04a1fff4 |
00603025 |
3c020000 |
03e00008 |
24420a50 |
27bdffe0 |
afbf0018 |
afb10014 |
afb00010 |
0c00008f |
00808825 |
0c0001ee |
00402025 |
3c040000 |
0c0001ee |
2484097c |
3c023b9a |
3442c9ff |
0051102b |
1040001e |
3c030004 |
34634b83 |
00111242 |
00430019 |
3c030000 |
246309c8 |
00002810 |
000581c2 |
00101080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
3c040000 |
0c0001ee |
24840980 |
00101140 |
00501023 |
00021080 |
00501023 |
00021100 |
00501021 |
000210c0 |
00501023 |
00021940 |
00621823 |
00031880 |
00701821 |
00031a40 |
02238823 |
3c0205f5 |
3442e0ff |
0051102b |
10400023 |
3c0255e6 |
34423b89 |
02220019 |
3c030000 |
246309c8 |
00002810 |
00058642 |
00101080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
3c040000 |
0c0001ee |
2484098c |
00101040 |
00501021 |
00021180 |
00501023 |
00021080 |
00501023 |
00021100 |
00501023 |
00021140 |
00501021 |
00021200 |
02228823 |
3c02000f |
3442423f |
0051102b |
14400005 |
3c020131 |
3c040000 |
0c0001ee |
24840998 |
3c020131 |
34422cff |
0051102b |
10400021 |
3c026b5f |
3442ca6b |
02220019 |
3c030000 |
246309c8 |
00002810 |
00058582 |
26020014 |
00021080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
0c0001dd |
24040020 |
00101940 |
00701823 |
00031180 |
00431023 |
000210c0 |
00501021 |
00021880 |
00431021 |
000211c0 |
02228823 |
3c02000f |
3442423f |
0051102b |
14400009 |
3c02431b |
3c040000 |
0c0001ee |
24840998 |
3c02000f |
3442423f |
0051102b |
10400017 |
3c02431b |
3442de83 |
02220019 |
3c030000 |
246309c8 |
00002810 |
00058482 |
00101080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
3c040000 |
0c0001ee |
248409a4 |
00101940 |
00701823 |
00031180 |
00431023 |
000210c0 |
00501021 |
00021180 |
02228823 |
3c020001 |
3442869f |
0051102b |
10400020 |
3c030a7c |
34635ac5 |
00111142 |
00430019 |
3c030000 |
246309c8 |
00002810 |
000581c2 |
00101080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
3c040000 |
0c0001ee |
2484098c |
00101040 |
00501021 |
00021980 |
00431021 |
00021080 |
00501021 |
00021080 |
00501021 |
00021140 |
02228823 |
2e2203e8 |
10400005 |
2e224e20 |
3c040000 |
0c0001ee |
248409b0 |
2e224e20 |
1440001f |
2e2203e8 |
3c02d1b7 |
34421759 |
02220019 |
3c030000 |
246309c8 |
00002810 |
00058342 |
26020014 |
00021080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
0c0001dd |
24040020 |
00101080 |
00501021 |
000210c0 |
00501023 |
00021100 |
00501021 |
00021100 |
02228823 |
2e2203e8 |
10400008 |
3c021062 |
3c040000 |
0c0001ee |
248409b0 |
2e2203e8 |
14400017 |
2e220064 |
3c021062 |
34424dd3 |
02220019 |
3c030000 |
246309c8 |
00002810 |
00058182 |
00101080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
3c040000 |
0c0001ee |
248409bc |
00101140 |
00501023 |
00021080 |
00501021 |
000210c0 |
02228823 |
2e220064 |
14400017 |
2e220014 |
3c0251eb |
3442851f |
02220019 |
3c030000 |
246309c8 |
00002810 |
00058142 |
00101080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
3c040000 |
0c0001ee |
2484098c |
00101040 |
00501021 |
000210c0 |
00501021 |
00021080 |
02228823 |
2e220014 |
14400014 |
3c030000 |
3c02cccc |
3442cccd |
02220019 |
246309c8 |
00002810 |
000580c2 |
26020014 |
00021080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
0c0001dd |
24040020 |
00101080 |
00501021 |
00021040 |
02228823 |
3c030000 |
246309c8 |
00111080 |
00431021 |
8c440000 |
0c0001ee |
00000000 |
0c0001dd |
2404000d |
0c0001dd |
2404000a |
8fbf0018 |
8fb10014 |
8fb00010 |
03e00008 |
27bd0020 |
27bdffe8 |
afbf0014 |
afb00010 |
24100003 |
0c0000a7 |
02002025 |
00101040 |
1000fffc |
02028021 |
3c022000 |
34420020 |
8c420000 |
00000000 |
30420002 |
14400008 |
3c022000 |
3c032000 |
34630020 |
8c620000 |
00000000 |
30420002 |
1040fffc |
3c022000 |
ac440000 |
03e00008 |
00000000 |
27bdffe0 |
afb00010 |
00808025 |
afbf0018 |
afb10014 |
92020000 |
00000000 |
1040000d |
2411000a |
00000000 |
14510003 |
00000000 |
0c0001dd |
2404000d |
92040000 |
0c0001dd |
26100001 |
92020000 |
00000000 |
1440fff5 |
00000000 |
8fbf0018 |
8fb10014 |
8fb00010 |
00001025 |
03e00008 |
27bd0020 |
27bdffe8 |
afbf0010 |
0c0001dd |
24040049 |
8fbf0010 |
00000000 |
03e00008 |
27bd0018 |
3c022000 |
34420020 |
8c420000 |
03e00008 |
30420001 |
27bdffe8 |
afbf0010 |
0c000211 |
00000000 |
1040fffd |
3c022000 |
8c420000 |
8fbf0010 |
00000000 |
03e00008 |
27bd0018 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
6e696e65 |
74790000 |
65696768 |
74790000 |
73657665 |
6e747900 |
73697874 |
79000000 |
66696674 |
79000000 |
666f7274 |
79000000 |
74686972 |
74790000 |
7477656e |
74790000 |
6e696e65 |
7465656e |
00000000 |
65696768 |
7465656e |
00000000 |
73657665 |
6e746565 |
6e000000 |
73697874 |
65656e00 |
66696674 |
65656e00 |
666f7572 |
7465656e |
00000000 |
74686972 |
7465656e |
00000000 |
7477656c |
76650000 |
656c6576 |
656e0000 |
74656e00 |
6e696e65 |
00000000 |
65696768 |
74000000 |
73657665 |
6e000000 |
73697800 |
66697665 |
00000000 |
666f7572 |
00000000 |
74687265 |
65000000 |
74776f00 |
6f6e6500 |
00000000 |
3a200000 |
2062696c |
6c696f6e |
20000000 |
2068756e |
64726564 |
20000000 |
6d696c6c |
696f6e20 |
00000000 |
206d696c |
6c696f6e |
20000000 |
74686f75 |
73616e64 |
20000000 |
2074686f |
7573616e |
64200000 |
00000978 |
00000974 |
00000970 |
00000968 |
00000960 |
00000958 |
00000954 |
0000094c |
00000944 |
0000093c |
00000938 |
00000930 |
00000928 |
0000091c |
00000910 |
00000908 |
00000900 |
000008f4 |
000008e8 |
000008dc |
00000978 |
00000938 |
000008d4 |
000008cc |
000008c4 |
000008bc |
000008b4 |
000008ac |
000008a4 |
0000089c |
00000000 |
/mlite_pack.vhd
0,0 → 1,487
--------------------------------------------------------------------- |
-- TITLE: Plasma Misc. Package |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/15/01 |
-- FILENAME: mlite_pack.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Data types, constants, and add functions needed for the Plasma CPU. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
|
package mlite_pack is |
constant ZERO : std_logic_vector(31 downto 0) := |
"00000000000000000000000000000000"; |
constant ONES : std_logic_vector(31 downto 0) := |
"11111111111111111111111111111111"; |
--make HIGH_Z equal to ZERO if compiler complains |
constant HIGH_Z : std_logic_vector(31 downto 0) := |
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; |
|
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"; |
|
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"; |
|
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"; |
|
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"; |
|
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"; |
|
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"; |
|
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"; |
|
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_NO : branch_function_type := "111"; |
|
-- 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"; |
|
function bv_adder(a : in std_logic_vector; |
b : in std_logic_vector; |
do_add: in std_logic) return std_logic_vector; |
function bv_negate(a : in std_logic_vector) return std_logic_vector; |
function bv_increment(a : in std_logic_vector(31 downto 2) |
) return std_logic_vector; |
function bv_inc(a : in std_logic_vector |
) return std_logic_vector; |
|
-- For Altera |
COMPONENT lpm_add_sub |
GENERIC ( |
lpm_width : NATURAL; |
lpm_direction : STRING := "UNUSED"; |
lpm_type : STRING; |
lpm_hint : STRING); |
PORT ( |
dataa : IN STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0); |
add_sub : IN STD_LOGIC ; |
datab : IN STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0); |
result : OUT STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0)); |
END COMPONENT; |
|
-- For Altera |
COMPONENT lpm_ram_dp |
GENERIC ( |
lpm_width : NATURAL; |
lpm_widthad : NATURAL; |
rden_used : STRING; |
intended_device_family : STRING; |
lpm_indata : STRING; |
lpm_wraddress_control : STRING; |
lpm_rdaddress_control : STRING; |
lpm_outdata : STRING; |
use_eab : STRING; |
lpm_type : STRING); |
PORT ( |
wren : IN STD_LOGIC ; |
wrclock : IN STD_LOGIC ; |
q : OUT STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0); |
data : IN STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0); |
rdaddress : IN STD_LOGIC_VECTOR (lpm_widthad-1 DOWNTO 0); |
wraddress : IN STD_LOGIC_VECTOR (lpm_widthad-1 DOWNTO 0)); |
END COMPONENT; |
|
-- For Altera |
component LPM_RAM_DQ |
generic ( |
LPM_WIDTH : natural; -- MUST be greater than 0 |
LPM_WIDTHAD : natural; -- MUST be greater than 0 |
LPM_NUMWORDS : natural := 0; |
LPM_INDATA : string := "REGISTERED"; |
LPM_ADDRESS_CONTROL: string := "REGISTERED"; |
LPM_OUTDATA : string := "REGISTERED"; |
LPM_FILE : string := "UNUSED"; |
LPM_TYPE : string := "LPM_RAM_DQ"; |
USE_EAB : string := "OFF"; |
INTENDED_DEVICE_FAMILY : string := "UNUSED"; |
LPM_HINT : string := "UNUSED"); |
port ( |
DATA : in std_logic_vector(LPM_WIDTH-1 downto 0); |
ADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0); |
INCLOCK : in std_logic := '0'; |
OUTCLOCK : in std_logic := '0'; |
WE : in std_logic; |
Q : out std_logic_vector(LPM_WIDTH-1 downto 0)); |
end component; |
|
-- For Xilinx |
component ramb4_s16_s16 |
port ( |
clka : in std_logic; |
rsta : in std_logic; |
addra : in std_logic_vector; |
dia : in std_logic_vector; |
ena : in std_logic; |
wea : in std_logic; |
doa : out std_logic_vector; |
|
clkb : in std_logic; |
rstb : in std_logic; |
addrb : in std_logic_vector; |
dib : in std_logic_vector; |
enb : in std_logic; |
web : in std_logic); |
end component; |
|
-- For Xilinx |
component reg_file_dp_ram |
port ( |
addra : IN std_logic_VECTOR(4 downto 0); |
addrb : IN std_logic_VECTOR(4 downto 0); |
clka : IN std_logic; |
clkb : IN std_logic; |
dinb : IN std_logic_VECTOR(31 downto 0); |
douta : OUT std_logic_VECTOR(31 downto 0); |
web : IN std_logic); |
end component; |
|
-- For Xilinx |
component reg_file_dp_ram_xc4000xla |
port ( |
A : IN std_logic_vector(4 DOWNTO 0); |
DI : IN std_logic_vector(31 DOWNTO 0); |
WR_EN : IN std_logic; |
WR_CLK : IN std_logic; |
DPRA : IN std_logic_vector(4 DOWNTO 0); |
SPO : OUT std_logic_vector(31 DOWNTO 0); |
DPO : OUT std_logic_vector(31 DOWNTO 0)); |
end component; |
|
component pc_next |
port(clk : in std_logic; |
reset_in : in std_logic; |
pc_new : in std_logic_vector(31 downto 2); |
take_branch : in std_logic; |
pause_in : in std_logic; |
opcode25_0 : in std_logic_vector(25 downto 0); |
pc_source : in pc_source_type; |
pc_future : out std_logic_vector(31 downto 2); |
pc_current : out std_logic_vector(31 downto 2); |
pc_plus4 : out std_logic_vector(31 downto 2)); |
end component; |
|
component mem_ctrl |
port(clk : in std_logic; |
reset_in : in std_logic; |
pause_in : in std_logic; |
nullify_op : in std_logic; |
address_pc : in std_logic_vector(31 downto 2); |
opcode_out : out std_logic_vector(31 downto 0); |
|
address_in : in std_logic_vector(31 downto 0); |
mem_source : in mem_source_type; |
data_write : in std_logic_vector(31 downto 0); |
data_read : out std_logic_vector(31 downto 0); |
pause_out : out std_logic; |
|
mem_address : out std_logic_vector(31 downto 2); |
mem_data_w : out std_logic_vector(31 downto 0); |
mem_data_r : in std_logic_vector(31 downto 0); |
mem_byte_we : out std_logic_vector(3 downto 0)); |
end component; |
|
component control |
port(opcode : in std_logic_vector(31 downto 0); |
intr_signal : in std_logic; |
rs_index : out std_logic_vector(5 downto 0); |
rt_index : out std_logic_vector(5 downto 0); |
rd_index : out std_logic_vector(5 downto 0); |
imm_out : out std_logic_vector(15 downto 0); |
alu_func : out alu_function_type; |
shift_func : out shift_function_type; |
mult_func : out mult_function_type; |
branch_func : out branch_function_type; |
a_source_out : out a_source_type; |
b_source_out : out b_source_type; |
c_source_out : out c_source_type; |
pc_source_out: out pc_source_type; |
mem_source_out:out mem_source_type); |
end component; |
|
component reg_bank |
generic(memory_type : string := "XILINX_16X"); |
port(clk : in std_logic; |
reset_in : in std_logic; |
pause : in std_logic; |
rs_index : in std_logic_vector(5 downto 0); |
rt_index : in std_logic_vector(5 downto 0); |
rd_index : in std_logic_vector(5 downto 0); |
reg_source_out : out std_logic_vector(31 downto 0); |
reg_target_out : out std_logic_vector(31 downto 0); |
reg_dest_new : in std_logic_vector(31 downto 0); |
intr_enable : out std_logic); |
end component; |
|
component bus_mux |
port(imm_in : in std_logic_vector(15 downto 0); |
reg_source : in std_logic_vector(31 downto 0); |
a_mux : in a_source_type; |
a_out : out std_logic_vector(31 downto 0); |
|
reg_target : in std_logic_vector(31 downto 0); |
b_mux : in b_source_type; |
b_out : out std_logic_vector(31 downto 0); |
|
c_bus : in std_logic_vector(31 downto 0); |
c_memory : in std_logic_vector(31 downto 0); |
c_pc : in std_logic_vector(31 downto 2); |
c_pc_plus4 : in std_logic_vector(31 downto 2); |
c_mux : in c_source_type; |
reg_dest_out : out std_logic_vector(31 downto 0); |
|
branch_func : in branch_function_type; |
take_branch : out std_logic); |
end component; |
|
component alu |
generic(alu_type : string := "DEFAULT"); |
port(a_in : in std_logic_vector(31 downto 0); |
b_in : in std_logic_vector(31 downto 0); |
alu_function : in alu_function_type; |
c_alu : out std_logic_vector(31 downto 0)); |
end component; |
|
component shifter |
generic(shifter_type : string := "DEFAULT" ); |
port(value : in std_logic_vector(31 downto 0); |
shift_amount : in std_logic_vector(4 downto 0); |
shift_func : in shift_function_type; |
c_shift : out std_logic_vector(31 downto 0)); |
end component; |
|
component mult |
generic(mult_type : string := "DEFAULT"); |
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); |
pause_out : out std_logic); |
end component; |
|
component pipeline |
port(clk : in std_logic; |
reset : in std_logic; |
a_bus : in std_logic_vector(31 downto 0); |
a_busD : out std_logic_vector(31 downto 0); |
b_bus : in std_logic_vector(31 downto 0); |
b_busD : out std_logic_vector(31 downto 0); |
alu_func : in alu_function_type; |
alu_funcD : out alu_function_type; |
shift_func : in shift_function_type; |
shift_funcD : out shift_function_type; |
mult_func : in mult_function_type; |
mult_funcD : out mult_function_type; |
reg_dest : in std_logic_vector(31 downto 0); |
reg_destD : out std_logic_vector(31 downto 0); |
rd_index : in std_logic_vector(5 downto 0); |
rd_indexD : out std_logic_vector(5 downto 0); |
|
rs_index : in std_logic_vector(5 downto 0); |
rt_index : in std_logic_vector(5 downto 0); |
pc_source : in pc_source_type; |
mem_source : in mem_source_type; |
a_source : in a_source_type; |
b_source : in b_source_type; |
c_source : in c_source_type; |
c_bus : in std_logic_vector(31 downto 0); |
pause_any : in std_logic; |
pause_pipeline : out std_logic); |
end component; |
|
component mlite_cpu |
generic(memory_type : string := "XILINX_16X"; --ALTERA_LPM, or DUAL_PORT_ |
mult_type : string := "DEFAULT"; |
shifter_type : string := "DEFAULT"; |
alu_type : string := "DEFAULT"; |
pipeline_stages : natural := 3); --3 or 4 |
port(clk : in std_logic; |
reset_in : in std_logic; |
intr_in : in std_logic; |
|
mem_address : out std_logic_vector(31 downto 0); |
mem_data_w : out std_logic_vector(31 downto 0); |
mem_data_r : in std_logic_vector(31 downto 0); |
mem_byte_we : out std_logic_vector(3 downto 0); |
mem_pause : in std_logic); |
end component; |
|
component ram |
generic(memory_type : string := "DEFAULT"); |
port(clk : in std_logic; |
enable : in std_logic; |
write_byte_enable : in std_logic_vector(3 downto 0); |
address : in std_logic_vector(31 downto 2); |
data_write : in std_logic_vector(31 downto 0); |
data_read : out std_logic_vector(31 downto 0)); |
end component; --ram |
|
component uart |
generic(log_file : string := "UNUSED"); |
port(clk : in std_logic; |
reset : in std_logic; |
enable_read : in std_logic; |
enable_write : in std_logic; |
data_in : in std_logic_vector(7 downto 0); |
data_out : out std_logic_vector(7 downto 0); |
uart_read : in std_logic; |
uart_write : out std_logic; |
busy_write : out std_logic; |
data_avail : out std_logic); |
end component; --uart |
|
component plasma |
generic(memory_type : string := "XILINX_X16"; --"DUAL_PORT_" "ALTERA_LPM"; |
log_file : string := "UNUSED"); |
port(clk : in std_logic; |
reset : in std_logic; |
uart_write : out std_logic; |
uart_read : in std_logic; |
|
address : out std_logic_vector(31 downto 2); |
data_write : out std_logic_vector(31 downto 0); |
data_read : in std_logic_vector(31 downto 0); |
write_byte_enable : out std_logic_vector(3 downto 0); |
mem_pause_in : in std_logic; |
|
gpio0_out : out std_logic_vector(31 downto 0); |
gpioA_in : in std_logic_vector(31 downto 0)); |
end component; --plasma |
|
end; --package mlite_pack |
|
|
package body mlite_pack is |
|
function bv_adder(a : in std_logic_vector; |
b : in std_logic_vector; |
do_add: in std_logic) return std_logic_vector is |
variable carry_in : std_logic; |
variable bb : std_logic_vector(a'length-1 downto 0); |
variable result : std_logic_vector(a'length downto 0); |
begin |
if do_add = '1' then |
bb := b; |
carry_in := '0'; |
else |
bb := not b; |
carry_in := '1'; |
end if; |
for index in 0 to a'length-1 loop |
result(index) := a(index) xor bb(index) xor carry_in; |
carry_in := (carry_in and (a(index) or bb(index))) or |
(a(index) and bb(index)); |
end loop; |
result(a'length) := carry_in xnor do_add; |
return result; |
end; --function |
|
|
function bv_negate(a : in std_logic_vector) return std_logic_vector is |
variable carry_in : std_logic; |
variable not_a : std_logic_vector(a'length-1 downto 0); |
variable result : std_logic_vector(a'length-1 downto 0); |
begin |
not_a := not a; |
carry_in := '1'; |
for index in a'reverse_range loop |
result(index) := not_a(index) xor carry_in; |
carry_in := carry_in and not_a(index); |
end loop; |
return result; |
end; --function |
|
|
function bv_increment(a : in std_logic_vector(31 downto 2) |
) return std_logic_vector is |
variable carry_in : std_logic; |
variable result : std_logic_vector(31 downto 2); |
begin |
carry_in := '1'; |
for index in 2 to 31 loop |
result(index) := a(index) xor carry_in; |
carry_in := a(index) and carry_in; |
end loop; |
return result; |
end; --function |
|
|
function bv_inc(a : in std_logic_vector |
) return std_logic_vector is |
variable carry_in : std_logic; |
variable result : std_logic_vector(a'length-1 downto 0); |
begin |
carry_in := '1'; |
for index in 0 to a'length-1 loop |
result(index) := a(index) xor carry_in; |
carry_in := a(index) and carry_in; |
end loop; |
return result; |
end; --function |
|
end; --package body |
|
|
/reg_bank.vhd
0,0 → 1,450
--------------------------------------------------------------------- |
-- TITLE: Register Bank |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/2/01 |
-- FILENAME: reg_bank.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements a register bank with 32 registers that are 32-bits wide. |
-- There are two read-ports and one write port. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
use work.mlite_pack.all; |
--Uncomment following two lines for Xilinx RAM16X1D |
library UNISIM; --Xilinx |
use UNISIM.vcomponents.all; --Xilinx |
|
entity reg_bank is |
generic(memory_type : string := "XILINX_16X"); |
port(clk : in std_logic; |
reset_in : in std_logic; |
pause : in std_logic; |
rs_index : in std_logic_vector(5 downto 0); |
rt_index : in std_logic_vector(5 downto 0); |
rd_index : in std_logic_vector(5 downto 0); |
reg_source_out : out std_logic_vector(31 downto 0); |
reg_target_out : out std_logic_vector(31 downto 0); |
reg_dest_new : in std_logic_vector(31 downto 0); |
intr_enable : out std_logic); |
end; --entity reg_bank |
|
|
-------------------------------------------------------------------- |
-- The ram_block architecture attempts to use TWO dual-port memories. |
-- Different FPGAs and ASICs need different implementations. |
-- Choose one of the RAM implementations below. |
-- I need feedback on this section! |
-------------------------------------------------------------------- |
architecture ram_block of reg_bank is |
signal intr_enable_reg : std_logic; |
type ram_type is array(31 downto 0) of std_logic_vector(31 downto 0); |
|
--controls access to dual-port memories |
signal addr_read1, addr_read2 : std_logic_vector(4 downto 0); |
signal addr_write : std_logic_vector(4 downto 0); |
signal data_out1, data_out2 : std_logic_vector(31 downto 0); |
signal write_enable : std_logic; |
|
begin |
|
reg_proc: process(clk, rs_index, rt_index, rd_index, reg_dest_new, |
intr_enable_reg, data_out1, data_out2, reset_in, pause) |
begin |
--setup for first dual-port memory |
if rs_index = "101110" then --reg_epc CP0 14 |
addr_read1 <= "00000"; |
else |
addr_read1 <= rs_index(4 downto 0); |
end if; |
case rs_index is |
when "000000" => reg_source_out <= ZERO; |
when "101100" => reg_source_out <= ZERO(31 downto 1) & intr_enable_reg; |
--interrupt vector address = 0x3c |
when "111111" => reg_source_out <= ZERO(31 downto 8) & "00111100"; |
when others => reg_source_out <= data_out1; |
end case; |
|
--setup for second dual-port memory |
addr_read2 <= rt_index(4 downto 0); |
case rt_index is |
when "000000" => reg_target_out <= ZERO; |
when others => reg_target_out <= data_out2; |
end case; |
|
--setup write port for both dual-port memories |
if rd_index /= "000000" and rd_index /= "101100" and pause = '0' then |
write_enable <= '1'; |
else |
write_enable <= '0'; |
end if; |
if rd_index = "101110" then --reg_epc CP0 14 |
addr_write <= "00000"; |
else |
addr_write <= rd_index(4 downto 0); |
end if; |
|
if reset_in = '1' then |
intr_enable_reg <= '0'; |
elsif rising_edge(clk) then |
if rd_index = "101110" then --reg_epc CP0 14 |
intr_enable_reg <= '0'; --disable interrupts |
elsif rd_index = "101100" then |
intr_enable_reg <= reg_dest_new(0); |
end if; |
end if; |
|
intr_enable <= intr_enable_reg; |
end process; |
|
|
-------------------------------------------------------------- |
---- Pick only ONE of the dual-port RAM implementations below! |
-------------------------------------------------------------- |
|
-- Option #1 |
-- One tri-port RAM, two read-ports, one write-port |
-- 32 registers 32-bits wide |
tri_port_mem: |
if memory_type = "TRI_PORT_X" generate |
ram_proc: process(clk, addr_read1, addr_read2, |
addr_write, reg_dest_new, write_enable) |
variable tri_port_ram : ram_type; |
begin |
data_out1 <= tri_port_ram(conv_integer(addr_read1)); |
data_out2 <= tri_port_ram(conv_integer(addr_read2)); |
if rising_edge(clk) then |
if write_enable = '1' then |
tri_port_ram(conv_integer(addr_write)) := reg_dest_new; |
end if; |
end if; |
end process; |
end generate; --tri_port_mem |
|
|
-- Option #2 |
-- Two dual-port RAMs, each with one read-port and one write-port |
dual_port_mem: |
if memory_type = "DUAL_PORT_" generate |
ram_proc2: process(clk, addr_read1, addr_read2, |
addr_write, reg_dest_new, write_enable) |
variable dual_port_ram1 : ram_type; |
variable dual_port_ram2 : ram_type; |
begin |
data_out1 <= dual_port_ram1(conv_integer(addr_read1)); |
data_out2 <= dual_port_ram2(conv_integer(addr_read2)); |
if rising_edge(clk) then |
if write_enable = '1' then |
dual_port_ram1(conv_integer(addr_write)) := reg_dest_new; |
dual_port_ram2(conv_integer(addr_write)) := reg_dest_new; |
end if; |
end if; |
end process; |
end generate; --dual_port_mem |
|
|
-- Option #3 |
-- RAM16X1D: 16 x 1 positive edge write, asynchronous read dual-port |
-- distributed RAM for all Xilinx FPGAs |
xilinx_16x1d: |
if memory_type = "XILINX_16X" generate |
signal data_out1A, data_out1B : std_logic_vector(31 downto 0); |
signal data_out2A, data_out2B : std_logic_vector(31 downto 0); |
signal weA, weB : std_logic; |
begin |
weA <= write_enable and not addr_write(4); --lower 16 registers |
weB <= write_enable and addr_write(4); --upper 16 registers |
|
reg_loop: for i in 0 to 31 generate |
begin |
--Read port 1 lower 16 registers |
reg_bit1a : RAM16X1D |
port map ( |
WCLK => clk, -- Port A write clock input |
WE => weA, -- Port A write enable input |
A0 => addr_write(0), -- Port A address[0] input bit |
A1 => addr_write(1), -- Port A address[1] input bit |
A2 => addr_write(2), -- Port A address[2] input bit |
A3 => addr_write(3), -- Port A address[3] input bit |
D => reg_dest_new(i), -- Port A 1-bit data input |
DPRA0 => addr_read1(0), -- Port B address[0] input bit |
DPRA1 => addr_read1(1), -- Port B address[1] input bit |
DPRA2 => addr_read1(2), -- Port B address[2] input bit |
DPRA3 => addr_read1(3), -- Port B address[3] input bit |
DPO => data_out1A(i), -- Port B 1-bit data output |
SPO => open -- Port A 1-bit data output |
); |
--Read port 1 upper 16 registers |
reg_bit1b : RAM16X1D |
port map ( |
WCLK => clk, -- Port A write clock input |
WE => weB, -- Port A write enable input |
A0 => addr_write(0), -- Port A address[0] input bit |
A1 => addr_write(1), -- Port A address[1] input bit |
A2 => addr_write(2), -- Port A address[2] input bit |
A3 => addr_write(3), -- Port A address[3] input bit |
D => reg_dest_new(i), -- Port A 1-bit data input |
DPRA0 => addr_read1(0), -- Port B address[0] input bit |
DPRA1 => addr_read1(1), -- Port B address[1] input bit |
DPRA2 => addr_read1(2), -- Port B address[2] input bit |
DPRA3 => addr_read1(3), -- Port B address[3] input bit |
DPO => data_out1B(i), -- Port B 1-bit data output |
SPO => open -- Port A 1-bit data output |
); |
--Read port 2 lower 16 registers |
reg_bit2a : RAM16X1D |
port map ( |
WCLK => clk, -- Port A write clock input |
WE => weA, -- Port A write enable input |
A0 => addr_write(0), -- Port A address[0] input bit |
A1 => addr_write(1), -- Port A address[1] input bit |
A2 => addr_write(2), -- Port A address[2] input bit |
A3 => addr_write(3), -- Port A address[3] input bit |
D => reg_dest_new(i), -- Port A 1-bit data input |
DPRA0 => addr_read2(0), -- Port B address[0] input bit |
DPRA1 => addr_read2(1), -- Port B address[1] input bit |
DPRA2 => addr_read2(2), -- Port B address[2] input bit |
DPRA3 => addr_read2(3), -- Port B address[3] input bit |
DPO => data_out2A(i), -- Port B 1-bit data output |
SPO => open -- Port A 1-bit data output |
); |
--Read port 2 upper 16 registers |
reg_bit2b : RAM16X1D |
port map ( |
WCLK => clk, -- Port A write clock input |
WE => weB, -- Port A write enable input |
A0 => addr_write(0), -- Port A address[0] input bit |
A1 => addr_write(1), -- Port A address[1] input bit |
A2 => addr_write(2), -- Port A address[2] input bit |
A3 => addr_write(3), -- Port A address[3] input bit |
D => reg_dest_new(i), -- Port A 1-bit data input |
DPRA0 => addr_read2(0), -- Port B address[0] input bit |
DPRA1 => addr_read2(1), -- Port B address[1] input bit |
DPRA2 => addr_read2(2), -- Port B address[2] input bit |
DPRA3 => addr_read2(3), -- Port B address[3] input bit |
DPO => data_out2B(i), -- Port B 1-bit data output |
SPO => open -- Port A 1-bit data output |
); |
end generate; --reg_loop |
|
data_out1 <= data_out1A when addr_read1(4)='0' else data_out1B; |
data_out2 <= data_out2A when addr_read2(4)='0' else data_out2B; |
end generate; --xilinx_16x1d |
|
|
-- Option #4 |
-- Altera LPM_RAM_DP |
-- Xilinx users may need to comment out this section!!! |
altera_mem: |
if memory_type = "ALTERA_LPM" generate |
lpm_ram_dp_component1 : lpm_ram_dp |
GENERIC MAP ( |
lpm_width => 32, |
lpm_widthad => 5, |
rden_used => "FALSE", |
intended_device_family => "UNUSED", |
lpm_indata => "REGISTERED", |
lpm_wraddress_control => "REGISTERED", |
lpm_rdaddress_control => "UNREGISTERED", |
lpm_outdata => "UNREGISTERED", |
use_eab => "ON", |
lpm_type => "LPM_RAM_DP" |
) |
PORT MAP ( |
wren => write_enable, |
wrclock => clk, |
data => reg_dest_new, |
rdaddress => addr_read1, |
wraddress => addr_write, |
q => data_out1 |
); |
lpm_ram_dp_component2 : lpm_ram_dp |
GENERIC MAP ( |
lpm_width => 32, |
lpm_widthad => 5, |
rden_used => "FALSE", |
intended_device_family => "UNUSED", |
lpm_indata => "REGISTERED", |
lpm_wraddress_control => "REGISTERED", |
lpm_rdaddress_control => "UNREGISTERED", |
lpm_outdata => "UNREGISTERED", |
use_eab => "ON", |
lpm_type => "LPM_RAM_DP" |
) |
PORT MAP ( |
wren => write_enable, |
wrclock => clk, |
data => reg_dest_new, |
rdaddress => addr_read2, |
wraddress => addr_write, |
q => data_out2 |
); |
end generate; --altera_mem |
|
|
-- Option #5 |
-- dual_port_mem_coregen: |
-- if memory_type = "DUAL_PORT_XILINX" generate |
-- reg_file_dp_ram_1: reg_file_dp_ram |
-- port map ( |
-- addra => addr_read1, |
-- addrb => addr_write, |
-- clka => clk, |
-- clkb => clk, |
-- dinb => reg_dest_new, |
-- douta => data_out1, |
-- web => write_enable); |
-- |
-- reg_file_dp_ram_2: reg_file_dp_ram |
-- port map ( |
-- addra => addr_read2, |
-- addrb => addr_write, |
-- clka => clk, |
-- clkb => clk, |
-- dinb => reg_dest_new, |
-- douta => data_out2, |
-- web => write_enable); |
-- end generate; --dual_port_mem |
|
|
-- dual_port_mem_xc4000xla: if memory_type = "DUAL_PORT_XILINX_XC4000XLA" generate |
-- reg_file_dp_ram_1: reg_file_dp_ram_xc4000xla |
-- port map ( |
-- A => addr_write, |
-- DI => reg_dest_new, |
-- WR_EN => write_enable, |
-- WR_CLK => clk, |
-- DPRA => addr_read1, |
-- SPO => open, |
-- DPO => data_out1); |
-- |
-- reg_file_dp_ram_2: reg_file_dp_ram_xc4000xla |
-- port map ( |
-- A => addr_write, |
-- DI => reg_dest_new, |
-- WR_EN => write_enable, |
-- WR_CLK => clk, |
-- DPRA => addr_read2, |
-- SPO => open, |
-- DPO => data_out2); |
-- end generate; --dual_port_mem |
|
|
-- Option #6 |
-- Generic Two-Port Synchronous RAM |
-- generic_tpram can be obtained from: |
-- http://www.opencores.org/cvsweb.shtml/generic_memories/ |
-- Supports ASICs (Artisan, Avant, and Virage) and Xilinx FPGA |
-- generic_mem: |
-- if memory_type = "OPENCORES_MEM" generate |
-- bank1 : generic_tpram port map ( |
-- clk_a => clk, |
-- rst_a => '0', |
-- ce_a => '1', |
-- we_a => '0', |
-- oe_a => '1', |
-- addr_a => addr_read1, |
-- di_a => ZERO, |
-- do_a => data_out1, |
-- |
-- clk_b => clk, |
-- rst_b => '0', |
-- ce_b => '1', |
-- we_b => write_enable, |
-- oe_b => '0', |
-- addr_b => addr_write, |
-- di_a => reg_dest_new); |
-- |
-- bank2 : generic_tpram port map ( |
-- clk_a => clk, |
-- rst_a => '0', |
-- ce_a => '1', |
-- we_a => '0', |
-- oe_a => '1', |
-- addr_a => addr_read2, |
-- di_a => ZERO, |
-- do_a => data_out2, |
-- |
-- clk_b => clk, |
-- rst_b => '0', |
-- ce_b => '1', |
-- we_b => write_enable, |
-- oe_b => '0', |
-- addr_b => addr_write, |
-- di_a => reg_dest_new); |
-- end generate; --generic_mem |
|
|
-- Option #7 |
-- Xilinx mode using four 16x16 banks |
-- xilinx_mem: |
-- if memory_type = "XILINX" generate |
-- bank1_high: ramb4_s16_s16 port map ( |
-- clka => clk, |
-- rsta => sig_false, |
-- addra => addr_read1, |
-- dia => zero_sig, |
-- ena => sig_true, |
-- wea => sig_false, |
-- doa => data_out1(31 downto 16), |
-- |
-- clkb => clk, |
-- rstb => sig_false, |
-- addrb => addr_write, |
-- dib => reg_dest_new(31 downto 16), |
-- enb => sig_true, |
-- web => write_enable); |
-- |
-- bank1_low: ramb4_s16_s16 port map ( |
-- clka => clk, |
-- rsta => sig_false, |
-- addra => addr_read1, |
-- dia => zero_sig, |
-- ena => sig_true, |
-- wea => sig_false, |
-- doa => data_out1(15 downto 0), |
-- |
-- clkb => clk, |
-- rstb => sig_false, |
-- addrb => addr_write, |
-- dib => reg_dest_new(15 downto 0), |
-- enb => sig_true, |
-- web => write_enable); |
-- |
-- bank2_high: ramb4_s16_s16 port map ( |
-- clka => clk, |
-- rsta => sig_false, |
-- addra => addr_read2, |
-- dia => zero_sig, |
-- ena => sig_true, |
-- wea => sig_false, |
-- doa => data_out2(31 downto 16), |
-- |
-- clkb => clk, |
-- rstb => sig_false, |
-- addrb => addr_write, |
-- dib => reg_dest_new(31 downto 16), |
-- enb => sig_true, |
-- web => write_enable); |
-- |
-- bank2_low: ramb4_s16_s16 port map ( |
-- clka => clk, |
-- rsta => sig_false, |
-- addra => addr_read2, |
-- dia => zero_sig, |
-- ena => sig_true, |
-- wea => sig_false, |
-- doa => data_out2(15 downto 0), |
-- |
-- clkb => clk, |
-- rstb => sig_false, |
-- addrb => addr_write, |
-- dib => reg_dest_new(15 downto 0), |
-- enb => sig_true, |
-- web => write_enable); |
-- end generate; --xilinx_mem |
|
end; --architecture ram_block |
/ram_xilinx.vhd
0,0 → 1,350
--------------------------------------------------------------------- |
-- TITLE: Random Access Memory for Xilinx |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 11/06/05 |
-- FILENAME: ram_xilinx.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the RAM for Spartan 3 Xilinx FPGA |
-- |
-- Compile the MIPS C and assembly code into "text.exe". |
-- Run convert.exe to change "text.exe" to "code.txt" which |
-- will contain the hex values of the opcodes. |
-- Next run "run_image ram_xilinx.vhd code.txt ram_image.vhd", |
-- to create the "ram_image.vhd" file that will have the opcodes |
-- corectly placed inside the INIT_00 => strings. |
-- Then include ram_image.vhd in the simulation/synthesis. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_misc.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
use work.mlite_pack.all; |
library UNISIM; |
use UNISIM.vcomponents.all; |
|
entity ram is |
generic(memory_type : string := "DEFAULT"); |
port(clk : in std_logic; |
enable : in std_logic; |
write_byte_enable : in std_logic_vector(3 downto 0); |
address : in std_logic_vector(31 downto 2); |
data_write : in std_logic_vector(31 downto 0); |
data_read : out std_logic_vector(31 downto 0)); |
end; --entity ram |
|
architecture logic of ram is |
begin |
|
RAMB16_S9_inst0 : RAMB16_S9 |
generic map ( |
INIT_00 => X"000000000000000000000000000000000000000000000000000000000c080400", |
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000") |
port map ( |
DO => data_read(31 downto 24), |
DOP => open, |
ADDR => address(12 downto 2), |
CLK => clk, |
DI => data_write(31 downto 24), |
DIP => ZERO(0 downto 0), |
EN => enable, |
SSR => ZERO(0), |
WE => write_byte_enable(3)); |
|
RAMB16_S9_inst1 : RAMB16_S9 |
generic map ( |
INIT_00 => X"000000000000000000000000000000000000000000000000000000000d090501", |
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000") |
port map ( |
DO => data_read(23 downto 16), |
DOP => open, |
ADDR => address(12 downto 2), |
CLK => clk, |
DI => data_write(23 downto 16), |
DIP => ZERO(0 downto 0), |
EN => enable, |
SSR => ZERO(0), |
WE => write_byte_enable(2)); |
|
RAMB16_S9_inst2 : RAMB16_S9 |
generic map ( |
INIT_00 => X"000000000000000000000000000000000000000000000000000000000e0a0602", |
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000") |
port map ( |
DO => data_read(15 downto 8), |
DOP => open, |
ADDR => address(12 downto 2), |
CLK => clk, |
DI => data_write(15 downto 8), |
DIP => ZERO(0 downto 0), |
EN => enable, |
SSR => ZERO(0), |
WE => write_byte_enable(1)); |
|
RAMB16_S9_inst3 : RAMB16_S9 |
generic map ( |
INIT_00 => X"000000000000000000000000000000000000000000000000000000000f0b0703", |
INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000", |
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000") |
port map ( |
DO => data_read(7 downto 0), |
DOP => open, |
ADDR => address(12 downto 2), |
CLK => clk, |
DI => data_write(7 downto 0), |
DIP => ZERO(0 downto 0), |
EN => enable, |
SSR => ZERO(0), |
WE => write_byte_enable(0)); |
|
end; --architecture logic |
/uart.vhd
0,0 → 1,162
--------------------------------------------------------------------- |
-- TITLE: UART |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 5/29/02 |
-- FILENAME: uart.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the UART. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_misc.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_textio.all; |
use ieee.std_logic_unsigned.all; |
use std.textio.all; |
use work.mlite_pack.all; |
|
entity uart is |
generic(log_file : string := "UNUSED"); |
port(clk : in std_logic; |
reset : in std_logic; |
enable_read : in std_logic; |
enable_write : in std_logic; |
data_in : in std_logic_vector(7 downto 0); |
data_out : out std_logic_vector(7 downto 0); |
uart_read : in std_logic; |
uart_write : out std_logic; |
busy_write : out std_logic; |
data_avail : out std_logic); |
end; --entity uart |
|
architecture logic of uart is |
signal delay_write_reg : std_logic_vector(9 downto 0); |
signal bits_write_reg : std_logic_vector(3 downto 0); |
signal data_write_reg : std_logic_vector(8 downto 0); |
signal delay_read_reg : std_logic_vector(9 downto 0); |
signal bits_read_reg : std_logic_vector(3 downto 0); |
signal data_read_reg : std_logic_vector(7 downto 0); |
signal data_save_reg : std_logic_vector(8 downto 0); |
signal busy_write_sig : std_logic; |
signal read_value_reg : std_logic_vector(7 downto 0); |
signal uart_read2 : std_logic; |
|
begin |
|
uart_proc: process(clk, reset, enable_read, enable_write, data_in, |
data_write_reg, bits_write_reg, delay_write_reg, |
data_read_reg, bits_read_reg, delay_read_reg, |
data_save_reg, read_value_reg, uart_read2) |
constant COUNT_VALUE : std_logic_vector(9 downto 0) := |
-- "0100011110"; --33MHz/2/57600Hz = 0x11e |
-- "1101100100"; --50MHz/57600Hz = 0x364 |
"0110110010"; --25MHz/57600Hz = 0x1b2 |
-- "0000000100"; --for debug (shorten read_value_reg) |
begin |
uart_read2 <= read_value_reg(read_value_reg'length - 1); |
|
if reset = '1' then |
data_write_reg <= ZERO(8 downto 1) & '1'; |
bits_write_reg <= "0000"; |
delay_write_reg <= ZERO(9 downto 0); |
read_value_reg <= ONES(7 downto 0); |
data_read_reg <= ZERO(7 downto 0); |
bits_read_reg <= "0000"; |
delay_read_reg <= ZERO(9 downto 0); |
data_save_reg <= ZERO(8 downto 0); |
elsif rising_edge(clk) then |
|
--Write UART |
if bits_write_reg = "0000" then --nothing left to write? |
if enable_write = '1' then |
delay_write_reg <= ZERO(9 downto 0); --delay before next bit |
bits_write_reg <= "1010"; --number of bits to write |
data_write_reg <= data_in & '0'; --remember data & start bit |
end if; |
else |
if delay_write_reg /= COUNT_VALUE then |
delay_write_reg <= delay_write_reg + 1; --delay before next bit |
else |
delay_write_reg <= ZERO(9 downto 0); --reset delay |
bits_write_reg <= bits_write_reg - 1; --bits left to write |
data_write_reg <= '1' & data_write_reg(8 downto 1); |
end if; |
end if; |
|
--Average uart_read signal |
if uart_read = '1' then |
if read_value_reg /= ONES(read_value_reg'length - 1 downto 0) then |
read_value_reg <= read_value_reg + 1; |
end if; |
else |
if read_value_reg /= ZERO(read_value_reg'length - 1 downto 0) then |
read_value_reg <= read_value_reg - 1; |
end if; |
end if; |
|
--Read UART |
if delay_read_reg = ZERO(9 downto 0) then --done delay for read? |
if bits_read_reg = "0000" then --nothing left to read? |
if uart_read2 = '0' then --wait for start bit |
delay_read_reg <= '0' & COUNT_VALUE(9 downto 1); --half period |
bits_read_reg <= "1001"; --bits left to read |
end if; |
else |
delay_read_reg <= COUNT_VALUE; --initialize delay |
bits_read_reg <= bits_read_reg - 1; --bits left to read |
data_read_reg <= uart_read2 & data_read_reg(7 downto 1); |
end if; |
else |
delay_read_reg <= delay_read_reg - 1; --delay |
end if; |
|
if bits_read_reg = "0000" and delay_read_reg = COUNT_VALUE then |
data_save_reg <= '1' & data_read_reg; |
elsif enable_read = '1' then |
data_save_reg(8) <= '0'; --data_available |
end if; |
end if; --rising_edge(clk) |
|
uart_write <= data_write_reg(0); |
if bits_write_reg /= "0000" and log_file = "UNUSED" then |
busy_write_sig <= '1'; |
else |
busy_write_sig <= '0'; |
end if; |
busy_write <= busy_write_sig; |
data_avail <= data_save_reg(8); |
data_out <= data_save_reg(7 downto 0); |
|
end process; --uart_proc |
|
uart_logger: |
if log_file /= "UNUSED" generate |
uart_proc: process(clk, enable_write, data_in) |
file store_file : text open write_mode is log_file; |
variable hex_file_line : line; |
variable c : character; |
variable index : natural; |
variable line_length : natural := 0; |
begin |
if rising_edge(clk) and busy_write_sig = '0' then |
if enable_write = '1' then |
index := conv_integer(data_in(6 downto 0)); |
if index /= 10 then |
c := character'val(index); |
write(hex_file_line, c); |
line_length := line_length + 1; |
end if; |
if index = 10 or line_length >= 72 then |
--The following line had to be commented out for synthesis |
writeline(store_file, hex_file_line); |
line_length := 0; |
end if; |
end if; --uart_sel |
end if; --rising_edge(clk) |
end process; --uart_proc |
end generate; --uart_logger |
|
end; --architecture logic |
/plasma.vhd
0,0 → 1,196
--------------------------------------------------------------------- |
-- TITLE: Plasma (CPU core with memory) |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 6/4/02 |
-- FILENAME: plasma.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- This entity combines the CPU core with memory and a UART. |
-- |
-- Memory Map: |
-- 0x00000000 - 0x0000ffff Internal RAM (16KB) |
-- 0x10000000 - 0x000fffff External RAM (1MB) |
-- Access all Misc registers with 32-bit accesses |
-- 0x20000000 Uart Write (will pause CPU if busy) |
-- 0x20000000 Uart Read |
-- 0x20000010 IRQ Mask |
-- 0x20000020 IRQ Status |
-- 0x20000030 GPIO0 Out |
-- 0x20000050 GPIOA In |
-- 0x20000060 Counter |
-- IRQ bits: |
-- 7 GPIO31 |
-- 6 GPIO30 |
-- 5 ^GPIO31 |
-- 4 ^GPIO30 |
-- 3 Counter(18) |
-- 2 ^Counter(18) |
-- 1 ^UartWriteBusy |
-- 0 UartDataAvailable |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
entity plasma is |
generic(memory_type : string := "XILINX_X16"; --"DUAL_PORT_" "ALTERA_LPM"; |
log_file : string := "UNUSED"); |
port(clk : in std_logic; |
reset : in std_logic; |
|
uart_write : out std_logic; |
uart_read : in std_logic; |
|
address : out std_logic_vector(31 downto 2); |
data_write : out std_logic_vector(31 downto 0); |
data_read : in std_logic_vector(31 downto 0); |
write_byte_enable : out std_logic_vector(3 downto 0); |
mem_pause_in : in std_logic; |
|
gpio0_out : out std_logic_vector(31 downto 0); |
gpioA_in : in std_logic_vector(31 downto 0)); |
end; --entity plasma |
|
architecture logic of plasma is |
signal address_reg : std_logic_vector(31 downto 2); |
signal data_write_reg : std_logic_vector(31 downto 0); |
signal write_byte_enable_reg : std_logic_vector(3 downto 0); |
|
signal mem_address : std_logic_vector(31 downto 0); |
signal mem_data_read : std_logic_vector(31 downto 0); |
signal mem_data_write : std_logic_vector(31 downto 0); |
signal mem_write_byte_enable : std_logic_vector(3 downto 0); |
signal data_read_ram : std_logic_vector(31 downto 0); |
signal data_read_uart : std_logic_vector(7 downto 0); |
signal write_enable : std_logic; |
signal mem_pause : std_logic; |
|
signal enable_internal_ram : std_logic; |
signal enable_misc : std_logic; |
signal enable_uart : std_logic; |
signal enable_uart_read : std_logic; |
signal enable_uart_write : std_logic; |
|
signal gpio0_reg : std_logic_vector(31 downto 0); |
|
signal uart_write_busy : std_logic; |
signal uart_data_avail : std_logic; |
signal irq_mask_reg : std_logic_vector(7 downto 0); |
signal irq_status : std_logic_vector(7 downto 0); |
signal irq : std_logic; |
signal counter_reg : std_logic_vector(31 downto 0); |
|
begin --architecture |
write_byte_enable <= write_byte_enable_reg; |
data_write <= data_write_reg; |
address <= address_reg; |
|
write_enable <= '1' when write_byte_enable_reg /= "0000" else '0'; |
mem_pause <= mem_pause_in or (uart_write_busy and enable_uart and write_enable); |
irq_status <= gpioA_in(31 downto 30) & (gpioA_in(31 downto 30) xor "11") & |
counter_reg(18) & not counter_reg(18) & |
not uart_write_busy & uart_data_avail; |
irq <= '1' when (irq_status and irq_mask_reg) /= ZERO(7 downto 0) else '0'; |
gpio0_out <= gpio0_reg; |
|
enable_internal_ram <= '1' when mem_address(30 downto 28) = "000" else '0'; |
enable_misc <= '1' when address_reg(30 downto 28) = "010" else '0'; |
enable_uart <= '1' when enable_misc = '1' and address_reg(7 downto 4) = "0000" else '0'; |
enable_uart_read <= enable_uart and not write_enable; |
enable_uart_write <= enable_uart and write_enable; |
|
u1_cpu: mlite_cpu |
generic map (memory_type => memory_type) |
PORT MAP ( |
clk => clk, |
reset_in => reset, |
intr_in => irq, |
|
mem_address => mem_address, |
mem_data_w => mem_data_write, |
mem_data_r => mem_data_read, |
mem_byte_we => mem_write_byte_enable, |
mem_pause => mem_pause); |
|
misc_proc: process(clk, reset, mem_address, address_reg, enable_misc, |
data_read_ram, data_read, data_read_uart, mem_pause, |
irq_mask_reg, irq_status, gpio0_reg, write_enable, |
gpioA_in, counter_reg, mem_data_write, data_write_reg) |
begin |
case address_reg(30 downto 28) is |
when "000" => --internal RAM |
mem_data_read <= data_read_ram; |
when "001" => --external RAM |
mem_data_read <= data_read; |
when "010" => --misc |
case address_reg(6 downto 4) is |
when "000" => --uart |
mem_data_read <= ZERO(31 downto 8) & data_read_uart; |
when "001" => --irq_mask |
mem_data_read <= ZERO(31 downto 8) & irq_mask_reg; |
when "010" => --irq_status |
mem_data_read <= ZERO(31 downto 8) & irq_status; |
when "011" => --gpio0 |
mem_data_read <= gpio0_reg; |
when "101" => --gpioA |
mem_data_read <= gpioA_in; |
when "110" => --counter |
mem_data_read <= counter_reg; |
when others => |
mem_data_read <= gpioA_in; |
end case; |
when others => |
mem_data_read <= ZERO; |
end case; |
|
if reset = '1' then |
address_reg <= ZERO(31 downto 2); |
data_write_reg <= ZERO; |
write_byte_enable_reg <= ZERO(3 downto 0); |
irq_mask_reg <= ZERO(7 downto 0); |
gpio0_reg <= ZERO; |
counter_reg <= ZERO; |
elsif rising_edge(clk) then |
if mem_pause = '0' then |
address_reg <= mem_address(31 downto 2); |
data_write_reg <= mem_data_write; |
write_byte_enable_reg <= mem_write_byte_enable; |
if enable_misc = '1' and write_enable = '1' then |
if address_reg(6 downto 4) = "001" then |
irq_mask_reg <= data_write_reg(7 downto 0); |
elsif address_reg(6 downto 4) = "011" then |
gpio0_reg <= data_write_reg; |
end if; |
end if; |
end if; |
counter_reg <= bv_inc(counter_reg); |
end if; |
end process; |
|
u2_ram: ram |
generic map (memory_type => memory_type) |
port map ( |
clk => clk, |
enable => enable_internal_ram, |
write_byte_enable => mem_write_byte_enable, |
address => mem_address(31 downto 2), |
data_write => mem_data_write, |
data_read => data_read_ram); |
|
u3_uart: uart |
generic map (log_file => log_file) |
port map( |
clk => clk, |
reset => reset, |
enable_read => enable_uart_read, |
enable_write => enable_uart_write, |
data_in => data_write_reg(7 downto 0), |
data_out => data_read_uart, |
uart_read => uart_read, |
uart_write => uart_write, |
busy_write => uart_write_busy, |
data_avail => uart_data_avail); |
|
end; --architecture logic |
/ram.vhd
0,0 → 1,175
--------------------------------------------------------------------- |
-- TITLE: Random Access Memory |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 4/21/01 |
-- FILENAME: ram.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the RAM, reads the executable from either "code.txt", |
-- or for Altera "code[0-3].hex". |
-- Modified from "The Designer's Guide to VHDL" by Peter J. Ashenden |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_misc.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_unsigned.all; |
use ieee.std_logic_textio.all; |
use std.textio.all; |
use work.mlite_pack.all; |
--Uncomment following two lines for Xilinx RAM16X1D |
library UNISIM; --Xilinx |
use UNISIM.vcomponents.all; --Xilinx |
|
entity ram is |
generic(memory_type : string := "DEFAULT"); |
port(clk : in std_logic; |
enable : in std_logic; |
write_byte_enable : in std_logic_vector(3 downto 0); |
address : in std_logic_vector(31 downto 2); |
data_write : in std_logic_vector(31 downto 0); |
data_read : out std_logic_vector(31 downto 0)); |
end; --entity ram |
|
architecture logic of ram is |
constant ADDRESS_WIDTH : natural := 13; |
begin |
|
generic_ram: |
if memory_type /= "ALTERA_LPM" generate |
--Simulate a synchronous RAM |
ram_proc: process(clk, enable, write_byte_enable, |
address, data_write) --mem_write, mem_sel |
variable mem_size : natural := 2 ** ADDRESS_WIDTH; |
variable data : std_logic_vector(31 downto 0); |
subtype word is std_logic_vector(data_write'length-1 downto 0); |
type storage_array is |
array(natural range 0 to mem_size/4 - 1) of word; |
variable storage : storage_array; |
variable index : natural := 0; |
file load_file : text open read_mode is "code.txt"; |
variable hex_file_line : line; |
begin |
|
--Load in the ram executable image |
if index = 0 then |
while not endfile(load_file) loop |
--The following two lines had to be commented out for synthesis |
readline(load_file, hex_file_line); |
hread(hex_file_line, data); |
storage(index) := data; |
index := index + 1; |
end loop; |
end if; |
|
if rising_edge(clk) then |
index := conv_integer(address(ADDRESS_WIDTH-1 downto 2)); |
data := storage(index); |
|
if enable = '1' then |
if write_byte_enable(0) = '1' then |
data(7 downto 0) := data_write(7 downto 0); |
end if; |
if write_byte_enable(1) = '1' then |
data(15 downto 8) := data_write(15 downto 8); |
end if; |
if write_byte_enable(2) = '1' then |
data(23 downto 16) := data_write(23 downto 16); |
end if; |
if write_byte_enable(3) = '1' then |
data(31 downto 24) := data_write(31 downto 24); |
end if; |
end if; |
|
if write_byte_enable /= "0000" then |
storage(index) := data; |
end if; |
end if; |
|
data_read <= data; |
end process; |
end generate; --generic_ram |
|
|
altera_ram: |
if memory_type = "ALTERA_LPM" generate |
lpm_ram_io_component0 : lpm_ram_dq |
GENERIC MAP ( |
intended_device_family => "UNUSED", |
lpm_width => 8, |
lpm_widthad => ADDRESS_WIDTH-2, |
lpm_indata => "REGISTERED", |
lpm_address_control => "REGISTERED", |
lpm_outdata => "UNREGISTERED", |
lpm_file => "code0.hex", |
use_eab => "ON", |
lpm_type => "LPM_RAM_DQ") |
PORT MAP ( |
data => data_write(31 downto 24), |
address => address(ADDRESS_WIDTH-1 downto 2), |
inclock => clk, |
we => write_byte_enable(3), |
q => data_read(31 downto 24)); |
|
lpm_ram_io_component1 : lpm_ram_dq |
GENERIC MAP ( |
intended_device_family => "UNUSED", |
lpm_width => 8, |
lpm_widthad => ADDRESS_WIDTH-2, |
lpm_indata => "REGISTERED", |
lpm_address_control => "REGISTERED", |
lpm_outdata => "UNREGISTERED", |
lpm_file => "code1.hex", |
use_eab => "ON", |
lpm_type => "LPM_RAM_DQ") |
PORT MAP ( |
data => data_write(23 downto 16), |
address => address(ADDRESS_WIDTH-1 downto 2), |
inclock => clk, |
we => write_byte_enable(2), |
q => data_read(23 downto 16)); |
|
lpm_ram_io_component2 : lpm_ram_dq |
GENERIC MAP ( |
intended_device_family => "UNUSED", |
lpm_width => 8, |
lpm_widthad => ADDRESS_WIDTH-2, |
lpm_indata => "REGISTERED", |
lpm_address_control => "REGISTERED", |
lpm_outdata => "UNREGISTERED", |
lpm_file => "code2.hex", |
use_eab => "ON", |
lpm_type => "LPM_RAM_DQ") |
PORT MAP ( |
data => data_write(15 downto 8), |
address => address(ADDRESS_WIDTH-1 downto 2), |
inclock => clk, |
we => write_byte_enable(1), |
q => data_read(15 downto 8)); |
|
lpm_ram_io_component3 : lpm_ram_dq |
GENERIC MAP ( |
intended_device_family => "UNUSED", |
lpm_width => 8, |
lpm_widthad => ADDRESS_WIDTH-2, |
lpm_indata => "REGISTERED", |
lpm_address_control => "REGISTERED", |
lpm_outdata => "UNREGISTERED", |
lpm_file => "code3.hex", |
use_eab => "ON", |
lpm_type => "LPM_RAM_DQ") |
PORT MAP ( |
data => data_write(7 downto 0), |
address => address(ADDRESS_WIDTH-1 downto 2), |
inclock => clk, |
we => write_byte_enable(0), |
q => data_read(7 downto 0)); |
|
end generate; --altera_ram |
|
|
--For XILINX see ram_xilinx.vhd |
|
end; --architecture logic |
/control.vhd
0,0 → 1,510
--------------------------------------------------------------------- |
-- TITLE: Controller / Opcode Decoder |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/8/01 |
-- FILENAME: control.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- NOTE: MIPS(tm) is a registered trademark of MIPS Technologies. |
-- MIPS Technologies does not endorse and is not associated with |
-- this project. |
-- DESCRIPTION: |
-- Controls the CPU by decoding the opcode and generating control |
-- signals to the rest of the CPU. |
-- This entity decodes the MIPS(tm) opcode into a |
-- Very-Long-Word-Instruction. |
-- The 32-bit opcode is converted to a |
-- 6+6+6+16+5+2+3+3+2+2+3+2+4 = 60 bit VLWI opcode. |
-- Based on information found in: |
-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich |
-- and "The Designer's Guide to VHDL" by Peter J. Ashenden |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
entity control is |
port(opcode : in std_logic_vector(31 downto 0); |
intr_signal : in std_logic; |
rs_index : out std_logic_vector(5 downto 0); |
rt_index : out std_logic_vector(5 downto 0); |
rd_index : out std_logic_vector(5 downto 0); |
imm_out : out std_logic_vector(15 downto 0); |
alu_func : out alu_function_type; |
shift_func : out shift_function_type; |
mult_func : out mult_function_type; |
branch_func : out branch_function_type; |
a_source_out : out a_source_type; |
b_source_out : out b_source_type; |
c_source_out : out c_source_type; |
pc_source_out: out pc_source_type; |
mem_source_out:out mem_source_type); |
end; --entity control |
|
architecture logic of control is |
begin |
|
control_proc: process(opcode, intr_signal) |
variable op, func : std_logic_vector(5 downto 0); |
variable rs, rt, rd : std_logic_vector(5 downto 0); |
variable rtx : std_logic_vector(4 downto 0); |
variable imm : std_logic_vector(15 downto 0); |
variable alu_function : alu_function_type; |
variable shift_function : shift_function_type; |
variable mult_function : mult_function_type; |
variable a_source : a_source_type; |
variable b_source : b_source_type; |
variable c_source : c_source_type; |
variable pc_source : pc_source_type; |
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; |
op := opcode(31 downto 26); |
rs := '0' & opcode(25 downto 21); |
rt := '0' & opcode(20 downto 16); |
rtx := opcode(20 downto 16); |
rd := '0' & opcode(15 downto 11); |
func := opcode(5 downto 0); |
imm := opcode(15 downto 0); |
|
case op is |
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; |
|
when "000010" => --SRL r[rd]=u[rt]>>re; |
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; |
|
when "000100" => --SLLV r[rd]=r[rt]<<r[rs]; |
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; |
|
when "000111" => --SRAV r[rd]=r[rt]>>r[rs]; |
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; |
|
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; |
|
when "001010" => --MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/ |
-- c_source := C_FROM_REG_SOURCE_EQZ; |
|
when "001011" => --MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/ |
-- 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; |
|
when "010001" => --FTHI s->hi=r[rs]; |
mult_function := MULT_WRITE_HI; |
|
when "010010" => --MFLO r[rd]=s->lo; |
c_source := C_FROM_MULT; |
mult_function := MULT_READ_LO; |
|
when "010011" => --MTLO s->lo=r[rs]; |
mult_function := MULT_WRITE_LO; |
|
when "011000" => --MULT s->lo=r[rs]*r[rt]; s->hi=0; |
mult_function := MULT_SIGNED_MULT; |
|
when "011001" => --MULTU s->lo=r[rs]*r[rt]; s->hi=0; |
mult_function := MULT_MULT; |
|
when "011010" => --DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; |
mult_function := MULT_SIGNED_DIVIDE; |
|
when "011011" => --DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; |
mult_function := MULT_DIVIDE; |
|
when "100000" => --ADD r[rd]=r[rs]+r[rt]; |
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; |
|
when "100010" => --SUB r[rd]=r[rs]-r[rt]; |
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; |
|
when "100100" => --AND r[rd]=r[rs]&r[rt]; |
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; |
|
when "100110" => --XOR r[rd]=r[rs]^r[rt]; |
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; |
|
when "101010" => --SLT r[rd]=r[rs]<r[rt]; |
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; |
|
when "101101" => --DADDU r[rd]=r[rs]+u[rt]; |
c_source := C_FROM_ALU; |
alu_function := ALU_ADD; |
|
when "110001" => --TGEU |
when "110010" => --TLT |
when "110011" => --TLTU |
when "110100" => --TEQ |
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; |
--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; |
|
when "00000" => --BLTZ branch=r[rs]<0; |
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; |
|
when "00001" => --BGEZ branch=r[rs]>=0; |
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; |
|
when "00010" => --BLTZL lbranch=r[rs]<0; |
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; |
|
when "00011" => --BGEZL lbranch=r[rs]>=0; |
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; |
rd := "011111"; |
pc_source := FROM_OPCODE25_0; |
|
when "000010" => --J s->pc_next=(s->pc&0xf0000000)|target; |
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; |
|
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; |
|
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; |
|
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; |
|
when "001000" => --ADDI r[rt]=r[rs]+(short)imm; |
b_source := B_FROM_SIGNED_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := ALU_ADD; |
|
when "001001" => --ADDIU u[rt]=u[rs]+(short)imm; |
b_source := B_FROM_SIGNED_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := ALU_ADD; |
|
when "001010" => --SLTI r[rt]=r[rs]<(short)imm; |
b_source := B_FROM_SIGNED_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
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; |
rd := rt; |
alu_function := ALU_LESS_THAN; |
|
when "001100" => --ANDI r[rt]=r[rs]&imm; |
b_source := B_FROM_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := ALU_AND; |
|
when "001101" => --ORI r[rt]=r[rs]|imm; |
b_source := B_FROM_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := ALU_OR; |
|
when "001110" => --XORI r[rt]=r[rs]^imm; |
b_source := B_FROM_IMM; |
c_source := C_FROM_ALU; |
rd := rt; |
alu_function := ALU_XOR; |
|
when "001111" => --LUI r[rt]=(imm<<16); |
c_source := C_FROM_IMM_SHIFT16; |
rd := rt; |
|
when "010000" => --COP0 |
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"; |
rd := '0' & opcode(20 downto 16); |
else --move to CP0 |
rs := "000000"; |
rd(5) := '1'; |
pc_source := FROM_BRANCH; --delay possible interrupt |
branch_function := BRANCH_NO; |
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; |
|
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; |
|
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; |
|
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; |
|
when "100000" => --LB r[rt]=*(signed char*)ptr; |
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]; |
|
when "100001" => --LH r[rt]=*(signed short*)ptr; |
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]; |
|
when "100010" => --LWL //Not Implemented |
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; |
|
when "100011" => --LW r[rt]=*(long*)ptr; |
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; |
|
when "100100" => --LBU r[rt]=*(unsigned char*)ptr; |
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]; |
|
when "100101" => --LHU r[rt]=*(unsigned short*)ptr; |
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]; |
|
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]; |
|
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; |
|
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]; |
|
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]; |
|
when "101110" => --SWR //Not Implemented |
when "101111" => --CACHE |
when "110000" => --LL r[rt]=*(long*)ptr; |
when "110001" => --LWC1 |
when "110010" => --LWC2 |
when "110011" => --LWC3 |
when "110101" => --LDC1 |
when "110110" => --LDC2 |
when "110111" => --LDC3 |
when "111000" => --SC *(long*)ptr=r[rt]; r[rt]=1; |
when "111001" => --SWC1 |
when "111010" => --SWC2 |
when "111011" => --SWC3 |
when "111101" => --SDC1 |
when "111110" => --SDC2 |
when "111111" => --SDC3 |
when others => |
end case; |
|
if c_source = C_FROM_NULL then |
rd := "000000"; |
end if; |
|
if intr_signal = '1' then |
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; |
end if; |
|
rs_index <= rs; |
rt_index <= rt; |
rd_index <= rd; |
imm_out <= imm; |
alu_func <= alu_function; |
shift_func <= shift_function; |
mult_func <= mult_function; |
branch_func <= branch_function; |
a_source_out <= a_source; |
b_source_out <= b_source; |
c_source_out <= c_source; |
pc_source_out <= pc_source; |
mem_source_out <= mem_source; |
|
end process; |
|
end; --logic |
/mlite_cpu.vhd
0,0 → 1,336
--------------------------------------------------------------------- |
-- TITLE: Plasma CPU core |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/15/01 |
-- FILENAME: mlite_cpu.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- NOTE: MIPS(tm) and MIPS I(tm) are registered trademarks of MIPS |
-- Technologies. MIPS Technologies does not endorse and is not |
-- associated with this project. |
-- DESCRIPTION: |
-- Top level VHDL document that ties the nine other entities together. |
-- |
-- Executes all MIPS I(tm) opcodes but exceptions and non-aligned |
-- memory accesses. Based on information found in: |
-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich |
-- and "The Designer's Guide to VHDL" by Peter J. Ashenden |
-- |
-- The CPU is implemented as a three or four stage pipeline. |
-- An add instruction would take the following steps (see cpu.gif): |
-- Stage #1: |
-- 1. The "pc_next" entity passes the program counter (PC) to the |
-- "mem_ctrl" entity which fetches the opcode from memory. |
-- Stage #2: |
-- 2. The memory returns the opcode. |
-- Stage #3: |
-- 3. "Mem_ctrl" passes the opcode to the "control" entity. |
-- 4. "Control" converts the 32-bit opcode to a 60-bit VLWI opcode |
-- and sends control signals to the other entities. |
-- 5. Based on the rs_index and rt_index control signals, "reg_bank" |
-- sends the 32-bit reg_source and reg_target to "bus_mux". |
-- 6. Based on the a_source and b_source control signals, "bus_mux" |
-- multiplexes reg_source onto a_bus and reg_target onto b_bus. |
-- Stage #4 (part of stage #3 if using three stage pipeline): |
-- 7. Based on the alu_func control signals, "alu" adds the values |
-- from a_bus and b_bus and places the result on c_bus. |
-- 8. Based on the c_source control signals, "bus_bux" multiplexes |
-- c_bus onto reg_dest. |
-- 9. Based on the rd_index control signal, "reg_bank" saves |
-- reg_dest into the correct register. |
-- Stage #4b: |
-- 10. Read or write memory if needed. |
-- |
-- All signals are active high. |
-- Here are the signals for writing a character to address 0xffff |
-- when using a three stage pipeline: |
-- |
-- Program: |
-- addr value opcode |
-- ============================= |
-- 3c: 00000000 nop |
-- 40: 34040041 li $a0,0x41 |
-- 44: 3405ffff li $a1,0xffff |
-- 48: a0a40000 sb $a0,0($a1) |
-- 4c: 00000000 nop |
-- 50: 00000000 nop |
-- |
-- intr_in mem_pause |
-- reset_in mem_byte_we Stages |
-- ns mem_address mem_data_w mem_data_r 40 44 48 4c 50 |
-- 3500 0 0 00000040 00000000 00000000 0 0 1 |
-- 3600 0 0 00000044 00000000 34040041 0 0 2 1 |
-- 3700 0 0 00000048 00000000 3405FFFF 0 0 3 2 1 |
-- 3800 0 0 0000004C 00000000 A0A40000 0 0 3 2 1 |
-- 3900 0 0 0000FFFC 41414141 00000000 1 0 3 2 |
-- 4000 0 0 00000050 41414141 XXXXXX41 0 0 4b 3 1 |
-- 4100 0 0 00000054 00000000 00000000 0 0 2 |
--------------------------------------------------------------------- |
library ieee; |
use work.mlite_pack.all; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
entity mlite_cpu is |
generic(memory_type : string := "XILINX_16X"; --ALTERA_LPM, or DUAL_PORT_ |
mult_type : string := "DEFAULT"; --AREA_OPTIMIZED |
shifter_type : string := "DEFAULT"; --AREA_OPTIMIZED |
alu_type : string := "DEFAULT"; --AREA_OPTIMIZED |
pipeline_stages : natural := 3); --3 or 4 |
port(clk : in std_logic; |
reset_in : in std_logic; |
intr_in : in std_logic; |
|
mem_address : out std_logic_vector(31 downto 0); |
mem_data_w : out std_logic_vector(31 downto 0); |
mem_data_r : in std_logic_vector(31 downto 0); |
mem_byte_we : out std_logic_vector(3 downto 0); |
mem_pause : in std_logic); |
end; --entity mlite_cpu |
|
architecture logic of mlite_cpu is |
--When using a three stage pipeline "sigD <= sig". |
--When using a four stage pipeline "sigD <= sig when rising_edge(clk)", |
-- so sigD is delayed by one clock cycle. |
signal opcode : std_logic_vector(31 downto 0); |
signal rs_index : std_logic_vector(5 downto 0); |
signal rt_index : std_logic_vector(5 downto 0); |
signal rd_index : std_logic_vector(5 downto 0); |
signal rd_indexD : std_logic_vector(5 downto 0); |
signal reg_source : std_logic_vector(31 downto 0); |
signal reg_target : std_logic_vector(31 downto 0); |
signal reg_dest : std_logic_vector(31 downto 0); |
signal reg_destD : std_logic_vector(31 downto 0); |
signal a_bus : std_logic_vector(31 downto 0); |
signal a_busD : std_logic_vector(31 downto 0); |
signal b_bus : std_logic_vector(31 downto 0); |
signal b_busD : std_logic_vector(31 downto 0); |
signal c_bus : std_logic_vector(31 downto 0); |
signal c_alu : std_logic_vector(31 downto 0); |
signal c_shift : std_logic_vector(31 downto 0); |
signal c_mult : std_logic_vector(31 downto 0); |
signal c_memory : std_logic_vector(31 downto 0); |
signal imm : std_logic_vector(15 downto 0); |
signal pc_future : std_logic_vector(31 downto 2); |
signal pc_current : std_logic_vector(31 downto 2); |
signal pc_plus4 : std_logic_vector(31 downto 2); |
signal alu_func : alu_function_type; |
signal alu_funcD : alu_function_type; |
signal shift_func : shift_function_type; |
signal shift_funcD : shift_function_type; |
signal mult_func : mult_function_type; |
signal mult_funcD : mult_function_type; |
signal branch_func : branch_function_type; |
signal take_branch : std_logic; |
signal a_source : a_source_type; |
signal b_source : b_source_type; |
signal c_source : c_source_type; |
signal pc_source : pc_source_type; |
signal mem_source : mem_source_type; |
signal pause_mult : std_logic; |
signal pause_ctrl : std_logic; |
signal pause_pipeline : std_logic; |
signal pause_any : std_logic; |
signal pause_non_ctrl : std_logic; |
signal pause_bank : std_logic; |
signal nullify_op : std_logic; |
signal intr_enable : std_logic; |
signal intr_signal : std_logic; |
signal reset_reg : std_logic_vector(3 downto 0); |
signal reset : std_logic; |
begin --architecture |
|
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') |
or intr_signal = '1' |
else '0'; |
c_bus <= c_alu or c_shift or c_mult; |
reset <= '1' when reset_in = '1' or reset_reg /= "1111" else '0'; |
mem_address(1 downto 0) <= "00"; |
|
--synchronize reset and interrupt pins |
intr_proc: process(clk, reset_in, reset_reg, intr_in, intr_enable, |
pc_source, pc_current, pause_any) |
begin |
if reset_in = '1' then |
reset_reg <= "0000"; |
intr_signal <= '0'; |
elsif rising_edge(clk) then |
if reset_reg /= "1111" then |
reset_reg <= reset_reg + 1; |
end if; |
|
--don't try to interrupt a multi-cycle instruction |
if pause_any = '0' then |
if intr_in = '1' and intr_enable = '1' and |
pc_source = FROM_INC4 then |
--the epc will contain pc+4 |
intr_signal <= '1'; |
else |
intr_signal <= '0'; |
end if; |
end if; |
|
end if; |
end process; |
|
u1_pc_next: pc_next PORT MAP ( |
clk => clk, |
reset_in => reset, |
take_branch => take_branch, |
pause_in => pause_any, |
pc_new => c_bus(31 downto 2), |
opcode25_0 => opcode(25 downto 0), |
pc_source => pc_source, |
pc_future => pc_future, |
pc_current => pc_current, |
pc_plus4 => pc_plus4); |
|
u2_mem_ctrl: mem_ctrl |
PORT MAP ( |
clk => clk, |
reset_in => reset, |
pause_in => pause_non_ctrl, |
nullify_op => nullify_op, |
address_pc => pc_future, |
opcode_out => opcode, |
|
address_in => c_bus, |
mem_source => mem_source, |
data_write => reg_target, |
data_read => c_memory, |
pause_out => pause_ctrl, |
|
mem_address => mem_address(31 downto 2), |
mem_data_w => mem_data_w, |
mem_data_r => mem_data_r, |
mem_byte_we => mem_byte_we); |
|
u3_control: control PORT MAP ( |
opcode => opcode, |
intr_signal => intr_signal, |
rs_index => rs_index, |
rt_index => rt_index, |
rd_index => rd_index, |
imm_out => imm, |
alu_func => alu_func, |
shift_func => shift_func, |
mult_func => mult_func, |
branch_func => branch_func, |
a_source_out => a_source, |
b_source_out => b_source, |
c_source_out => c_source, |
pc_source_out=> pc_source, |
mem_source_out=> mem_source); |
|
u4_reg_bank: reg_bank |
generic map(memory_type => memory_type) |
port map ( |
clk => clk, |
reset_in => reset, |
pause => pause_bank, |
rs_index => rs_index, |
rt_index => rt_index, |
rd_index => rd_indexD, |
reg_source_out => reg_source, |
reg_target_out => reg_target, |
reg_dest_new => reg_destD, |
intr_enable => intr_enable); |
|
u5_bus_mux: bus_mux port map ( |
imm_in => imm, |
reg_source => reg_source, |
a_mux => a_source, |
a_out => a_bus, |
|
reg_target => reg_target, |
b_mux => b_source, |
b_out => b_bus, |
|
c_bus => c_bus, |
c_memory => c_memory, |
c_pc => pc_current, |
c_pc_plus4 => pc_plus4, |
c_mux => c_source, |
reg_dest_out => reg_dest, |
|
branch_func => branch_func, |
take_branch => take_branch); |
|
u6_alu: alu |
generic map (alu_type => alu_type) |
port map ( |
a_in => a_busD, |
b_in => b_busD, |
alu_function => alu_funcD, |
c_alu => c_alu); |
|
u7_shifter: shifter |
generic map (shifter_type => shifter_type) |
port map ( |
value => b_busD, |
shift_amount => a_busD(4 downto 0), |
shift_func => shift_funcD, |
c_shift => c_shift); |
|
u8_mult: mult |
generic map (mult_type => mult_type) |
port map ( |
clk => clk, |
reset_in => reset, |
a => a_busD, |
b => b_busD, |
mult_func => mult_funcD, |
c_mult => c_mult, |
pause_out => pause_mult); |
|
pipeline3: if pipeline_stages <= 3 generate |
a_busD <= a_bus; |
b_busD <= b_bus; |
alu_funcD <= alu_func; |
shift_funcD <= shift_func; |
mult_funcD <= mult_func; |
rd_indexD <= rd_index; |
reg_destD <= reg_dest; |
pause_pipeline <= '0'; |
end generate; --pipeline2 |
|
pipeline4: if pipeline_stages > 3 generate |
--When operating in four stage pipeline mode, the following signals |
--are delayed by one clock cycle: a_bus, b_bus, alu/shift/mult_func, |
--c_source, and rd_index. |
u9_pipeline: pipeline port map ( |
clk => clk, |
reset => reset, |
a_bus => a_bus, |
a_busD => a_busD, |
b_bus => b_bus, |
b_busD => b_busD, |
alu_func => alu_func, |
alu_funcD => alu_funcD, |
shift_func => shift_func, |
shift_funcD => shift_funcD, |
mult_func => mult_func, |
mult_funcD => mult_funcD, |
reg_dest => reg_dest, |
reg_destD => reg_destD, |
rd_index => rd_index, |
rd_indexD => rd_indexD, |
|
rs_index => rs_index, |
rt_index => rt_index, |
pc_source => pc_source, |
mem_source => mem_source, |
a_source => a_source, |
b_source => b_source, |
c_source => c_source, |
c_bus => c_bus, |
pause_any => pause_any, |
pause_pipeline => pause_pipeline); |
|
end generate; --pipeline4 |
|
end; --architecture logic |
/mult.vhd
0,0 → 1,204
--------------------------------------------------------------------- |
-- TITLE: Multiplication and Division Unit |
-- AUTHORS: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 1/31/01 |
-- FILENAME: mult.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the multiplication and division unit in 32 clocks. |
-- |
-- MULTIPLICATION |
-- long64 answer = 0 |
-- for(i = 0; i < 32; ++i) |
-- { |
-- answer = (answer >> 1) + (((b&1)?a:0) << 31); |
-- b = b >> 1; |
-- } |
-- |
-- DIVISION |
-- long upper=a, lower=0; |
-- a = b << 31; |
-- for(i = 0; i < 32; ++i) |
-- { |
-- lower = lower << 1; |
-- if(upper >= a && a && b < 2) |
-- { |
-- upper = upper - a; |
-- lower |= 1; |
-- } |
-- a = ((b&2) << 30) | (a >> 1); |
-- b = b >> 1; |
-- } |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
use IEEE.std_logic_arith.all; |
use work.mlite_pack.all; |
|
entity mult is |
generic(mult_type : string := "DEFAULT"); |
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); |
pause_out : out std_logic); |
end; --entity mult |
|
architecture logic of mult is |
|
constant MODE_MULT : std_logic := '1'; |
constant MODE_DIV : std_logic := '0'; |
|
signal mode_reg : std_logic; |
signal negate_reg : std_logic; |
signal sign_reg : std_logic; |
signal sign2_reg : std_logic; |
signal count_reg : std_logic_vector(5 downto 0); |
signal aa_reg : std_logic_vector(31 downto 0); |
signal bb_reg : std_logic_vector(31 downto 0); |
signal upper_reg : std_logic_vector(31 downto 0); |
signal lower_reg : std_logic_vector(31 downto 0); |
|
signal a_neg : std_logic_vector(31 downto 0); |
signal b_neg : std_logic_vector(31 downto 0); |
signal sum : std_logic_vector(32 downto 0); |
|
begin |
|
-- Result |
c_mult <= lower_reg when mult_func = MULT_READ_LO and negate_reg = '0' else |
bv_negate(lower_reg) when mult_func = MULT_READ_LO |
and negate_reg = '1' else |
upper_reg when mult_func = MULT_READ_HI else |
ZERO; |
pause_out <= '1' when (count_reg /= "000000") and |
(mult_func = MULT_READ_LO or mult_func = MULT_READ_HI) else '0'; |
|
-- ABS and remainder signals |
a_neg <= bv_negate(a); |
b_neg <= bv_negate(b); |
sum <= bv_adder(upper_reg, aa_reg, mode_reg); |
|
--multiplication/division unit |
mult_proc: process(clk, reset_in, a, b, mult_func, |
a_neg, b_neg, sum, sign_reg, mode_reg, negate_reg, |
count_reg, aa_reg, bb_reg, upper_reg, lower_reg) |
variable count : std_logic_vector(2 downto 0); |
begin |
count := "001"; |
if reset_in = '1' then |
mode_reg <= '0'; |
negate_reg <= '0'; |
sign_reg <= '0'; |
sign2_reg <= '0'; |
count_reg <= "000000"; |
aa_reg <= ZERO; |
bb_reg <= ZERO; |
upper_reg <= ZERO; |
lower_reg <= ZERO; |
elsif rising_edge(clk) then |
case mult_func is |
when MULT_WRITE_LO => |
lower_reg <= a; |
negate_reg <= '0'; |
when MULT_WRITE_HI => |
upper_reg <= a; |
negate_reg <= '0'; |
when MULT_MULT => |
mode_reg <= MODE_MULT; |
aa_reg <= a; |
bb_reg <= b; |
upper_reg <= ZERO; |
count_reg <= "100000"; |
negate_reg <= '0'; |
sign_reg <= '0'; |
sign2_reg <= '0'; |
when MULT_SIGNED_MULT => |
mode_reg <= MODE_MULT; |
if b(31) = '0' then |
aa_reg <= a; |
bb_reg <= b; |
sign_reg <= a(31); |
else |
aa_reg <= a_neg; |
bb_reg <= b_neg; |
sign_reg <= a_neg(31); |
end if; |
sign2_reg <= '0'; |
upper_reg <= ZERO; |
count_reg <= "100000"; |
negate_reg <= '0'; |
when MULT_DIVIDE => |
mode_reg <= MODE_DIV; |
aa_reg <= b(0) & ZERO(30 downto 0); |
bb_reg <= b; |
upper_reg <= a; |
count_reg <= "100000"; |
negate_reg <= '0'; |
when MULT_SIGNED_DIVIDE => |
mode_reg <= MODE_DIV; |
if b(31) = '0' then |
aa_reg(31) <= b(0); |
bb_reg <= b; |
else |
aa_reg(31) <= b_neg(0); |
bb_reg <= b_neg; |
end if; |
if a(31) = '0' then |
upper_reg <= a; |
else |
upper_reg <= a_neg; |
end if; |
aa_reg(30 downto 0) <= ZERO(30 downto 0); |
count_reg <= "100000"; |
negate_reg <= a(31) xor b(31); |
when others => |
|
if count_reg /= "000000" then |
if mode_reg = MODE_MULT then |
-- Multiplication |
if bb_reg(0) = '1' then |
upper_reg <= (sign_reg xor sum(32)) & sum(31 downto 1); |
lower_reg <= sum(0) & lower_reg(31 downto 1); |
sign2_reg <= sign2_reg or sign_reg; |
sign_reg <= '0'; |
bb_reg <= '0' & bb_reg(31 downto 1); |
-- The following six lines are optional for speedup |
elsif bb_reg(3 downto 0) = "0000" and sign2_reg = '0' and |
count_reg(5 downto 2) /= "0000" then |
upper_reg <= "0000" & upper_reg(31 downto 4); |
lower_reg <= upper_reg(3 downto 0) & lower_reg(31 downto 4); |
count := "100"; |
bb_reg <= "0000" & bb_reg(31 downto 4); |
else |
upper_reg <= sign2_reg & upper_reg(31 downto 1); |
lower_reg <= upper_reg(0) & lower_reg(31 downto 1); |
bb_reg <= '0' & bb_reg(31 downto 1); |
end if; |
else |
-- Division |
if sum(32) = '0' and aa_reg /= ZERO and |
bb_reg(31 downto 1) = ZERO(31 downto 1) then |
upper_reg <= sum(31 downto 0); |
lower_reg(0) <= '1'; |
else |
lower_reg(0) <= '0'; |
end if; |
aa_reg <= bb_reg(1) & aa_reg(31 downto 1); |
lower_reg(31 downto 1) <= lower_reg(30 downto 0); |
bb_reg <= '0' & bb_reg(31 downto 1); |
end if; |
count_reg <= count_reg - count; |
end if; --count |
|
end case; |
|
end if; |
|
end process; |
|
end; --architecture logic |
/alu.vhd
0,0 → 1,61
--------------------------------------------------------------------- |
-- TITLE: Arithmetic Logic Unit |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/8/01 |
-- FILENAME: alu.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the ALU. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
entity alu is |
generic(alu_type : string := "DEFAULT"); |
port(a_in : in std_logic_vector(31 downto 0); |
b_in : in std_logic_vector(31 downto 0); |
alu_function : in alu_function_type; |
c_alu : out std_logic_vector(31 downto 0)); |
end; --alu |
|
architecture logic of alu is |
signal do_add : std_logic; |
signal sum : std_logic_vector(32 downto 0); |
signal less_than : std_logic; |
begin |
|
do_add <= '1' when alu_function = ALU_ADD else '0'; |
sum <= bv_adder(a_in, b_in, do_add); |
less_than <= sum(32) when a_in(31) = b_in(31) or alu_function = ALU_LESS_THAN |
else a_in(31); |
|
GENERIC_ALU: if alu_type = "DEFAULT" generate |
c_alu <= sum(31 downto 0) when alu_function=ALU_ADD or |
alu_function=ALU_SUBTRACT else |
ZERO(31 downto 1) & less_than 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; |
end generate; |
|
AREA_OPTIMIZED_ALU: if alu_type/="DEFAULT" 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) & less_than 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; |
|
end; --architecture logic |
|
/bus_mux.vhd
0,0 → 1,136
--------------------------------------------------------------------- |
-- TITLE: Bus Multiplexer / Signal Router |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/8/01 |
-- FILENAME: bus_mux.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- This entity is the main signal router. |
-- It multiplexes signals from multiple sources to the correct location. |
-- The outputs are as follows: |
-- a_bus : goes to the ALU |
-- b_bus : goes to the ALU |
-- reg_dest_out : goes to the register bank |
-- take_branch : goes to pc_next |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mlite_pack.all; |
|
entity bus_mux is |
port(imm_in : in std_logic_vector(15 downto 0); |
reg_source : in std_logic_vector(31 downto 0); |
a_mux : in a_source_type; |
a_out : out std_logic_vector(31 downto 0); |
|
reg_target : in std_logic_vector(31 downto 0); |
b_mux : in b_source_type; |
b_out : out std_logic_vector(31 downto 0); |
|
c_bus : in std_logic_vector(31 downto 0); |
c_memory : in std_logic_vector(31 downto 0); |
c_pc : in std_logic_vector(31 downto 2); |
c_pc_plus4 : in std_logic_vector(31 downto 2); |
c_mux : in c_source_type; |
reg_dest_out : out std_logic_vector(31 downto 0); |
|
branch_func : in branch_function_type; |
take_branch : out std_logic); |
end; --entity bus_mux |
|
architecture logic of bus_mux is |
begin |
|
--Determine value of a_bus |
amux: process(reg_source, imm_in, a_mux, c_pc) |
begin |
case a_mux is |
when A_FROM_REG_SOURCE => |
a_out <= reg_source; |
when A_FROM_IMM10_6 => |
a_out <= ZERO(31 downto 5) & imm_in(10 downto 6); |
when A_FROM_PC => |
a_out <= c_pc & "00"; |
when others => |
a_out <= c_pc & "00"; |
end case; |
end process; |
|
--Determine value of b_bus |
bmux: process(reg_target, imm_in, b_mux) |
begin |
case b_mux is |
when B_FROM_REG_TARGET => |
b_out <= reg_target; |
when B_FROM_IMM => |
b_out <= ZERO(31 downto 16) & imm_in; |
when B_FROM_SIGNED_IMM => |
if imm_in(15) = '0' then |
b_out(31 downto 16) <= ZERO(31 downto 16); |
else |
b_out(31 downto 16) <= "1111111111111111"; |
end if; |
b_out(15 downto 0) <= imm_in; |
when B_FROM_IMMX4 => |
if imm_in(15) = '0' then |
b_out(31 downto 18) <= "00000000000000"; |
else |
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; |
|
--Determine value of c_bus |
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 => |
reg_dest_out <= c_bus; |
when C_FROM_MEMORY => |
reg_dest_out <= c_memory; |
when C_FROM_PC => |
reg_dest_out <= c_pc(31 downto 2) & "00"; |
when C_FROM_PC_PLUS4 => |
reg_dest_out <= c_pc_plus4 & "00"; |
when C_FROM_IMM_SHIFT16 => |
reg_dest_out <= imm_in & ZERO(15 downto 0); |
when others => |
reg_dest_out <= c_bus; |
end case; |
end process; |
|
--Determine value of take_branch |
pc_mux: process(branch_func, reg_source, reg_target) |
variable is_equal : std_logic; |
begin |
if reg_source = reg_target then |
is_equal := '1'; |
else |
is_equal := '0'; |
end if; |
case branch_func is |
when BRANCH_LTZ => |
take_branch <= reg_source(31); |
when BRANCH_LEZ => |
take_branch <= reg_source(31) or is_equal; |
when BRANCH_EQ => |
take_branch <= is_equal; |
when BRANCH_NE => |
take_branch <= not is_equal; |
when BRANCH_GEZ => |
take_branch <= not reg_source(31); |
when BRANCH_GTZ => |
take_branch <= not reg_source(31) and not is_equal; |
when BRANCH_YES => |
take_branch <= '1'; |
when others => |
take_branch <= '0'; |
end case; |
end process; |
|
end; --architecture logic |
/plasma_if.vhd
0,0 → 1,152
--------------------------------------------------------------------- |
-- TITLE: Plamsa Interface (clock divider and interface to FPGA board) |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 6/6/02 |
-- FILENAME: plasma_if.vhd |
-- PROJECT: Plasma CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- This entity divides the clock by two and interfaces to the |
-- Altera EP20K200EFC484-2X FPGA board. |
-- Xilinx Spartan-3 XC3S200FT256-4 FPGA. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
--use work.mlite_pack.all; |
|
entity plasma_if is |
port(clk_in : in std_logic; |
reset : in std_logic; |
uart_read : in std_logic; |
uart_write : out std_logic; |
|
ram_address : out std_logic_vector(31 downto 2); |
ram_data : inout std_logic_vector(31 downto 0); |
ram_ce1_n : out std_logic; |
ram_ub1_n : out std_logic; |
ram_lb1_n : out std_logic; |
ram_ce2_n : out std_logic; |
ram_ub2_n : out std_logic; |
ram_lb2_n : out std_logic; |
ram_we_n : out std_logic; |
ram_oe_n : out std_logic; |
|
gpio0_out : out std_logic_vector(31 downto 0); |
gpioA_in : in std_logic_vector(31 downto 0)); |
end; --entity plasma_if |
|
|
architecture logic of plasma_if is |
|
component plasma |
generic(memory_type : string := "XILINX_X16"; --"DUAL_PORT_" "ALTERA_LPM"; |
log_file : string := "UNUSED"); |
port(clk : in std_logic; |
reset : in std_logic; |
uart_write : out std_logic; |
uart_read : in std_logic; |
|
address : out std_logic_vector(31 downto 2); |
data_write : out std_logic_vector(31 downto 0); |
data_read : in std_logic_vector(31 downto 0); |
write_byte_enable : out std_logic_vector(3 downto 0); |
mem_pause_in : in std_logic; |
|
gpio0_out : out std_logic_vector(31 downto 0); |
gpioA_in : in std_logic_vector(31 downto 0)); |
end component; --plasma |
|
signal clk_reg : std_logic; |
signal we_n_next : std_logic; |
signal we_n_reg : std_logic; |
signal mem_address : std_logic_vector(31 downto 2); |
signal data_write : std_logic_vector(31 downto 0); |
signal data_reg : std_logic_vector(31 downto 0); |
signal write_byte_enable : std_logic_vector(3 downto 0); |
signal mem_pause_in : std_logic; |
|
begin --architecture |
--Divide 50 MHz clock by two |
clk_div: process(reset, clk_in, clk_reg, we_n_next) |
begin |
if reset = '1' then |
clk_reg <= '0'; |
elsif rising_edge(clk_in) then |
clk_reg <= not clk_reg; |
end if; |
|
if reset = '1' then |
we_n_reg <= '1'; |
data_reg <= (others => '0'); |
elsif falling_edge(clk_in) then |
we_n_reg <= we_n_next or not clk_reg; |
data_reg <= ram_data; |
end if; |
end process; --clk_div |
|
mem_pause_in <= '0'; |
ram_address <= mem_address(31 downto 2); |
ram_we_n <= we_n_reg; |
|
--For Xilinx Spartan-3 Starter Kit |
ram_control: |
process(clk_reg, mem_address, write_byte_enable, data_write) |
begin |
if mem_address(30 downto 28) = "001" then --RAM |
ram_ce1_n <= '0'; |
ram_ce2_n <= '0'; |
if write_byte_enable = "0000" then --read |
ram_data <= (others => 'Z'); |
ram_ub1_n <= '0'; |
ram_lb1_n <= '0'; |
ram_ub2_n <= '0'; |
ram_lb2_n <= '0'; |
we_n_next <= '1'; |
ram_oe_n <= '0'; |
else --write |
if clk_reg = '1' then |
ram_data <= (others => 'Z'); |
else |
ram_data <= data_write; |
end if; |
ram_ub1_n <= not write_byte_enable(3); |
ram_lb1_n <= not write_byte_enable(2); |
ram_ub2_n <= not write_byte_enable(1); |
ram_lb2_n <= not write_byte_enable(0); |
we_n_next <= '0'; |
ram_oe_n <= '1'; |
end if; |
else |
ram_data <= (others => 'Z'); |
ram_ce1_n <= '1'; |
ram_ub1_n <= '1'; |
ram_lb1_n <= '1'; |
ram_ce2_n <= '1'; |
ram_ub2_n <= '1'; |
ram_lb2_n <= '1'; |
we_n_next <= '1'; |
ram_oe_n <= '1'; |
end if; |
end process; --ram_control |
|
u1_plama: plasma |
generic map (memory_type => "XILINX_16X", |
log_file => "UNUSED") |
PORT MAP ( |
clk => clk_reg, |
reset => reset, |
uart_write => uart_write, |
uart_read => uart_read, |
|
address => mem_address, |
data_write => data_write, |
data_read => data_reg, |
write_byte_enable => write_byte_enable, |
mem_pause_in => mem_pause_in, |
|
gpio0_out => gpio0_out, |
gpioA_in => gpioA_in); |
|
end; --architecture logic |
|
/makefile
0,0 → 1,119
#Makefile for Plasma |
|
#for ModelSim |
#WORK_DIR = work |
#DEP_FILE = _primary.dat |
#COMPILE = vcom -check_synthesis |
|
#for FREE VHDL simulator http://www.symphonyeda.com |
#WARNING: vhdle now deletes the output.txt if terminated by a ^C |
WORK_DIR = work.sym |
DEP_FILE = prim.dep |
COMPILE = vhdlp -s |
|
all: $(WORK_DIR)/tbench/$(DEP_FILE) |
|
run: all |
-@del output.txt |
vhdle -t 30us tbench |
type output.txt|more |
|
run2: all |
-@del output.txt |
vhdle -t 50us tbench |
type output.txt|more |
|
run3: all |
-@del output.txt |
vhdle -t 100us tbench |
type output.txt|more |
|
opcodes: all |
make -C ..\tools opcodes |
vhdle -t 200us tbench |
@type output.txt|more |
|
simulate: all |
vhdle -s -t 10us tbench -do simili.cmd -list trace.txt |
-@..\tools\tracehex.exe |
-@start ed trace2.txt |
|
simulate2: all |
vhdle -s -t 4us tbench -do simili.cmd -list trace.txt |
-@..\tools\tracehex.exe |
-@ed trace2.txt |
|
$(WORK_DIR)/lpm_pack/$(DEP_FILE): lpm_pack.vhd |
$(COMPILE) lpm_pack.vhd |
|
$(WORK_DIR)/lpm_model/$(DEP_FILE): lpm_model.vhd |
$(COMPILE) -87 lpm_model.vhd |
|
$(WORK_DIR)/mlite_pack/$(DEP_FILE): mlite_pack.vhd |
$(COMPILE) mlite_pack.vhd |
|
$(WORK_DIR)/alu/$(DEP_FILE): mlite_pack.vhd alu.vhd |
$(COMPILE) alu.vhd |
|
$(WORK_DIR)/bus_mux/$(DEP_FILE): mlite_pack.vhd bus_mux.vhd |
$(COMPILE) bus_mux.vhd |
|
$(WORK_DIR)/control/$(DEP_FILE): mlite_pack.vhd control.vhd |
$(COMPILE) control.vhd |
|
$(WORK_DIR)/mem_ctrl/$(DEP_FILE): mlite_pack.vhd mem_ctrl.vhd |
$(COMPILE) mem_ctrl.vhd |
|
$(WORK_DIR)/mult/$(DEP_FILE): mlite_pack.vhd mult.vhd |
$(COMPILE) mult.vhd |
|
$(WORK_DIR)/pc_next/$(DEP_FILE): mlite_pack.vhd pc_next.vhd |
$(COMPILE) pc_next.vhd |
|
$(WORK_DIR)/reg_bank/$(DEP_FILE): mlite_pack.vhd reg_bank.vhd |
$(COMPILE) reg_bank.vhd |
|
$(WORK_DIR)/shifter/$(DEP_FILE): mlite_pack.vhd shifter.vhd |
$(COMPILE) shifter.vhd |
|
$(WORK_DIR)/pipeline/$(DEP_FILE): mlite_pack.vhd pipeline.vhd |
$(COMPILE) pipeline.vhd |
|
$(WORK_DIR)/mlite_cpu/$(DEP_FILE): mlite_cpu.vhd \ |
$(WORK_DIR)/mlite_pack/$(DEP_FILE) \ |
$(WORK_DIR)/alu/$(DEP_FILE) \ |
$(WORK_DIR)/bus_mux/$(DEP_FILE) \ |
$(WORK_DIR)/control/$(DEP_FILE) \ |
$(WORK_DIR)/mem_ctrl/$(DEP_FILE) \ |
$(WORK_DIR)/mult/$(DEP_FILE) \ |
$(WORK_DIR)/pc_next/$(DEP_FILE) \ |
$(WORK_DIR)/reg_bank/$(DEP_FILE) \ |
$(WORK_DIR)/shifter/$(DEP_FILE) \ |
$(WORK_DIR)/pipeline/$(DEP_FILE) |
$(COMPILE) mlite_cpu.vhd |
|
$(WORK_DIR)/ram/$(DEP_FILE): mlite_pack.vhd ram.vhd |
$(COMPILE) -87 ram.vhd |
|
$(WORK_DIR)/uart/$(DEP_FILE): mlite_pack.vhd uart.vhd |
$(COMPILE) -87 uart.vhd |
|
$(WORK_DIR)/plasma/$(DEP_FILE): mlite_pack.vhd plasma.vhd \ |
$(WORK_DIR)/mlite_cpu/$(DEP_FILE) \ |
$(WORK_DIR)/ram/$(DEP_FILE) \ |
$(WORK_DIR)/uart/$(DEP_FILE) |
$(COMPILE) plasma.vhd |
|
$(WORK_DIR)/plasma_if/$(DEP_FILE): mlite_pack.vhd plasma_if.vhd \ |
$(WORK_DIR)/plasma/$(DEP_FILE) |
$(COMPILE) plasma_if.vhd |
|
$(WORK_DIR)/tbench/$(DEP_FILE): mlite_pack.vhd tbench.vhd \ |
$(WORK_DIR)/plasma/$(DEP_FILE) \ |
$(WORK_DIR)/plasma_if/$(DEP_FILE) |
$(COMPILE) tbench.vhd |
|
altera: $(WORK_DIR)/lpm_pack/$(DEP_FILE) \ |
$(WORK_DIR)/lpm_model/$(DEP_FILE) |
echo UNUSED > UNUSED |
|
/simili.cmd
0,0 → 1,8
add list /u1/* |
#add list /u1/u1_cpu/* |
#add list /u1/u1_cpu/u8_mult/* |
#add list /u1/u1_cpu/pc /u1/u1_cpu/opcode /u1/* |
#add list /u1/u1_cpu/u3_control/* |
#add list /u1/u1_cpu/u8_mult/* |
SetListStyle nodelta collapse |
SetListInterval 0us 1ms |
simili.cmd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property