URL
https://opencores.org/ocsvn/mblite/mblite/trunk
Subversion Repositories mblite
Compare Revisions
- This comparison shows the changes necessary to convert path
/mblite
- from Rev 7 to Rev 8
- ↔ Reverse comparison
Rev 7 → Rev 8
/trunk/changelog.txt
1,3 → 1,5
[2010-03-30] Added utility sw/util/bin2vhd_32b.c |
[2010-03-30] Added utility sw/util/bin2vhd_4x8b.c |
[2010-03-31] Fixed the bug with BGT and BGE instruction |
[2010-03-31] Fixed the bug with BGT and BGE instruction |
[2010-03-31] Formatted code according to industry standards |
[2010-04-01] Fixed the bug with Carry_Keep |
/trunk/designs/core_wb/testbench.vhd
12,151 → 12,151
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
use std.textio.all; |
|
ENTITY testbench IS |
END testbench; |
entity testbench is |
end testbench; |
|
ARCHITECTURE arch OF testbench IS |
architecture arch of testbench is |
|
SIGNAL imem_o : imem_out_type; |
SIGNAL imem_i : imem_in_type; |
signal imem_o : imem_out_type; |
signal imem_i : imem_in_type; |
|
SIGNAL wb_o : wb_mst_out_type; |
SIGNAL wb_i : wb_mst_in_type; |
signal wb_o : wb_mst_out_type; |
signal wb_i : wb_mst_in_type; |
|
SIGNAL sys_clk_i : std_logic := '0'; |
SIGNAL sys_int_i : std_logic; |
SIGNAL sys_rst_i : std_logic; |
signal sys_clk_i : std_logic := '0'; |
signal sys_int_i : std_logic; |
signal sys_rst_i : std_logic; |
|
CONSTANT std_out_adr : std_logic_vector(CFG_DMEM_SIZE - 1 DOWNTO 0) := X"FFFFFFC0"; |
SIGNAL std_out_ack : std_logic; |
constant std_out_adr : std_logic_vector(CFG_DMEM_SIZE - 1 downto 0) := X"FFFFFFC0"; |
signal std_out_ack : std_logic; |
|
SIGNAL stdo_ena : std_logic; |
signal stdo_ena : std_logic; |
|
SIGNAL dmem_ena : std_logic; |
SIGNAL dmem_dat : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
SIGNAL dmem_sel : std_logic_vector(3 DOWNTO 0); |
signal dmem_ena : std_logic; |
signal dmem_dat : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
signal dmem_sel : std_logic_vector(3 downto 0); |
|
CONSTANT rom_size : integer := 16; |
CONSTANT ram_size : integer := 16; |
constant rom_size : integer := 16; |
constant ram_size : integer := 16; |
|
BEGIN |
begin |
|
sys_clk_i <= NOT sys_clk_i AFTER 10000 ps; |
sys_rst_i <= '1' AFTER 0 ps, '0' AFTER 150000 ps; |
sys_int_i <= '1' AFTER 500000000 ps, '0' after 500040000 ps; |
sys_clk_i <= not sys_clk_i after 10000 ps; |
sys_rst_i <= '1' after 0 ps, '0' after 150000 ps; |
sys_int_i <= '1' after 500000000 ps, '0' after 500040000 ps; |
|
timeout: PROCESS(sys_clk_i) |
BEGIN |
IF NOW = 10 ms THEN |
report "TIMEOUT" SEVERITY FAILURE; |
END IF; |
timeout: process(sys_clk_i) |
begin |
if NOW = 10 ms then |
report "TIMEOUT" severity FAILURE; |
end if; |
|
-- BREAK ON EXIT (0xB8000000) |
IF compare(imem_i.dat_i, "10111000000000000000000000000000") = '1' THEN |
if compare(imem_i.dat_i, "10111000000000000000000000000000") = '1' then |
-- Make sure the simulator finishes when an error is encountered. |
-- For modelsim: see menu Simulate -> Runtime options -> Assertions |
REPORT "FINISHED" SEVERITY FAILURE; |
END IF; |
END PROCESS; |
report "FINISHED" severity FAILURE; |
end if; |
end process; |
|
-- Character device |
wb_stdio_slave: PROCESS(sys_clk_i) |
VARIABLE s : line; |
VARIABLE byte : std_logic_vector(7 DOWNTO 0); |
VARIABLE char : character; |
BEGIN |
IF rising_edge(sys_clk_i) THEN |
IF (wb_o.stb_o AND wb_o.cyc_o AND compare(wb_o.adr_o, std_out_adr)) = '1' THEN |
IF wb_o.we_o = '1' AND std_out_ack = '0' THEN |
wb_stdio_slave: process(sys_clk_i) |
variable s : line; |
variable byte : std_logic_vector(7 downto 0); |
variable char : character; |
begin |
if rising_edge(sys_clk_i) then |
if (wb_o.stb_o and wb_o.cyc_o and compare(wb_o.adr_o, std_out_adr)) = '1' then |
if wb_o.we_o = '1' and std_out_ack = '0' then |
-- WRITE STDOUT |
std_out_ack <= '1'; |
CASE wb_o.sel_o IS |
WHEN "0001" => byte := wb_o.dat_o( 7 DOWNTO 0); |
WHEN "0010" => byte := wb_o.dat_o(15 DOWNTO 8); |
WHEN "0100" => byte := wb_o.dat_o(23 DOWNTO 16); |
WHEN "1000" => byte := wb_o.dat_o(31 DOWNTO 24); |
WHEN OTHERS => NULL; |
END CASE; |
case wb_o.sel_o is |
when "0001" => byte := wb_o.dat_o( 7 downto 0); |
when "0010" => byte := wb_o.dat_o(15 downto 8); |
when "0100" => byte := wb_o.dat_o(23 downto 16); |
when "1000" => byte := wb_o.dat_o(31 downto 24); |
when others => null; |
end case; |
char := character'val(my_conv_integer(byte)); |
IF byte = X"0D" THEN |
if byte = X"0D" then |
-- Ignore character 13 |
ELSIF byte = X"0A" THEN |
elsif byte = X"0A" then |
-- Writeline on character 10 (newline) |
writeline(output, s); |
ELSE |
else |
-- Write to buffer |
write(s, char); |
END IF; |
ELSIF std_out_ack = '0' THEN |
end if; |
elsif std_out_ack = '0' then |
std_out_ack <= '1'; |
END IF; |
ELSE |
end if; |
else |
std_out_ack <= '0'; |
END IF; |
END IF; |
end if; |
end if; |
|
END PROCESS; |
end process; |
|
wb_i.clk_i <= sys_clk_i; |
wb_i.rst_i <= sys_rst_i; |
wb_i.int_i <= sys_int_i; |
|
dmem_ena <= wb_o.stb_o AND wb_o.cyc_o AND NOT compare(wb_o.adr_o, std_out_adr); |
dmem_ena <= wb_o.stb_o and wb_o.cyc_o and not compare(wb_o.adr_o, std_out_adr); |
|
PROCESS(wb_o.stb_o, wb_o.cyc_o, std_out_ack, wb_o.adr_o) |
BEGIN |
IF NOT compare(wb_o.adr_o, std_out_adr) = '1' THEN |
wb_i.ack_i <= wb_o.stb_o AND wb_o.cyc_o AFTER 2 ns; |
ELSE |
wb_i.ack_i <= std_out_ack AFTER 22 ns; |
END IF; |
END PROCESS; |
process(wb_o.stb_o, wb_o.cyc_o, std_out_ack, wb_o.adr_o) |
begin |
if not compare(wb_o.adr_o, std_out_adr) = '1' then |
wb_i.ack_i <= wb_o.stb_o and wb_o.cyc_o after 2 ns; |
else |
wb_i.ack_i <= std_out_ack after 22 ns; |
end if; |
end process; |
|
imem : sram GENERIC MAP |
imem : sram generic map |
( |
WIDTH => CFG_IMEM_WIDTH, |
SIZE => rom_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => imem_i.dat_i, |
dat_i => "00000000000000000000000000000000", |
adr_i => imem_o.adr_o(rom_size - 1 DOWNTO 2), |
adr_i => imem_o.adr_o(rom_size - 1 downto 2), |
wre_i => '0', |
ena_i => imem_o.ena_o, |
clk_i => sys_clk_i |
); |
|
dmem_sel <= wb_o.sel_o WHEN wb_o.we_o = '1' ELSE (OTHERS => '0'); |
wb_i.dat_i <= X"61616161" WHEN std_out_ack = '1' ELSE dmem_dat; |
dmem_sel <= wb_o.sel_o when wb_o.we_o = '1' else (others => '0'); |
wb_i.dat_i <= X"61616161" when std_out_ack = '1' else dmem_dat; |
|
dmem : sram_4en GENERIC MAP |
dmem : sram_4en generic map |
( |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => ram_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => dmem_dat, |
dat_i => wb_o.dat_o, |
adr_i => wb_o.adr_o(ram_size - 1 DOWNTO 2), |
adr_i => wb_o.adr_o(ram_size - 1 downto 2), |
wre_i => dmem_sel, |
ena_i => dmem_ena, |
clk_i => sys_clk_i |
); |
|
core_wb0 : core_wb PORT MAP |
core_wb0 : core_wb port map |
( |
imem_o => imem_o, |
wb_o => wb_o, |
164,4 → 164,4
wb_i => wb_i |
); |
|
END arch; |
end arch; |
/trunk/designs/core_wb/config_Pkg.vhd
11,52 → 11,52
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
PACKAGE config_Pkg IS |
package config_Pkg is |
|
---------------------------------------------------------------------------------------------- |
-- CORE PARAMETERS |
---------------------------------------------------------------------------------------------- |
-- Implement external interrupt |
CONSTANT CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
constant CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
|
-- Implement hardware multiplier |
CONSTANT CFG_USE_HW_MUL : boolean := true; -- Disable or enable multiplier [0,1] |
constant CFG_USE_HW_MUL : boolean := true; -- Disable or enable multiplier [0,1] |
|
-- Implement hardware barrel shifter |
CONSTANT CFG_USE_BARREL : boolean := true; -- Disable or enable barrel shifter [0,1] |
constant CFG_USE_BARREL : boolean := true; -- Disable or enable barrel shifter [0,1] |
|
-- Debug mode |
CONSTANT CFG_DEBUG : boolean := true; -- Resets some extra registers for better readability |
constant CFG_DEBUG : boolean := true; -- Resets some extra registers for better readability |
-- and enables feedback (report) [0,1] |
-- Set CFG_DEBUG to zero to obtain best performance. |
|
-- Memory parameters |
CONSTANT CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
CONSTANT CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
CONSTANT CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
constant CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
constant CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
constant CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
|
-- Register parameters |
CONSTANT CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
CONSTANT CFG_REG_FWD_WB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
CONSTANT CFG_MEM_FWD_WB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
constant CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
constant CFG_REG_FWD_WRB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
constant CFG_MEM_FWD_WRB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
|
---------------------------------------------------------------------------------------------- |
-- CONSTANTS (currently not configurable / not tested) |
---------------------------------------------------------------------------------------------- |
CONSTANT CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
CONSTANT CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
CONSTANT CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
constant CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
constant CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
constant CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
|
---------------------------------------------------------------------------------------------- |
-- BUS PARAMETERS |
---------------------------------------------------------------------------------------------- |
|
TYPE memory_map_type IS ARRAY(natural RANGE <>) OF std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
CONSTANT CFG_NUM_SLAVES : positive := 2; |
CONSTANT CFG_MEMORY_MAP : memory_map_type(0 TO CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
type memory_map_type is array(natural range <>) of std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
constant CFG_NUM_SLAVES : positive := 2; |
constant CFG_MEMORY_MAP : memory_map_type(0 to CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
|
END config_Pkg; |
end config_Pkg; |
/trunk/designs/core_syn/testbench.vhd
11,52 → 11,52
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY std; |
USE std.textio.ALL; |
library std; |
use std.textio.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY testbench IS |
END testbench; |
entity testbench is |
end testbench; |
|
ARCHITECTURE arch OF testbench IS |
architecture arch of testbench is |
|
COMPONENT mblite_soc IS PORT |
component mblite_soc is port |
( |
sys_clk_i : in STD_LOGIC := 'X'; |
dbg_dmem_o_we_o : out STD_LOGIC; |
dbg_dmem_o_ena_o : out STD_LOGIC; |
sys_rst_i : in STD_LOGIC := 'X'; |
sys_ena_i : in STD_LOGIC := 'X'; |
sys_int_i : in STD_LOGIC := 'X'; |
dbg_dmem_o_adr_o : out STD_LOGIC_VECTOR(31 downto 0); |
dbg_dmem_o_dat_o : out STD_LOGIC_VECTOR(31 downto 0); |
dbg_dmem_o_sel_o : out STD_LOGIC_VECTOR( 3 downto 0) |
sys_clk_i : in std_logic := 'x'; |
dbg_dmem_o_we_o : out std_logic; |
dbg_dmem_o_ena_o : out std_logic; |
sys_rst_i : in std_logic := 'x'; |
sys_ena_i : in std_logic := 'x'; |
sys_int_i : in std_logic := 'x'; |
dbg_dmem_o_adr_o : out std_logic_vector(31 downto 0); |
dbg_dmem_o_dat_o : out std_logic_vector(31 downto 0); |
dbg_dmem_o_sel_o : out std_logic_vector( 3 downto 0) |
); |
END COMPONENT; |
end component; |
|
SIGNAL sys_clk_i : std_logic := '0'; |
SIGNAL sys_int_i : std_logic := '0'; |
SIGNAL sys_rst_i : std_logic := '0'; |
SIGNAL sys_ena_i : std_logic := '1'; |
signal sys_clk_i : std_logic := '0'; |
signal sys_int_i : std_logic := '0'; |
signal sys_rst_i : std_logic := '0'; |
signal sys_ena_i : std_logic := '1'; |
|
SIGNAL dmem_o : dmem_out_type; |
signal dmem_o : dmem_out_type; |
|
CONSTANT std_out_adr : std_logic_vector(CFG_DMEM_SIZE - 1 DOWNTO 0) := X"FFFFFFC0"; |
BEGIN |
constant std_out_adr : std_logic_vector(CFG_DMEM_SIZE - 1 downto 0) := X"FFFFFFC0"; |
begin |
|
sys_clk_i <= NOT sys_clk_i AFTER 10000 ps; |
sys_rst_i <= '1' AFTER 0 ps, '0' AFTER 150000 ps; |
sys_int_i <= '1' AFTER 500000000 ps, '0' after 500040000 ps; |
sys_clk_i <= not sys_clk_i after 10000 ps; |
sys_rst_i <= '1' after 0 ps, '0' after 150000 ps; |
sys_int_i <= '1' after 500000000 ps, '0' after 500040000 ps; |
|
soc : mblite_soc PORT MAP |
soc : mblite_soc port map |
( |
sys_clk_i => sys_clk_i, |
dbg_dmem_o_we_o => dmem_o.we_o, |
69,45 → 69,45
dbg_dmem_o_sel_o => dmem_o.sel_o |
); |
|
timeout: PROCESS(sys_clk_i) |
BEGIN |
IF NOW = 10 ms THEN |
REPORT "TIMEOUT" SEVERITY FAILURE; |
END IF; |
END PROCESS; |
timeout: process(sys_clk_i) |
begin |
if NOW = 10 ms then |
report "TIMEOUT" severity FAILURE; |
end if; |
end process; |
|
-- Character device |
stdio: PROCESS(sys_clk_i) |
VARIABLE s : line; |
VARIABLE byte : std_logic_vector(7 DOWNTO 0); |
VARIABLE char : character; |
BEGIN |
stdio: process(sys_clk_i) |
variable s : line; |
variable byte : std_logic_vector(7 downto 0); |
variable char : character; |
begin |
|
IF rising_edge(sys_clk_i) THEN |
IF (NOT sys_rst_i AND dmem_o.ena_o AND compare(dmem_o.adr_o, std_out_adr)) = '1' THEN |
IF dmem_o.we_o = '1' THEN |
if rising_edge(sys_clk_i) then |
if (not sys_rst_i and dmem_o.ena_o and compare(dmem_o.adr_o, std_out_adr)) = '1' then |
if dmem_o.we_o = '1' then |
-- WRITE STDOUT |
CASE dmem_o.sel_o IS |
WHEN "0001" => byte := dmem_o.dat_o( 7 DOWNTO 0); |
WHEN "0010" => byte := dmem_o.dat_o(15 DOWNTO 8); |
WHEN "0100" => byte := dmem_o.dat_o(23 DOWNTO 16); |
WHEN "1000" => byte := dmem_o.dat_o(31 DOWNTO 24); |
WHEN OTHERS => NULL; |
END CASE; |
case dmem_o.sel_o is |
when "0001" => byte := dmem_o.dat_o( 7 downto 0); |
when "0010" => byte := dmem_o.dat_o(15 downto 8); |
when "0100" => byte := dmem_o.dat_o(23 downto 16); |
when "1000" => byte := dmem_o.dat_o(31 downto 24); |
when others => null; |
end case; |
char := character'val(my_conv_integer(byte)); |
IF byte = X"0D" THEN |
if byte = X"0D" then |
-- Ignore character 13 |
ELSIF byte = X"0A" THEN |
elsif byte = X"0A" then |
-- Writeline on character 10 (newline) |
writeline(output, s); |
ELSE |
else |
-- Write to buffer |
write(s, char); |
END IF; |
END IF; |
END IF; |
END IF; |
end if; |
end if; |
end if; |
end if; |
|
END PROCESS; |
end process; |
|
END arch; |
end arch; |
/trunk/designs/core_syn/mblite_soc.vhd
11,76 → 11,76
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY mblite_soc IS PORT |
entity mblite_soc is port |
( |
sys_clk_i : IN std_logic; |
dbg_dmem_o_we_o : OUT std_logic; |
dbg_dmem_o_ena_o : OUT std_logic; |
sys_rst_i : IN std_logic; |
sys_ena_i : IN std_logic; |
sys_int_i : IN std_logic; |
dbg_dmem_o_adr_o : OUT std_logic_vector (31 DOWNTO 0); |
dbg_dmem_o_dat_o : OUT std_logic_vector (31 DOWNTO 0); |
dbg_dmem_o_sel_o : OUT std_logic_vector ( 3 DOWNTO 0) |
sys_clk_i : in std_logic; |
dbg_dmem_o_we_o : out std_logic; |
dbg_dmem_o_ena_o : out std_logic; |
sys_rst_i : in std_logic; |
sys_ena_i : in std_logic; |
sys_int_i : in std_logic; |
dbg_dmem_o_adr_o : out std_logic_vector (31 downto 0); |
dbg_dmem_o_dat_o : out std_logic_vector (31 downto 0); |
dbg_dmem_o_sel_o : out std_logic_vector ( 3 downto 0) |
); |
END mblite_soc; |
end mblite_soc; |
|
ARCHITECTURE arch OF mblite_soc IS |
architecture arch of mblite_soc is |
|
COMPONENT sram_init IS GENERIC |
component sram_init is generic |
( |
WIDTH : integer; |
SIZE : integer |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
dat_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic; |
ena_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
dat_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic; |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END COMPONENT; |
end component; |
|
COMPONENT sram_4en_init IS GENERIC |
component sram_4en_init is generic |
( |
WIDTH : integer; |
SIZE : integer |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
dat_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic_vector(3 DOWNTO 0); |
ena_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
dat_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic_vector(3 downto 0); |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END COMPONENT; |
end component; |
|
SIGNAL dmem_o : dmem_out_type; |
SIGNAL imem_o : imem_out_type; |
SIGNAL dmem_i : dmem_in_type; |
SIGNAL imem_i : imem_in_type; |
signal dmem_o : dmem_out_type; |
signal imem_o : imem_out_type; |
signal dmem_i : dmem_in_type; |
signal imem_i : imem_in_type; |
|
SIGNAL mem_enable : std_logic; |
SIGNAL sel_o : std_logic_vector(3 DOWNTO 0); |
signal mem_enable : std_logic; |
signal sel_o : std_logic_vector(3 downto 0); |
|
CONSTANT std_out_adr : std_logic_vector(CFG_DMEM_SIZE - 1 DOWNTO 0) := X"FFFFFFC0"; |
CONSTANT rom_size : integer := 13; |
CONSTANT ram_size : integer := 13; |
constant std_out_adr : std_logic_vector(CFG_DMEM_SIZE - 1 downto 0) := X"FFFFFFC0"; |
constant rom_size : integer := 13; |
constant ram_size : integer := 13; |
|
BEGIN |
begin |
|
dbg_dmem_o_we_o <= dmem_o.we_o; |
dbg_dmem_o_ena_o <= dmem_o.ena_o; |
88,34 → 88,34
dbg_dmem_o_dat_o <= dmem_o.dat_o; |
dbg_dmem_o_sel_o <= dmem_o.sel_o; |
|
imem : sram GENERIC MAP |
imem : sram generic map |
( |
WIDTH => CFG_IMEM_WIDTH, |
SIZE => rom_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => imem_i.dat_i, |
dat_i => "00000000000000000000000000000000", |
adr_i => imem_o.adr_o(rom_size - 1 DOWNTO 2), |
adr_i => imem_o.adr_o(rom_size - 1 downto 2), |
wre_i => '0', |
ena_i => imem_o.ena_o, |
clk_i => sys_clk_i |
); |
|
mem_enable <= NOT sys_rst_i AND dmem_o.ena_o AND NOT compare(dmem_o.adr_o, std_out_adr); |
sel_o <= dmem_o.sel_o WHEN dmem_o.we_o = '1' ELSE (OTHERS => '0'); |
mem_enable <= not sys_rst_i and dmem_o.ena_o and not compare(dmem_o.adr_o, std_out_adr); |
sel_o <= dmem_o.sel_o when dmem_o.we_o = '1' else (others => '0'); |
|
dmem : sram_4en GENERIC MAP |
dmem : sram_4en generic map |
( |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => ram_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => dmem_i.dat_i, |
dat_i => dmem_o.dat_o, |
adr_i => dmem_o.adr_o(ram_size - 1 DOWNTO 2), |
adr_i => dmem_o.adr_o(ram_size - 1 downto 2), |
wre_i => sel_o, |
ena_i => mem_enable, |
clk_i => sys_clk_i |
123,7 → 123,7
|
dmem_i.ena_i <= sys_ena_i; |
|
core0 : core PORT MAP |
core0 : core port map |
( |
imem_o => imem_o, |
dmem_o => dmem_o, |
133,4 → 133,4
rst_i => sys_rst_i, |
clk_i => sys_clk_i |
); |
END arch; |
end arch; |
/trunk/designs/core_syn/sram_init.vhd
11,32 → 11,32
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.std_Pkg.all; |
|
ENTITY sram_init IS GENERIC |
entity sram_init is generic |
( |
WIDTH : integer := 32; |
SIZE : integer := 11 |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
dat_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic; |
ena_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
dat_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic; |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END sram_init; |
end sram_init; |
|
ARCHITECTURE arch OF sram_init IS |
TYPE ram_type IS array (0 TO 2 ** SIZE - 1) OF std_logic_vector(WIDTH - 1 DOWNTO 0); |
SIGNAL ram : ram_type := ( |
architecture arch of sram_init is |
type ram_type is array (0 to 2 ** SIZE - 1) of std_logic_vector(WIDTH - 1 downto 0); |
signal ram : ram_type := ( |
X"B8080050",X"00000000",X"B8080728",X"00000000",X"B8080738",X"00000000",X"00000000",X"00000000", |
X"B8080730",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000", |
X"00000000",X"00000000",X"00000000",X"00000000",X"31A01028",X"30400F18",X"B0000000",X"30209038", |
294,16 → 294,16
X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000", |
X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000"); |
|
BEGIN |
PROCESS(clk_i) |
BEGIN |
IF rising_edge(clk_i) THEN |
IF notx(adr_i) AND ena_i = '1' THEN |
IF wre_i = '1' THEN |
begin |
process(clk_i) |
begin |
if rising_edge(clk_i) then |
if notx(adr_i) and ena_i = '1' then |
if wre_i = '1' then |
ram(my_conv_integer(adr_i)) <= dat_i; |
END IF; |
end if; |
dat_o <= ram(my_conv_integer(adr_i)); |
END IF; |
END IF; |
END PROCESS; |
END arch; |
end if; |
end if; |
end process; |
end arch; |
/trunk/designs/core_syn/config_Pkg.vhd
11,52 → 11,52
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
PACKAGE config_Pkg IS |
package config_Pkg is |
|
---------------------------------------------------------------------------------------------- |
-- CORE PARAMETERS |
---------------------------------------------------------------------------------------------- |
-- Implement external interrupt |
CONSTANT CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
constant CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
|
-- Implement hardware multiplier |
CONSTANT CFG_USE_HW_MUL : boolean := false; -- Disable or enable multiplier [0,1] |
constant CFG_USE_HW_MUL : boolean := false; -- Disable or enable multiplier [0,1] |
|
-- Implement hardware barrel shifter |
CONSTANT CFG_USE_BARREL : boolean := false; -- Disable or enable barrel shifter [0,1] |
constant CFG_USE_BARREL : boolean := false; -- Disable or enable barrel shifter [0,1] |
|
-- Debug mode |
CONSTANT CFG_DEBUG : boolean := false; -- Resets some extra registers for better readability |
constant CFG_DEBUG : boolean := false; -- Resets some extra registers for better readability |
-- and enables feedback (report) [0,1] |
-- Set CFG_DEBUG to zero to obtain best performance. |
|
-- Memory parameters |
CONSTANT CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
CONSTANT CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
CONSTANT CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
constant CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
constant CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
constant CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
|
-- Register parameters |
CONSTANT CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
CONSTANT CFG_REG_FWD_WB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
CONSTANT CFG_MEM_FWD_WB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
constant CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
constant CFG_REG_FWD_WRB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
constant CFG_MEM_FWD_WRB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
|
---------------------------------------------------------------------------------------------- |
-- CONSTANTS (currently not configurable / not tested) |
---------------------------------------------------------------------------------------------- |
CONSTANT CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
CONSTANT CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
CONSTANT CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
constant CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
constant CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
constant CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
|
---------------------------------------------------------------------------------------------- |
-- BUS PARAMETERS |
---------------------------------------------------------------------------------------------- |
|
TYPE memory_map_type IS ARRAY(natural RANGE <>) OF std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
CONSTANT CFG_NUM_SLAVES : positive := 2; |
CONSTANT CFG_MEMORY_MAP : memory_map_type(0 TO CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
type memory_map_type is array(natural range <>) of std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
constant CFG_NUM_SLAVES : positive := 2; |
constant CFG_MEMORY_MAP : memory_map_type(0 to CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
|
END config_Pkg; |
/trunk/designs/core_syn/sram_4en_init.vhd
13,32 → 13,32
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.std_Pkg.all; |
|
ENTITY sram_4en_init IS GENERIC |
entity sram_4en_init is generic |
( |
WIDTH : integer := 32; |
SIZE : integer := 11 |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
dat_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic_vector(3 DOWNTO 0); |
ena_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
dat_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic_vector(3 downto 0); |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END sram_4en_init; |
end sram_4en_init; |
|
ARCHITECTURE arch OF sram_4en_init IS |
TYPE ram_type IS array (0 TO 2 ** SIZE - 1) OF std_logic_vector(WIDTH - 1 DOWNTO 0); |
SIGNAL ram : ram_type := ( |
architecture arch of sram_4en_init is |
type ram_type is array (0 to 2 ** size - 1) of std_logic_vector(WIDTH - 1 downto 0); |
signal ram : ram_type := ( |
X"B8080050",X"00000000",X"B8080728",X"00000000",X"B8080738",X"00000000",X"00000000",X"00000000", |
X"B8080730",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000", |
X"00000000",X"00000000",X"00000000",X"00000000",X"31A01028",X"30400F18",X"B0000000",X"30209038", |
296,32 → 296,32
X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000", |
X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000",X"00000000"); |
|
SIGNAL di0, di1, di2, di3 : std_logic_vector(WIDTH/4 - 1 DOWNTO 0); |
BEGIN |
signal di0, di1, di2, di3 : std_logic_vector(WIDTH/4 - 1 downto 0); |
begin |
process(wre_i, dat_i, adr_i) |
begin |
if wre_i(0) = '1' then |
di0 <= dat_i(WIDTH/4 - 1 DOWNTO 0); |
di0 <= dat_i(WIDTH/4 - 1 downto 0); |
else |
di0 <= ram(my_conv_integer(adr_i))(WIDTH/4 - 1 DOWNTO 0); |
di0 <= ram(my_conv_integer(adr_i))(WIDTH/4 - 1 downto 0); |
end if; |
|
if wre_i(1) = '1' then |
di1 <= dat_i(WIDTH/2 - 1 DOWNTO WIDTH/4); |
di1 <= dat_i(WIDTH/2 - 1 downto WIDTH/4); |
else |
di1 <= ram(my_conv_integer(adr_i))(WIDTH/2 - 1 DOWNTO WIDTH/4); |
di1 <= ram(my_conv_integer(adr_i))(WIDTH/2 - 1 downto WIDTH/4); |
end if; |
|
if wre_i(2) = '1' then |
di2 <= dat_i(3*WIDTH/4 - 1 DOWNTO WIDTH/2); |
di2 <= dat_i(3*WIDTH/4 - 1 downto WIDTH/2); |
else |
di2 <= ram(my_conv_integer(adr_i))(3*WIDTH/4 - 1 DOWNTO WIDTH/2); |
di2 <= ram(my_conv_integer(adr_i))(3*WIDTH/4 - 1 downto WIDTH/2); |
end if; |
|
if wre_i(3) = '1' then |
di3 <= dat_i(WIDTH-1 DOWNTO 3*WIDTH/4); |
di3 <= dat_i(WIDTH-1 downto 3*WIDTH/4); |
else |
di3 <= ram(my_conv_integer(adr_i))(WIDTH-1 DOWNTO 3*WIDTH/4); |
di3 <= ram(my_conv_integer(adr_i))(WIDTH-1 downto 3*WIDTH/4); |
end if; |
end process; |
|
334,4 → 334,4
dat_o <= ram(my_conv_integer(adr_i)); |
end if; |
end process; |
END arch; |
end arch; |
/trunk/designs/core_decoder_wb/testbench.vhd
12,69 → 12,69
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY testbench IS |
END testbench; |
entity testbench is |
end testbench; |
|
ARCHITECTURE arch OF testbench IS |
architecture arch of testbench is |
|
COMPONENT wb_stdio IS PORT |
component wb_stdio is port |
( |
wb_o : OUT wb_slv_out_type; |
wb_i : IN wb_slv_in_type |
wb_o : out wb_slv_out_type; |
wb_i : in wb_slv_in_type |
); |
END COMPONENT; |
end component; |
|
SIGNAL dmem_o : dmem_out_type; |
SIGNAL dmem_i : dmem_in_type; |
SIGNAL imem_o : imem_out_type; |
SIGNAL imem_i : imem_in_type; |
SIGNAL s_dmem_o : dmem_out_array_type(CFG_NUM_SLAVES - 1 DOWNTO 0); |
SIGNAL s_dmem_i : dmem_in_array_type(CFG_NUM_SLAVES - 1 DOWNTO 0); |
signal dmem_o : dmem_out_type; |
signal dmem_i : dmem_in_type; |
signal imem_o : imem_out_type; |
signal imem_i : imem_in_type; |
signal s_dmem_o : dmem_out_array_type(CFG_NUM_SLAVES - 1 downto 0); |
signal s_dmem_i : dmem_in_array_type(CFG_NUM_SLAVES - 1 downto 0); |
|
SIGNAL m_wb_i : wb_mst_in_type; |
SIGNAL m_wb_o : wb_mst_out_type; |
SIGNAL s_wb_i : wb_slv_in_type; |
SIGNAL s_wb_o : wb_slv_out_type; |
signal m_wb_i : wb_mst_in_type; |
signal m_wb_o : wb_mst_out_type; |
signal s_wb_i : wb_slv_in_type; |
signal s_wb_o : wb_slv_out_type; |
|
SIGNAL sys_clk_i : std_logic := '0'; |
SIGNAL sys_int_i : std_logic; |
SIGNAL sys_rst_i : std_logic; |
signal sys_clk_i : std_logic := '0'; |
signal sys_int_i : std_logic; |
signal sys_rst_i : std_logic; |
|
CONSTANT rom_size : integer := 16; |
CONSTANT ram_size : integer := 16; |
constant rom_size : integer := 16; |
constant ram_size : integer := 16; |
|
SIGNAL sel_o : std_logic_vector(3 DOWNTO 0); |
SIGNAL ena_o : std_logic; |
signal sel_o : std_logic_vector(3 downto 0); |
signal ena_o : std_logic; |
|
BEGIN |
begin |
|
sys_clk_i <= NOT sys_clk_i AFTER 10000 ps; |
sys_rst_i <= '1' AFTER 0 ps, '0' AFTER 150000 ps; |
sys_int_i <= '1' AFTER 500000000 ps, '0' after 500040000 ps; |
sys_clk_i <= not sys_clk_i after 10000 ps; |
sys_rst_i <= '1' after 0 ps, '0' after 150000 ps; |
sys_int_i <= '1' after 500000000 ps, '0' after 500040000 ps; |
|
-- Warning: an infinite loop like while(1) {} triggers this timeout too! |
-- disable this feature when a premature finish occur. |
timeout: PROCESS(sys_clk_i) |
BEGIN |
IF NOW = 10 ms THEN |
REPORT "TIMEOUT" SEVERITY FAILURE; |
END IF; |
timeout: process(sys_clk_i) |
begin |
if NOW = 10 ms then |
report "TIMEOUT" severity FAILURE; |
end if; |
-- BREAK ON EXIT (0xB8000000) |
IF compare(imem_i.dat_i, "10111000000000000000000000000000") = '1' THEN |
if compare(imem_i.dat_i, "10111000000000000000000000000000") = '1' then |
-- Make sure the simulator finishes when an error is encountered. |
-- For modelsim: see menu Simulate -> Runtime options -> Assertions |
REPORT "FINISHED" SEVERITY FAILURE; |
END IF; |
END PROCESS; |
report "FINISHED" severity FAILURE; |
end if; |
end process; |
|
s_wb_i.clk_i <= sys_clk_i; |
s_wb_i.rst_i <= sys_rst_i; |
91,13 → 91,13
m_wb_i.ack_i <= s_wb_o.ack_o; |
m_wb_i.int_i <= s_wb_o.int_o; |
|
stdio : wb_stdio PORT MAP |
stdio : wb_stdio port map |
( |
wb_i => s_wb_i, |
wb_o => s_wb_o |
); |
|
wb_adapter : core_wb_adapter PORT MAP |
wb_adapter : core_wb_adapter port map |
( |
dmem_i => s_dmem_i(1), |
wb_o => m_wb_o, |
106,29 → 106,29
); |
|
s_dmem_i(0).ena_i <= '1'; |
sel_o <= s_dmem_o(0).sel_o WHEN s_dmem_o(0).we_o = '1' ELSE (OTHERS => '0'); |
ena_o <= NOT sys_rst_i AND s_dmem_o(0).ena_o; |
sel_o <= s_dmem_o(0).sel_o when s_dmem_o(0).we_o = '1' else (others => '0'); |
ena_o <= not sys_rst_i and s_dmem_o(0).ena_o; |
|
dmem : sram_4en GENERIC MAP |
dmem : sram_4en generic map |
( |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => ram_size - 2 |
SIZE => ram_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => s_dmem_i(0).dat_i, |
dat_i => s_dmem_o(0).dat_o, |
adr_i => s_dmem_o(0).adr_o(ram_size - 1 DOWNTO 2), |
adr_i => s_dmem_o(0).adr_o(ram_size - 1 downto 2), |
wre_i => sel_o, |
ena_i => ena_o, |
clk_i => sys_clk_i |
); |
|
decoder : core_address_decoder GENERIC MAP |
decoder : core_address_decoder generic map |
( |
G_NUM_SLAVES => CFG_NUM_SLAVES |
) |
PORT MAP |
port map |
( |
m_dmem_i => dmem_i, |
s_dmem_o => s_dmem_o, |
137,22 → 137,22
clk_i => sys_clk_i |
); |
|
imem : sram GENERIC MAP |
imem : sram generic map |
( |
WIDTH => CFG_IMEM_WIDTH, |
SIZE => rom_size - 2 |
SIZE => rom_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => imem_i.dat_i, |
dat_i => "00000000000000000000000000000000", |
adr_i => imem_o.adr_o(rom_size - 1 DOWNTO 2), |
adr_i => imem_o.adr_o(rom_size - 1 downto 2), |
wre_i => '0', |
ena_i => imem_o.ena_o, |
clk_i => sys_clk_i |
); |
|
core0 : core PORT MAP |
core0 : core port map |
( |
imem_o => imem_o, |
dmem_o => dmem_o, |
163,4 → 163,4
clk_i => sys_clk_i |
); |
|
END arch; |
end arch; |
/trunk/designs/core_decoder_wb/config_Pkg.vhd
11,52 → 11,52
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
PACKAGE config_Pkg IS |
package config_Pkg is |
|
---------------------------------------------------------------------------------------------- |
-- CORE PARAMETERS |
---------------------------------------------------------------------------------------------- |
-- Implement external interrupt |
CONSTANT CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
constant CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
|
-- Implement hardware multiplier |
CONSTANT CFG_USE_HW_MUL : boolean := true; -- Disable or enable multiplier [0,1] |
constant CFG_USE_HW_MUL : boolean := true; -- Disable or enable multiplier [0,1] |
|
-- Implement hardware barrel shifter |
CONSTANT CFG_USE_BARREL : boolean := true; -- Disable or enable barrel shifter [0,1] |
constant CFG_USE_BARREL : boolean := true; -- Disable or enable barrel shifter [0,1] |
|
-- Debug mode |
CONSTANT CFG_DEBUG : boolean := true; -- Resets some extra registers for better readability |
constant CFG_DEBUG : boolean := true; -- Resets some extra registers for better readability |
-- and enables feedback (report) [0,1] |
-- Set CFG_DEBUG to zero to obtain best performance. |
|
-- Memory parameters |
CONSTANT CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
CONSTANT CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
CONSTANT CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
constant CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
constant CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
constant CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
|
-- Register parameters |
CONSTANT CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
CONSTANT CFG_REG_FWD_WB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
CONSTANT CFG_MEM_FWD_WB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
constant CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
constant CFG_REG_FWD_WRB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
constant CFG_MEM_FWD_WRB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
|
---------------------------------------------------------------------------------------------- |
-- CONSTANTS (currently not configurable / not tested) |
---------------------------------------------------------------------------------------------- |
CONSTANT CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
CONSTANT CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
CONSTANT CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
constant CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
constant CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
constant CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
|
---------------------------------------------------------------------------------------------- |
-- BUS PARAMETERS |
---------------------------------------------------------------------------------------------- |
|
TYPE memory_map_type IS ARRAY(natural RANGE <>) OF std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
CONSTANT CFG_NUM_SLAVES : positive := 2; |
CONSTANT CFG_MEMORY_MAP : memory_map_type(0 TO CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
type memory_map_type is array(natural range <>) of std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
constant CFG_NUM_SLAVES : positive := 2; |
constant CFG_MEMORY_MAP : memory_map_type(0 to CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
|
END config_Pkg; |
end config_Pkg; |
/trunk/designs/core_decoder_wb/wb_stdio.vhd
11,84 → 11,84
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
USE std.textio.ALL; |
use std.textio.all; |
|
ENTITY wb_stdio IS PORT |
entity wb_stdio is port |
( |
wb_o : OUT wb_slv_out_type; |
wb_i : IN wb_slv_in_type |
wb_o : out wb_slv_out_type; |
wb_i : in wb_slv_in_type |
); |
END wb_stdio; |
end wb_stdio; |
|
ARCHITECTURE arch OF wb_stdio IS |
CONSTANT ack_assert_delay : TIME := 2 ns; |
CONSTANT ack_deassert_delay : TIME := 2 ns; |
SIGNAL ack : std_logic; |
SIGNAL chr_dat : std_logic_vector(31 DOWNTO 0); |
SIGNAL chr_cnt : natural := 0; |
BEGIN |
architecture arch of wb_stdio is |
constant ack_assert_delay : TIME := 2 ns; |
constant ack_deassert_delay : TIME := 2 ns; |
signal ack : std_logic; |
signal chr_dat : std_logic_vector(31 downto 0); |
signal chr_cnt : natural := 0; |
begin |
wb_o.int_o <= '0'; |
wb_o.dat_o <= chr_dat; |
-- Character device |
stdio: PROCESS(wb_i.clk_i) |
VARIABLE s : line; |
VARIABLE byte : std_logic_vector(7 DOWNTO 0); |
VARIABLE char : character; |
BEGIN |
IF rising_edge(wb_i.clk_i) THEN |
IF (wb_i.stb_i AND wb_i.cyc_i) = '1' THEN |
IF wb_i.we_i = '1' AND ack = '0' THEN |
stdio: process(wb_i.clk_i) |
variable s : line; |
variable byte : std_logic_vector(7 downto 0); |
variable char : character; |
begin |
if rising_edge(wb_i.clk_i) then |
if (wb_i.stb_i and wb_i.cyc_i) = '1' then |
if wb_i.we_i = '1' and ack = '0' then |
-- WRITE STDOUT |
wb_o.ack_o <= '1' AFTER ack_assert_delay; |
wb_o.ack_o <= '1' after ack_assert_delay; |
ack <= '1'; |
CASE wb_i.sel_i IS |
WHEN "0001" => byte := wb_i.dat_i( 7 DOWNTO 0); |
WHEN "0010" => byte := wb_i.dat_i(15 DOWNTO 8); |
WHEN "0100" => byte := wb_i.dat_i(23 DOWNTO 16); |
WHEN "1000" => byte := wb_i.dat_i(31 DOWNTO 24); |
WHEN OTHERS => NULL; |
END CASE; |
case wb_i.sel_i is |
when "0001" => byte := wb_i.dat_i( 7 downto 0); |
when "0010" => byte := wb_i.dat_i(15 downto 8); |
when "0100" => byte := wb_i.dat_i(23 downto 16); |
when "1000" => byte := wb_i.dat_i(31 downto 24); |
when others => null; |
end case; |
char := character'val(my_conv_integer(byte)); |
IF byte = X"0D" THEN |
if byte = X"0D" then |
-- Ignore character 13 |
ELSIF byte = X"0A" THEN |
elsif byte = X"0A" then |
-- Writeline on character 10 (newline) |
writeline(output, s); |
ELSE |
else |
-- Write to buffer |
write(s, char); |
END IF; |
ELSIF ack = '0' THEN |
end if; |
elsif ack = '0' then |
-- READ stdout |
ack <= '1'; |
wb_o.ack_o <= '1' AFTER ack_assert_delay; |
IF chr_cnt = 0 THEN |
wb_o.ack_o <= '1' after ack_assert_delay; |
if chr_cnt = 0 then |
chr_cnt <= 1; |
chr_dat <= X"4C4C4C4C"; |
ELSIF chr_cnt = 1 THEN |
elsif chr_cnt = 1 then |
chr_cnt <= 2; |
chr_dat <= X"4D4D4D4D"; |
ELSIF chr_cnt = 2 THEN |
elsif chr_cnt = 2 then |
chr_cnt <= 3; |
chr_dat <= X"4E4E4E4E"; |
ELSIF chr_cnt = 3 THEN |
elsif chr_cnt = 3 then |
chr_cnt <= 0; |
chr_dat <= X"0A0A0A0A"; |
END IF; |
END IF; |
ELSE |
end if; |
end if; |
else |
ack <= '0'; |
wb_o.ack_o <= '0' AFTER ack_deassert_delay; |
END IF; |
END IF; |
END PROCESS; |
END arch; |
wb_o.ack_o <= '0' after ack_deassert_delay; |
end if; |
end if; |
end process; |
end arch; |
/trunk/designs/core/testbench.vhd
12,157 → 12,157
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY std; |
USE std.textio.ALL; |
library std; |
use std.textio.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY testbench IS |
END testbench; |
entity testbench is |
end testbench; |
|
ARCHITECTURE arch OF testbench IS |
architecture arch of testbench is |
|
SIGNAL dmem_o : dmem_out_type; |
SIGNAL imem_o : imem_out_type; |
SIGNAL dmem_i : dmem_in_type; |
SIGNAL imem_i : imem_in_type; |
signal dmem_o : dmem_out_type; |
signal imem_o : imem_out_type; |
signal dmem_i : dmem_in_type; |
signal imem_i : imem_in_type; |
|
SIGNAL sys_clk_i : std_logic := '0'; |
SIGNAL sys_int_i : std_logic := '0'; |
SIGNAL sys_rst_i : std_logic := '0'; |
SIGNAL sys_ena_i : std_logic := '1'; |
signal sys_clk_i : std_logic := '0'; |
signal sys_int_i : std_logic := '0'; |
signal sys_rst_i : std_logic := '0'; |
signal sys_ena_i : std_logic := '1'; |
|
CONSTANT std_out_adr : std_logic_vector(CFG_DMEM_SIZE - 1 DOWNTO 0) := X"FFFFFFC0"; |
CONSTANT rom_size : integer := 16; |
CONSTANT ram_size : integer := 16; |
constant std_out_adr : std_logic_vector(CFG_DMEM_SIZE - 1 downto 0) := X"FFFFFFC0"; |
constant rom_size : integer := 16; |
constant ram_size : integer := 16; |
|
SIGNAL mem_enable : std_logic; |
SIGNAL chr_enable : std_logic; |
SIGNAL chr_read : std_logic; |
SIGNAL sel_o : std_logic_vector(3 DOWNTO 0); |
SIGNAL mem_dat : std_logic_vector(31 DOWNTO 0); |
SIGNAL chr_dat : std_logic_vector(31 DOWNTO 0); |
SIGNAL chr_cnt : integer := 0; |
signal mem_enable : std_logic; |
signal chr_enable : std_logic; |
signal chr_read : std_logic; |
signal sel_o : std_logic_vector(3 downto 0); |
signal mem_dat : std_logic_vector(31 downto 0); |
signal chr_dat : std_logic_vector(31 downto 0); |
signal chr_cnt : integer := 0; |
|
BEGIN |
|
sys_clk_i <= NOT sys_clk_i AFTER 10000 ps; |
sys_rst_i <= '1' AFTER 0 ps, '0' AFTER 150000 ps; |
sys_int_i <= '1' AFTER 500000000 ps, '0' after 500040000 ps; |
sys_clk_i <= not sys_clk_i after 10000 ps; |
sys_rst_i <= '1' after 0 ps, '0' after 150000 ps; |
sys_int_i <= '1' after 500000000 ps, '0' after 500040000 ps; |
|
|
dmem_i.ena_i <= sys_ena_i; |
sel_o <= dmem_o.sel_o WHEN dmem_o.we_o = '1' ELSE (OTHERS => '0'); |
sel_o <= dmem_o.sel_o when dmem_o.we_o = '1' else (others => '0'); |
|
mem_enable <= NOT sys_rst_i AND dmem_o.ena_o AND NOT compare(dmem_o.adr_o, std_out_adr); |
chr_enable <= NOT sys_rst_i AND dmem_o.ena_o AND compare(dmem_o.adr_o, std_out_adr); |
mem_enable <= not sys_rst_i and dmem_o.ena_o and not compare(dmem_o.adr_o, std_out_adr); |
chr_enable <= not sys_rst_i and dmem_o.ena_o and compare(dmem_o.adr_o, std_out_adr); |
|
dmem_i.dat_i <= chr_dat WHEN chr_read = '1' ELSE mem_dat; |
dmem_i.dat_i <= chr_dat when chr_read = '1' else mem_dat; |
|
-- Character device |
stdio: PROCESS(sys_clk_i) |
VARIABLE s : line; |
VARIABLE byte : std_logic_vector(7 DOWNTO 0); |
VARIABLE char : character; |
BEGIN |
IF rising_edge(sys_clk_i) THEN |
IF chr_enable = '1' THEN |
IF dmem_o.we_o = '1' THEN |
stdio: process(sys_clk_i) |
variable s : line; |
variable byte : std_logic_vector(7 downto 0); |
variable char : character; |
begin |
if rising_edge(sys_clk_i) then |
if chr_enable = '1' then |
if dmem_o.we_o = '1' then |
-- WRITE STDOUT |
CASE dmem_o.sel_o IS |
WHEN "0001" => byte := dmem_o.dat_o( 7 DOWNTO 0); |
WHEN "0010" => byte := dmem_o.dat_o(15 DOWNTO 8); |
WHEN "0100" => byte := dmem_o.dat_o(23 DOWNTO 16); |
WHEN "1000" => byte := dmem_o.dat_o(31 DOWNTO 24); |
WHEN OTHERS => NULL; |
END CASE; |
case dmem_o.sel_o is |
when "0001" => byte := dmem_o.dat_o( 7 downto 0); |
when "0010" => byte := dmem_o.dat_o(15 downto 8); |
when "0100" => byte := dmem_o.dat_o(23 downto 16); |
when "1000" => byte := dmem_o.dat_o(31 downto 24); |
when others => null; |
end case; |
char := character'val(my_conv_integer(byte)); |
IF byte = X"0D" THEN |
if byte = X"0D" then |
-- Ignore character 13 |
ELSIF byte = X"0A" THEN |
elsif byte = X"0A" then |
-- Writeline on character 10 (newline) |
writeline(output, s); |
ELSE |
else |
-- Write to buffer |
write(s, char); |
END IF; |
end if; |
chr_read <= '0'; |
ELSE |
else |
chr_read <= '1'; |
IF chr_cnt = 0 THEN |
if chr_cnt = 0 then |
chr_cnt <= 1; |
chr_dat <= X"4C4C4C4C"; |
ELSIF chr_cnt = 1 THEN |
elsif chr_cnt = 1 then |
chr_cnt <= 2; |
chr_dat <= X"4D4D4D4D"; |
ELSIF chr_cnt = 2 THEN |
elsif chr_cnt = 2 then |
chr_cnt <= 3; |
chr_dat <= X"4E4E4E4E"; |
ELSIF chr_cnt = 3 THEN |
elsif chr_cnt = 3 then |
chr_cnt <= 0; |
chr_dat <= X"0A0A0A0A"; |
END IF; |
END IF; |
ELSE |
end if; |
end if; |
else |
chr_read <= '0'; |
END IF; |
END IF; |
end if; |
end if; |
|
END PROCESS; |
end process; |
|
-- Warning: an infinite loop like while(1) {} triggers this timeout too! |
-- disable this feature when a premature finish occur. |
timeout: PROCESS(sys_clk_i) |
BEGIN |
IF NOW = 10 ms THEN |
REPORT "TIMEOUT" SEVERITY FAILURE; |
END IF; |
timeout: process(sys_clk_i) |
begin |
if now = 10 ms then |
report "TIMEOUT" severity FAILURE; |
end if; |
-- BREAK ON EXIT (0xB8000000) |
IF compare(imem_i.dat_i, "10111000000000000000000000000000") = '1' THEN |
if compare(imem_i.dat_i, "10111000000000000000000000000000") = '1' then |
-- Make sure the simulator finishes when an error is encountered. |
-- For modelsim: see menu Simulate -> Runtime options -> Assertions |
REPORT "FINISHED" SEVERITY FAILURE; |
END IF; |
END PROCESS; |
report "FINISHED" severity FAILURE; |
end if; |
end process; |
|
imem : sram GENERIC MAP |
imem : sram generic map |
( |
WIDTH => CFG_IMEM_WIDTH, |
SIZE => rom_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => imem_i.dat_i, |
dat_i => "00000000000000000000000000000000", |
adr_i => imem_o.adr_o(rom_size - 1 DOWNTO 2), |
adr_i => imem_o.adr_o(rom_size - 1 downto 2), |
wre_i => '0', |
ena_i => imem_o.ena_o, |
clk_i => sys_clk_i |
); |
|
dmem : sram_4en GENERIC MAP |
dmem : sram_4en generic map |
( |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => ram_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => mem_dat, |
dat_i => dmem_o.dat_o, |
adr_i => dmem_o.adr_o(ram_size - 1 DOWNTO 2), |
adr_i => dmem_o.adr_o(ram_size - 1 downto 2), |
wre_i => sel_o, |
ena_i => mem_enable, |
clk_i => sys_clk_i |
); |
|
core0 : core PORT MAP |
core0 : core port map |
( |
imem_o => imem_o, |
dmem_o => dmem_o, |
173,7 → 173,7
clk_i => sys_clk_i |
); |
|
END arch; |
end arch; |
|
---------------------------------------------------------------------------------------------- |
-- USE CONFIGURATIONS INSTEAD OF GENERICS TO IMPLEMENT - FOR EXAMPLE - DIFFERENT MEMORIES. |
180,10 → 180,10
-- CONFIGURATIONS CAN HIERARCHICALLY INVOKE OTHER CONFIGURATIONS TO REDUCE THE SIZE OF THE |
-- CONFIGURATION DECLARATION |
---------------------------------------------------------------------------------------------- |
CONFIGURATION tb_conf_example OF testbench IS |
FOR arch |
FOR ALL: sram_4en |
USE ENTITY mblite.sram_4en(arch); |
END FOR; |
END FOR; |
END tb_conf_example; |
configuration tb_conf_example of testbench is |
for arch |
for all: sram_4en |
use entity mblite.sram_4en(arch); |
end for; |
end for; |
end tb_conf_example; |
/trunk/designs/core/config_Pkg.vhd
11,52 → 11,52
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
PACKAGE config_Pkg IS |
package config_Pkg is |
|
---------------------------------------------------------------------------------------------- |
-- CORE PARAMETERS |
---------------------------------------------------------------------------------------------- |
-- Implement external interrupt |
CONSTANT CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
constant CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
|
-- Implement hardware multiplier |
CONSTANT CFG_USE_HW_MUL : boolean := true; -- Disable or enable multiplier [0,1] |
constant CFG_USE_HW_MUL : boolean := true; -- Disable or enable multiplier [0,1] |
|
-- Implement hardware barrel shifter |
CONSTANT CFG_USE_BARREL : boolean := true; -- Disable or enable barrel shifter [0,1] |
constant CFG_USE_BARREL : boolean := true; -- Disable or enable barrel shifter [0,1] |
|
-- Debug mode |
CONSTANT CFG_DEBUG : boolean := true; -- Resets some extra registers for better readability |
constant CFG_DEBUG : boolean := true; -- Resets some extra registers for better readability |
-- and enables feedback (report) [0,1] |
-- Set CFG_DEBUG to zero to obtain best performance. |
|
-- Memory parameters |
CONSTANT CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
CONSTANT CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
CONSTANT CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
constant CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
constant CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
constant CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
|
-- Register parameters |
CONSTANT CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
CONSTANT CFG_REG_FWD_WB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
CONSTANT CFG_MEM_FWD_WB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
constant CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
constant CFG_REG_FWD_WRB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
constant CFG_MEM_FWD_WRB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
|
---------------------------------------------------------------------------------------------- |
-- CONSTANTS (currently not configurable / not tested) |
---------------------------------------------------------------------------------------------- |
CONSTANT CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
CONSTANT CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
CONSTANT CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
constant CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
constant CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
constant CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
|
---------------------------------------------------------------------------------------------- |
-- BUS PARAMETERS |
---------------------------------------------------------------------------------------------- |
|
TYPE memory_map_type IS ARRAY(natural RANGE <>) OF std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
CONSTANT CFG_NUM_SLAVES : positive := 2; |
CONSTANT CFG_MEMORY_MAP : memory_map_type(0 TO CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
type memory_map_type is array(natural range <>) of std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
constant CFG_NUM_SLAVES : positive := 2; |
constant CFG_MEMORY_MAP : memory_map_type(0 to CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
|
END config_Pkg; |
end config_Pkg; |
/trunk/designs/core_decoder/testbench.vhd
12,67 → 12,67
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY testbench IS |
END testbench; |
entity testbench is |
end testbench; |
|
ARCHITECTURE arch OF testbench IS |
architecture arch of testbench is |
|
COMPONENT mblite_stdio IS PORT |
component mblite_stdio is port |
( |
dmem_i : OUT dmem_in_type; |
dmem_o : IN dmem_out_type; |
clk_i : IN std_logic |
dmem_i : out dmem_in_type; |
dmem_o : in dmem_out_type; |
clk_i : in std_logic |
); |
END COMPONENT; |
end component; |
|
SIGNAL dmem_o : dmem_out_type; |
SIGNAL dmem_i : dmem_in_type; |
SIGNAL imem_o : imem_out_type; |
SIGNAL imem_i : imem_in_type; |
SIGNAL s_dmem_o : dmem_out_array_type(CFG_NUM_SLAVES - 1 DOWNTO 0); |
SIGNAL s_dmem_i : dmem_in_array_type(CFG_NUM_SLAVES - 1 DOWNTO 0); |
signal dmem_o : dmem_out_type; |
signal dmem_i : dmem_in_type; |
signal imem_o : imem_out_type; |
signal imem_i : imem_in_type; |
signal s_dmem_o : dmem_out_array_type(CFG_NUM_SLAVES - 1 downto 0); |
signal s_dmem_i : dmem_in_array_type(CFG_NUM_SLAVES - 1 downto 0); |
|
SIGNAL sys_clk_i : std_logic := '0'; |
SIGNAL sys_int_i : std_logic; |
SIGNAL sys_rst_i : std_logic; |
signal sys_clk_i : std_logic := '0'; |
signal sys_int_i : std_logic; |
signal sys_rst_i : std_logic; |
|
CONSTANT rom_size : integer := 16; |
CONSTANT ram_size : integer := 16; |
constant rom_size : integer := 16; |
constant ram_size : integer := 16; |
|
SIGNAL sel_o : std_logic_vector(3 DOWNTO 0); |
SIGNAL ena_o : std_logic; |
signal sel_o : std_logic_vector(3 downto 0); |
signal ena_o : std_logic; |
|
BEGIN |
|
sys_clk_i <= NOT sys_clk_i AFTER 10000 ps; |
sys_rst_i <= '1' AFTER 0 ps, '0' AFTER 150000 ps; |
sys_int_i <= '1' AFTER 500000000 ps, '0' after 500040000 ps; |
sys_clk_i <= not sys_clk_i after 10000 ps; |
sys_rst_i <= '1' after 0 ps, '0' after 150000 ps; |
sys_int_i <= '1' after 500000000 ps, '0' after 500040000 ps; |
|
-- Warning: an infinite loop like while(1) {} triggers this timeout too! |
-- disable this feature when a premature finish occur. |
timeout: PROCESS(sys_clk_i) |
BEGIN |
IF NOW = 10 ms THEN |
REPORT "TIMEOUT" SEVERITY FAILURE; |
END IF; |
timeout: process(sys_clk_i) |
begin |
if NOW = 10 ms then |
report "TIMEOUT" severity FAILURE; |
end if; |
-- BREAK ON EXIT (0xB8000000) |
IF compare(imem_i.dat_i, "10111000000000000000000000000000") = '1' THEN |
if compare(imem_i.dat_i, "10111000000000000000000000000000") = '1' then |
-- Make sure the simulator finishes when an error is encountered. |
-- For modelsim: see menu Simulate -> Runtime options -> Assertions |
REPORT "FINISHED" SEVERITY FAILURE; |
END IF; |
END PROCESS; |
report "FINISHED" severity FAILURE; |
end if; |
end process; |
|
stdio : mblite_stdio PORT MAP |
stdio : mblite_stdio port map |
( |
dmem_i => s_dmem_i(1), |
dmem_o => s_dmem_o(1), |
80,29 → 80,29
); |
|
s_dmem_i(0).ena_i <= '1'; |
sel_o <= s_dmem_o(0).sel_o WHEN s_dmem_o(0).we_o = '1' ELSE (OTHERS => '0'); |
ena_o <= NOT sys_rst_i AND s_dmem_o(0).ena_o; |
sel_o <= s_dmem_o(0).sel_o when s_dmem_o(0).we_o = '1' else (others => '0'); |
ena_o <= not sys_rst_i and s_dmem_o(0).ena_o; |
|
dmem : sram_4en GENERIC MAP |
dmem : sram_4en generic map |
( |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => ram_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => s_dmem_i(0).dat_i, |
dat_i => s_dmem_o(0).dat_o, |
adr_i => s_dmem_o(0).adr_o(ram_size - 1 DOWNTO 2), |
adr_i => s_dmem_o(0).adr_o(ram_size - 1 downto 2), |
wre_i => sel_o, |
ena_i => ena_o, |
clk_i => sys_clk_i |
); |
|
decoder : core_address_decoder GENERIC MAP |
decoder : core_address_decoder generic map |
( |
G_NUM_SLAVES => CFG_NUM_SLAVES |
) |
PORT MAP |
port map |
( |
m_dmem_i => dmem_i, |
s_dmem_o => s_dmem_o, |
111,22 → 111,22
clk_i => sys_clk_i |
); |
|
imem : sram GENERIC MAP |
imem : sram generic map |
( |
WIDTH => CFG_IMEM_WIDTH, |
SIZE => rom_size - 2 |
) |
PORT MAP |
port map |
( |
dat_o => imem_i.dat_i, |
dat_i => "00000000000000000000000000000000", |
adr_i => imem_o.adr_o(rom_size - 1 DOWNTO 2), |
adr_i => imem_o.adr_o(rom_size - 1 downto 2), |
wre_i => '0', |
ena_i => imem_o.ena_o, |
clk_i => sys_clk_i |
); |
|
core0 : core PORT MAP |
core0 : core port map |
( |
imem_o => imem_o, |
dmem_o => dmem_o, |
137,4 → 137,4
clk_i => sys_clk_i |
); |
|
END arch; |
end arch; |
/trunk/designs/core_decoder/config_Pkg.vhd
11,52 → 11,52
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
PACKAGE config_Pkg IS |
package config_Pkg is |
|
---------------------------------------------------------------------------------------------- |
-- CORE PARAMETERS |
---------------------------------------------------------------------------------------------- |
-- Implement external interrupt |
CONSTANT CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
constant CFG_INTERRUPT : boolean := true; -- Disable or enable external interrupt [0,1] |
|
-- Implement hardware multiplier |
CONSTANT CFG_USE_HW_MUL : boolean := true; -- Disable or enable multiplier [0,1] |
constant CFG_USE_HW_MUL : boolean := true; -- Disable or enable multiplier [0,1] |
|
-- Implement hardware barrel shifter |
CONSTANT CFG_USE_BARREL : boolean := true; -- Disable or enable barrel shifter [0,1] |
constant CFG_USE_BARREL : boolean := true; -- Disable or enable barrel shifter [0,1] |
|
-- Debug mode |
CONSTANT CFG_DEBUG : boolean := true; -- Resets some extra registers for better readability |
constant CFG_DEBUG : boolean := true; -- Resets some extra registers for better readability |
-- and enables feedback (report) [0,1] |
-- Set CFG_DEBUG to zero to obtain best performance. |
|
-- Memory parameters |
CONSTANT CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
CONSTANT CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
CONSTANT CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
constant CFG_DMEM_SIZE : positive := 32; -- Data memory bus size in 2LOG # elements |
constant CFG_IMEM_SIZE : positive := 16; -- Instruction memory bus size in 2LOG # elements |
constant CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy |
|
-- Register parameters |
CONSTANT CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
CONSTANT CFG_REG_FWD_WB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
CONSTANT CFG_MEM_FWD_WB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
constant CFG_REG_FORCE_ZERO : boolean := true; -- Force data to zero if register address is zero [0,1] |
constant CFG_REG_FWD_WRB : boolean := true; -- Forward writeback to loosen register memory requirements [0,1] |
constant CFG_MEM_FWD_WRB : boolean := true; -- Forward memory result in stead of introducing stalls [0,1] |
|
---------------------------------------------------------------------------------------------- |
-- CONSTANTS (currently not configurable / not tested) |
---------------------------------------------------------------------------------------------- |
CONSTANT CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
CONSTANT CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
CONSTANT CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
constant CFG_DMEM_WIDTH : positive := 32; -- Data memory width in bits |
constant CFG_IMEM_WIDTH : positive := 32; -- Instruction memory width in bits |
constant CFG_GPRF_SIZE : positive := 5; -- General Purpose Register File Size in 2LOG # elements |
|
---------------------------------------------------------------------------------------------- |
-- BUS PARAMETERS |
---------------------------------------------------------------------------------------------- |
|
TYPE memory_map_type IS ARRAY(natural RANGE <>) OF std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
CONSTANT CFG_NUM_SLAVES : positive := 2; |
CONSTANT CFG_MEMORY_MAP : memory_map_type(0 TO CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
type memory_map_type is array(natural range <>) of std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
constant CFG_NUM_SLAVES : positive := 2; |
constant CFG_MEMORY_MAP : memory_map_type(0 to CFG_NUM_SLAVES) := (X"00000000", X"00FFFFFF", X"FFFFFFFF"); |
|
END config_Pkg; |
end config_Pkg; |
/trunk/designs/core_decoder/mblite_stdio.vhd
11,58 → 11,58
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
USE std.textio.ALL; |
use std.textio.all; |
|
ENTITY mblite_stdio IS PORT |
entity mblite_stdio is port |
( |
dmem_i : OUT dmem_in_type; |
dmem_o : IN dmem_out_type; |
clk_i : IN std_logic |
dmem_i : out dmem_in_type; |
dmem_o : in dmem_out_type; |
clk_i : in std_logic |
); |
END mblite_stdio; |
end mblite_stdio; |
|
ARCHITECTURE arch OF mblite_stdio IS |
BEGIN |
architecture arch of mblite_stdio is |
begin |
-- Character device |
stdio: PROCESS(clk_i) |
VARIABLE s : line; |
VARIABLE byte : std_logic_vector(7 DOWNTO 0); |
VARIABLE char : character; |
BEGIN |
dmem_i.dat_i <= (OTHERS => '0'); |
stdio: process(clk_i) |
variable s : line; |
variable byte : std_logic_vector(7 downto 0); |
variable char : character; |
begin |
dmem_i.dat_i <= (others => '0'); |
dmem_i.ena_i <= '1'; |
IF rising_edge(clk_i) THEN |
IF dmem_o.ena_o = '1' THEN |
IF dmem_o.we_o = '1' THEN |
if rising_edge(clk_i) then |
if dmem_o.ena_o = '1' then |
if dmem_o.we_o = '1' then |
-- WRITE STDOUT |
CASE dmem_o.sel_o IS |
WHEN "0001" => byte := dmem_o.dat_o( 7 DOWNTO 0); |
WHEN "0010" => byte := dmem_o.dat_o(15 DOWNTO 8); |
WHEN "0100" => byte := dmem_o.dat_o(23 DOWNTO 16); |
WHEN "1000" => byte := dmem_o.dat_o(31 DOWNTO 24); |
WHEN OTHERS => NULL; |
END CASE; |
case dmem_o.sel_o is |
when "0001" => byte := dmem_o.dat_o( 7 downto 0); |
when "0010" => byte := dmem_o.dat_o(15 downto 8); |
when "0100" => byte := dmem_o.dat_o(23 downto 16); |
when "1000" => byte := dmem_o.dat_o(31 downto 24); |
when others => null; |
end case; |
char := character'val(my_conv_integer(byte)); |
IF byte = X"0D" THEN |
if byte = x"0d" then |
-- Ignore character 13 |
ELSIF byte = X"0A" THEN |
elsif byte = x"0a" then |
-- Writeline on character 10 (newline) |
writeline(output, s); |
ELSE |
else |
-- Write to buffer |
write(s, char); |
END IF; |
END IF; |
END IF; |
END IF; |
END PROCESS; |
END arch; |
end if; |
end if; |
end if; |
end if; |
end process; |
end arch; |
/trunk/hw/core/core_wb.vhd
12,16 → 12,16
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY core_wb IS GENERIC |
entity core_wb is generic |
( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
28,21 → 28,21
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
PORT |
port |
( |
imem_o : OUT imem_out_type; |
wb_o : OUT wb_mst_out_type; |
imem_i : IN imem_in_type; |
wb_i : IN wb_mst_in_type |
imem_o : out imem_out_type; |
wb_o : out wb_mst_out_type; |
imem_i : in imem_in_type; |
wb_i : in wb_mst_in_type |
); |
END core_wb; |
end core_wb; |
|
ARCHITECTURE arch OF core_wb IS |
SIGNAL dmem_i : dmem_in_type; |
SIGNAL dmem_o : dmem_out_type; |
BEGIN |
architecture arch of core_wb is |
signal dmem_i : dmem_in_type; |
signal dmem_o : dmem_out_type; |
begin |
|
wb_adapter0 : core_wb_adapter PORT MAP |
wb_adapter0 : core_wb_adapter port map |
( |
dmem_i => dmem_i, |
wb_o => wb_o, |
50,7 → 50,7
wb_i => wb_i |
); |
|
core0 : core GENERIC MAP |
core0 : core generic map |
( |
G_INTERRUPT => G_INTERRUPT, |
G_USE_HW_MUL => G_USE_HW_MUL, |
57,7 → 57,7
G_USE_BARREL => G_USE_BARREL, |
G_DEBUG => G_DEBUG |
) |
PORT MAP |
port map |
( |
imem_o => imem_o, |
dmem_o => dmem_o, |
68,4 → 68,4
clk_i => wb_i.clk_i |
); |
|
END arch; |
end arch; |
/trunk/hw/core/core_wb_adapter.vhd
13,32 → 13,32
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY core_wb_adapter IS PORT |
entity core_wb_adapter is port |
( |
dmem_i : OUT dmem_in_type; |
wb_o : OUT wb_mst_out_type; |
dmem_o : IN dmem_out_type; |
wb_i : IN wb_mst_in_type |
dmem_i : out dmem_in_type; |
wb_o : out wb_mst_out_type; |
dmem_o : in dmem_out_type; |
wb_i : in wb_mst_in_type |
); |
END core_wb_adapter; |
end core_wb_adapter; |
|
ARCHITECTURE arch OF core_wb_adapter IS |
architecture arch of core_wb_adapter is |
|
SIGNAL r_cyc_o : std_logic; |
SIGNAL rin_cyc_o : std_logic; |
SIGNAL r_data, rin_data : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
SIGNAL s_wait : std_logic; |
signal r_cyc_o : std_logic; |
signal rin_cyc_o : std_logic; |
signal r_data, rin_data : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
signal s_wait : std_logic; |
|
BEGIN |
begin |
|
-- Direct input-output connections |
wb_o.adr_o <= dmem_o.adr_o; |
47,52 → 47,52
dmem_i.dat_i <= wb_i.dat_i; |
|
-- synchronous bus control connections |
wb_o.cyc_o <= r_cyc_o OR wb_i.ack_i; |
wb_o.cyc_o <= r_cyc_o or wb_i.ack_i; |
wb_o.stb_o <= r_cyc_o; |
|
-- asynchronous core enable connection |
dmem_i.ena_i <= '0' WHEN (dmem_o.ena_o = '1' AND rin_cyc_o = '1') OR s_wait = '1' ELSE '1'; |
dmem_i.ena_i <= '0' when (dmem_o.ena_o = '1' and rin_cyc_o = '1') or s_wait = '1' else '1'; |
wb_o.dat_o <= rin_data; |
|
-- logic for wishbone master |
wb_adapter_comb: PROCESS(wb_i, dmem_o, r_cyc_o, r_data) |
BEGIN |
wb_adapter_comb: process(wb_i, dmem_o, r_cyc_o, r_data) |
begin |
|
IF wb_i.rst_i = '1' THEN |
if wb_i.rst_i = '1' then |
-- reset bus |
rin_data <= r_data; |
rin_cyc_o <= '0'; |
s_wait <= '0'; |
ELSIF r_cyc_o = '1' AND wb_i.ack_i = '1' THEN |
elsif r_cyc_o = '1' and wb_i.ack_i = '1' then |
-- terminate wishbone cycle |
rin_data <= r_data; |
rin_cyc_o <= '0'; |
s_wait <= '0'; |
ELSIF dmem_o.ena_o = '1' AND wb_i.ack_i = '1' THEN |
elsif dmem_o.ena_o = '1' and wb_i.ack_i = '1' then |
-- wishbone bus is occuppied |
rin_data <= r_data; |
rin_cyc_o <= '1'; |
s_wait <= '1'; |
ELSIF r_cyc_o = '0' AND dmem_o.ena_o = '1' AND wb_i.ack_i = '0' THEN |
elsif r_cyc_o = '0' and dmem_o.ena_o = '1' and wb_i.ack_i = '0' then |
-- start wishbone cycle |
rin_data <= dmem_o.dat_o; |
rin_cyc_o <= '1'; |
s_wait <= '0'; |
ELSE |
else |
-- maintain wishbone cycle |
rin_data <= r_data; |
rin_cyc_o <= r_cyc_o; |
s_wait <= '0'; |
END IF; |
end if; |
|
END PROCESS; |
end process; |
|
wb_adapter_seq: PROCESS(wb_i.clk_i) |
BEGIN |
IF rising_edge(wb_i.clk_i) THEN |
wb_adapter_seq: process(wb_i.clk_i) |
begin |
if rising_edge(wb_i.clk_i) then |
r_cyc_o <= rin_cyc_o; |
r_data <= rin_data; |
END IF; |
END PROCESS; |
end if; |
end process; |
|
END arch; |
end arch; |
/trunk/hw/core/core_address_decoder.vhd
11,86 → 11,87
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY core_address_decoder IS GENERIC |
entity core_address_decoder is generic |
( |
G_NUM_SLAVES : positive := CFG_NUM_SLAVES; |
G_MEMORY_MAP : memory_map_type := CFG_MEMORY_MAP |
); |
PORT |
port |
( |
m_dmem_i : OUT dmem_in_type; |
s_dmem_o : OUT dmem_out_array_type(G_NUM_SLAVES - 1 DOWNTO 0); |
m_dmem_o : IN dmem_out_type; |
s_dmem_i : IN dmem_in_array_type(G_NUM_SLAVES - 1 DOWNTO 0); |
m_dmem_i : out dmem_in_type; |
s_dmem_o : out dmem_out_array_type(G_NUM_SLAVES - 1 downto 0); |
m_dmem_o : in dmem_out_type; |
s_dmem_i : in dmem_in_array_type(G_NUM_SLAVES - 1 downto 0); |
clk_i : std_logic |
); |
END core_address_decoder; |
end core_address_decoder; |
|
ARCHITECTURE arch OF core_address_decoder IS |
architecture arch of core_address_decoder is |
|
-- Decodes the address based on the memory map. Returns "1" if 0 or 1 slave is attached. |
FUNCTION decode(adr : std_logic_vector) RETURN std_logic_vector IS |
VARIABLE result : std_logic_vector(G_NUM_SLAVES - 1 DOWNTO 0); |
BEGIN |
result := (OTHERS => '1'); |
IF G_NUM_SLAVES > 1 AND notx(adr) THEN |
FOR i IN G_NUM_SLAVES - 1 DOWNTO 0 LOOP |
IF (adr >= G_MEMORY_MAP(i) AND adr < G_MEMORY_MAP(i+1)) THEN |
function decode(adr : std_logic_vector) return std_logic_vector is |
variable result : std_logic_vector(G_NUM_SLAVES - 1 downto 0); |
begin |
if G_NUM_SLAVES > 1 and notx(adr) then |
for i in G_NUM_SLAVES - 1 downto 0 loop |
if (adr >= G_MEMORY_MAP(i) and adr < G_MEMORY_MAP(i+1)) then |
result(i) := '1'; |
ELSE |
else |
result(i) := '0'; |
END IF; |
END LOOP; |
END IF; |
RETURN result; |
END FUNCTION; |
end if; |
end loop; |
else |
result := (others => '1'); |
end if; |
return result; |
end function; |
|
FUNCTION demux(dmem_i : dmem_in_array_type; ce, r_ce : std_logic_vector) RETURN dmem_in_type IS |
VARIABLE dmem : dmem_in_type; |
BEGIN |
function demux(dmem_i : dmem_in_array_type; ce, r_ce : std_logic_vector) return dmem_in_type is |
variable dmem : dmem_in_type; |
begin |
dmem := dmem_i(0); |
IF notx(ce) THEN |
FOR i IN G_NUM_SLAVES - 1 DOWNTO 0 LOOP |
IF ce(i) = '1' THEN |
if notx(ce) then |
for i in G_NUM_SLAVES - 1 downto 0 loop |
if ce(i) = '1' then |
dmem.ena_i := dmem_i(i).ena_i; |
END IF; |
IF r_ce(i) = '1' THEN |
end if; |
if r_ce(i) = '1' then |
dmem.dat_i := dmem_i(i).dat_i; |
END IF; |
END LOOP; |
END IF; |
RETURN dmem; |
END FUNCTION; |
end if; |
end loop; |
end if; |
return dmem; |
end function; |
|
SIGNAL r_ce, ce : std_logic_vector(G_NUM_SLAVES - 1 DOWNTO 0) := (OTHERS => '1'); |
signal r_ce, ce : std_logic_vector(G_NUM_SLAVES - 1 downto 0) := (others => '1'); |
|
BEGIN |
begin |
|
ce <= decode(m_dmem_o.adr_o); |
m_dmem_i <= demux(s_dmem_i, ce, r_ce); |
|
CON: FOR i IN G_NUM_SLAVES-1 DOWNTO 0 GENERATE |
BEGIN |
CON: for i in G_NUM_SLAVES-1 downto 0 generate |
begin |
s_dmem_o(i).dat_o <= m_dmem_o.dat_o; |
s_dmem_o(i).adr_o <= m_dmem_o.adr_o; |
s_dmem_o(i).sel_o <= m_dmem_o.sel_o; |
s_dmem_o(i).we_o <= m_dmem_o.we_o AND ce(i); |
s_dmem_o(i).ena_o <= m_dmem_o.ena_o AND ce(i); |
END GENERATE; |
s_dmem_o(i).we_o <= m_dmem_o.we_o and ce(i); |
s_dmem_o(i).ena_o <= m_dmem_o.ena_o and ce(i); |
end generate; |
|
PROCESS(clk_i) |
BEGIN |
IF rising_edge(clk_i) THEN |
process(clk_i) |
begin |
if rising_edge(clk_i) then |
r_ce <= ce; |
END IF; |
END PROCESS; |
END arch; |
end if; |
end process; |
end arch; |
/trunk/hw/core/execute.vhd
14,244 → 14,244
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY execute IS GENERIC |
entity execute is generic |
( |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL |
); |
PORT |
port |
( |
exec_o : OUT execute_out_type; |
exec_i : IN execute_in_type; |
ena_i : IN std_logic; |
rst_i : IN std_logic; |
clk_i : IN std_logic |
exec_o : out execute_out_type; |
exec_i : in execute_in_type; |
ena_i : in std_logic; |
rst_i : in std_logic; |
clk_i : in std_logic |
); |
END execute; |
end execute; |
|
ARCHITECTURE arch OF execute IS |
architecture arch of execute is |
|
TYPE execute_reg_type IS RECORD |
carry : std_logic; |
flush_ex : std_logic; |
END RECORD; |
type execute_reg_type is record |
carry : std_logic; |
flush_ex : std_logic; |
end record; |
|
SIGNAL r, rin : execute_out_type; |
SIGNAL reg, regin : execute_reg_type; |
signal r, rin : execute_out_type; |
signal reg, regin : execute_reg_type; |
|
BEGIN |
begin |
|
exec_o <= r; |
|
execute_comb: PROCESS(exec_i,exec_i.fwd_mem,exec_i.ctrl_ex, |
exec_i.ctrl_wb,exec_i.ctrl_mem, |
execute_comb: process(exec_i,exec_i.fwd_mem,exec_i.ctrl_ex, |
exec_i.ctrl_wrb,exec_i.ctrl_mem, |
exec_i.ctrl_mem.transfer_size, |
exec_i.ctrl_mem_wb,exec_i.fwd_dec, |
exec_i.ctrl_mem_wrb,exec_i.fwd_dec, |
r,r.ctrl_mem,r.ctrl_mem.transfer_size, |
r.ctrl_wb,reg) |
r.ctrl_wrb,reg) |
|
VARIABLE v : execute_out_type; |
VARIABLE v_reg : execute_reg_type; |
variable v : execute_out_type; |
variable v_reg : execute_reg_type; |
|
VARIABLE alu_src_a : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
VARIABLE alu_src_b : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
VARIABLE carry : std_logic; |
variable alu_src_a : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
variable alu_src_b : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
variable carry : std_logic; |
|
VARIABLE result : std_logic_vector(CFG_DMEM_WIDTH DOWNTO 0); |
VARIABLE result_add : std_logic_vector(CFG_DMEM_WIDTH DOWNTO 0); |
VARIABLE zero : std_logic; |
variable result : std_logic_vector(CFG_DMEM_WIDTH downto 0); |
variable result_add : std_logic_vector(CFG_DMEM_WIDTH downto 0); |
variable zero : std_logic; |
|
VARIABLE dat_a, dat_b : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
VARIABLE sel_dat_a, sel_dat_b, sel_dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
VARIABLE mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
variable dat_a, dat_b : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
variable sel_dat_a, sel_dat_b, sel_dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
variable mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
|
BEGIN |
begin |
|
v := r; |
|
sel_dat_a := select_register_data(exec_i.dat_a, exec_i.reg_a, exec_i.fwd_dec_result, forward_condition(exec_i.fwd_dec.reg_write, exec_i.fwd_dec.reg_d, exec_i.reg_a)); |
sel_dat_b := select_register_data(exec_i.dat_b, exec_i.reg_b, exec_i.fwd_dec_result, forward_condition(exec_i.fwd_dec.reg_write, exec_i.fwd_dec.reg_d, exec_i.reg_b)); |
sel_dat_d := select_register_data(exec_i.dat_d, exec_i.ctrl_wb.reg_d, exec_i.fwd_dec_result, forward_condition(exec_i.fwd_dec.reg_write, exec_i.fwd_dec.reg_d, exec_i.ctrl_wb.reg_d)); |
sel_dat_d := select_register_data(exec_i.dat_d, exec_i.ctrl_wrb.reg_d, exec_i.fwd_dec_result, forward_condition(exec_i.fwd_dec.reg_write, exec_i.fwd_dec.reg_d, exec_i.ctrl_wrb.reg_d)); |
|
IF reg.flush_ex = '1' THEN |
if reg.flush_ex = '1' then |
v.ctrl_mem.mem_write := '0'; |
v.ctrl_mem.mem_read := '0'; |
v.ctrl_wb.reg_write := '0'; |
v.ctrl_wb.reg_d := (OTHERS => '0'); |
ELSE |
v.ctrl_wrb.reg_write := '0'; |
v.ctrl_wrb.reg_d := (others => '0'); |
else |
v.ctrl_mem := exec_i.ctrl_mem; |
v.ctrl_wb := exec_i.ctrl_wb; |
END IF; |
v.ctrl_wrb := exec_i.ctrl_wrb; |
end if; |
|
IF exec_i.ctrl_mem_wb.mem_read = '1' THEN |
mem_result := align_mem_load(exec_i.mem_result, exec_i.ctrl_mem_wb.transfer_size, exec_i.alu_result(1 DOWNTO 0)); |
ELSE |
if exec_i.ctrl_mem_wrb.mem_read = '1' then |
mem_result := align_mem_load(exec_i.mem_result, exec_i.ctrl_mem_wrb.transfer_size, exec_i.alu_result(1 downto 0)); |
else |
mem_result := exec_i.alu_result; |
END IF; |
end if; |
|
IF forward_condition(r.ctrl_wb.reg_write, r.ctrl_wb.reg_d, exec_i.reg_a) = '1' THEN |
if forward_condition(r.ctrl_wrb.reg_write, r.ctrl_wrb.reg_d, exec_i.reg_a) = '1' then |
-- Forward Execution Result to REG a |
dat_a := r.alu_result; |
ELSIF forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.reg_a) = '1' THEN |
elsif forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.reg_a) = '1' then |
-- Forward Memory Result to REG a |
dat_a := mem_result; |
ELSE |
else |
-- DEFAULT: value of REG a |
dat_a := sel_dat_a; |
END IF; |
end if; |
|
IF forward_condition(r.ctrl_wb.reg_write, r.ctrl_wb.reg_d, exec_i.reg_b) = '1' THEN |
if forward_condition(r.ctrl_wrb.reg_write, r.ctrl_wrb.reg_d, exec_i.reg_b) = '1' then |
-- Forward (latched) Execution Result to REG b |
dat_b := r.alu_result; |
ELSIF forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.reg_b) = '1' THEN |
elsif forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.reg_b) = '1' then |
-- Forward Memory Result to REG b |
dat_b := mem_result; |
ELSE |
else |
-- DEFAULT: value of REG b |
dat_b := sel_dat_b; |
END IF; |
end if; |
|
IF forward_condition(r.ctrl_wb.reg_write, r.ctrl_wb.reg_d, exec_i.ctrl_wb.reg_d) = '1' THEN |
if forward_condition(r.ctrl_wrb.reg_write, r.ctrl_wrb.reg_d, exec_i.ctrl_wrb.reg_d) = '1' then |
-- Forward Execution Result to REG d |
v.dat_d := align_mem_store(r.alu_result, exec_i.ctrl_mem.transfer_size); |
ELSIF forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.ctrl_wb.reg_d) = '1' THEN |
elsif forward_condition(exec_i.fwd_mem.reg_write, exec_i.fwd_mem.reg_d, exec_i.ctrl_wrb.reg_d) = '1' then |
-- Forward Memory Result to REG d |
v.dat_d := align_mem_store(mem_result, exec_i.ctrl_mem.transfer_size); |
ELSE |
else |
-- DEFAULT: value of REG d |
v.dat_d := align_mem_store(sel_dat_d, exec_i.ctrl_mem.transfer_size); |
END IF; |
end if; |
|
-- Set the first operand of the ALU |
CASE exec_i.ctrl_ex.alu_src_a IS |
WHEN ALU_SRC_PC => alu_src_a := sign_extend(exec_i.program_counter, '0', 32); |
WHEN ALU_SRC_NOT_REGA => alu_src_a := NOT dat_a; |
WHEN ALU_SRC_ZERO => alu_src_a := (OTHERS => '0'); |
WHEN OTHERS => alu_src_a := dat_a; |
END CASE; |
case exec_i.ctrl_ex.alu_src_a is |
when ALU_SRC_PC => alu_src_a := sign_extend(exec_i.program_counter, '0', 32); |
when ALU_SRC_NOT_REGA => alu_src_a := not dat_a; |
when ALU_SRC_ZERO => alu_src_a := (others => '0'); |
when others => alu_src_a := dat_a; |
end case; |
|
-- Set the second operand of the ALU |
CASE exec_i.ctrl_ex.alu_src_b IS |
WHEN ALU_SRC_IMM => alu_src_b := exec_i.imm; |
WHEN ALU_SRC_NOT_IMM => alu_src_b := NOT exec_i.imm; |
WHEN ALU_SRC_NOT_REGB => alu_src_b := NOT dat_b; |
WHEN OTHERS => alu_src_b := dat_b; |
END CASE; |
case exec_i.ctrl_ex.alu_src_b is |
when ALU_SRC_IMM => alu_src_b := exec_i.imm; |
when ALU_SRC_NOT_IMM => alu_src_b := not exec_i.imm; |
when ALU_SRC_NOT_REGB => alu_src_b := not dat_b; |
when others => alu_src_b := dat_b; |
end case; |
|
-- Determine value of carry in |
CASE exec_i.ctrl_ex.carry IS |
WHEN CARRY_ALU => carry := reg.carry; |
WHEN CARRY_ONE => carry := '1'; |
WHEN CARRY_ARITH => carry := alu_src_a(CFG_DMEM_WIDTH - 1); |
WHEN OTHERS => carry := '0'; |
END CASE; |
case exec_i.ctrl_ex.carry is |
when CARRY_ALU => carry := reg.carry; |
when CARRY_ONE => carry := '1'; |
when CARRY_ARITH => carry := alu_src_a(CFG_DMEM_WIDTH - 1); |
when others => carry := '0'; |
end case; |
|
result_add := add(alu_src_a, alu_src_b, carry); |
|
CASE exec_i.ctrl_ex.alu_op IS |
WHEN ALU_ADD => result := result_add; |
WHEN ALU_OR => result := '0' & (alu_src_a OR alu_src_b); |
WHEN ALU_AND => result := '0' & (alu_src_a AND alu_src_b); |
WHEN ALU_XOR => result := '0' & (alu_src_a XOR alu_src_b); |
WHEN ALU_SHIFT => result := alu_src_a(0) & carry & alu_src_a(CFG_DMEM_WIDTH - 1 DOWNTO 1); |
WHEN ALU_SEXT8 => result := '0' & sign_extend(alu_src_a(7 DOWNTO 0), alu_src_a(7), 32); |
WHEN ALU_SEXT16 => result := '0' & sign_extend(alu_src_a(15 DOWNTO 0), alu_src_a(15), 32); |
WHEN ALU_MUL => |
IF G_USE_HW_MUL = true THEN |
case exec_i.ctrl_ex.alu_op is |
when ALU_ADD => result := result_add; |
when ALU_OR => result := '0' & (alu_src_a or alu_src_b); |
when ALU_AND => result := '0' & (alu_src_a and alu_src_b); |
when ALU_XOR => result := '0' & (alu_src_a xor alu_src_b); |
when ALU_SHIFT => result := alu_src_a(0) & carry & alu_src_a(CFG_DMEM_WIDTH - 1 downto 1); |
when ALU_SEXT8 => result := '0' & sign_extend(alu_src_a(7 downto 0), alu_src_a(7), 32); |
when ALU_SEXT16 => result := '0' & sign_extend(alu_src_a(15 downto 0), alu_src_a(15), 32); |
when ALU_MUL => |
if G_USE_HW_MUL = true then |
result := '0' & multiply(alu_src_a, alu_src_b); |
ELSE |
result := (OTHERS => '0'); |
END IF; |
WHEN ALU_BS => |
IF G_USE_BARREL = true THEN |
result := '0' & shift(alu_src_a, alu_src_b(4 DOWNTO 0), exec_i.imm(10), exec_i.imm(9)); |
ELSE |
result := (OTHERS => '0'); |
END IF; |
WHEN OTHERS => |
result := (OTHERS => '0'); |
REPORT "Invalid ALU operation" SEVERITY FAILURE; |
END CASE; |
else |
result := (others => '0'); |
end if; |
when ALU_BS => |
if G_USE_BARREL = true then |
result := '0' & shift(alu_src_a, alu_src_b(4 downto 0), exec_i.imm(10), exec_i.imm(9)); |
else |
result := (others => '0'); |
end if; |
when others => |
result := (others => '0'); |
report "Invalid ALU operation" severity FAILURE; |
end case; |
|
-- Set carry register |
IF exec_i.ctrl_ex.carry_keep = CARRY_KEEP THEN |
if exec_i.ctrl_ex.carry_keep = CARRY_KEEP then |
v_reg.carry := reg.carry; |
ELSE |
else |
v_reg.carry := result(CFG_DMEM_WIDTH); |
END IF; |
end if; |
|
zero := is_zero(dat_a); |
|
-- Overwrite branch condition |
IF reg.flush_ex = '1' THEN |
if reg.flush_ex = '1' then |
v.branch := '0'; |
ELSE |
else |
-- Determine branch condition |
CASE exec_i.ctrl_ex.branch_cond IS |
WHEN BNC => v.branch := '1'; |
WHEN BEQ => v.branch := zero; |
WHEN BNE => v.branch := NOT zero; |
WHEN BLT => v.branch := dat_a(CFG_DMEM_WIDTH - 1); |
WHEN BLE => v.branch := dat_a(CFG_DMEM_WIDTH - 1) OR zero; |
WHEN BGT => v.branch := NOT (dat_a(CFG_DMEM_WIDTH - 1) OR zero); |
WHEN BGE => v.branch := NOT dat_a(CFG_DMEM_WIDTH - 1); |
WHEN OTHERS => v.branch := '0'; |
END CASE; |
END IF; |
case exec_i.ctrl_ex.branch_cond is |
when BNC => v.branch := '1'; |
when BEQ => v.branch := zero; |
when BNE => v.branch := not zero; |
when BLT => v.branch := dat_a(CFG_DMEM_WIDTH - 1); |
when BLE => v.branch := dat_a(CFG_DMEM_WIDTH - 1) or zero; |
when BGT => v.branch := not (dat_a(CFG_DMEM_WIDTH - 1) or zero); |
when BGE => v.branch := not dat_a(CFG_DMEM_WIDTH - 1); |
when others => v.branch := '0'; |
end case; |
end if; |
|
-- Handle CMPU |
IF ( exec_i.ctrl_ex.operation AND NOT (alu_src_a(CFG_DMEM_WIDTH - 1) XOR alu_src_b(CFG_DMEM_WIDTH - 1))) = '1' THEN |
if ( exec_i.ctrl_ex.operation and not (alu_src_a(CFG_DMEM_WIDTH - 1) xor alu_src_b(CFG_DMEM_WIDTH - 1))) = '1' then |
-- Set MSB |
v.alu_result(CFG_DMEM_WIDTH - 1 DOWNTO 0) := (NOT result(CFG_DMEM_WIDTH - 1)) & result(CFG_DMEM_WIDTH - 2 DOWNTO 0); |
ELSE |
v.alu_result(CFG_DMEM_WIDTH - 1 downto 0) := (not result(CFG_DMEM_WIDTH - 1)) & result(CFG_DMEM_WIDTH - 2 downto 0); |
else |
-- Use ALU result |
v.alu_result := result(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
END IF; |
v.alu_result := result(CFG_DMEM_WIDTH - 1 downto 0); |
end if; |
|
v.program_counter := exec_i.program_counter; |
|
-- Determine flush signals |
v.flush_id := v.branch; |
v_reg.flush_ex := v.branch AND NOT exec_i.ctrl_ex.delay; |
v_reg.flush_ex := v.branch and not exec_i.ctrl_ex.delay; |
|
rin <= v; |
rin <= v; |
regin <= v_reg; |
|
END PROCESS; |
end process; |
|
execute_seq: PROCESS(clk_i) |
PROCEDURE proc_execute_reset IS |
BEGIN |
r.alu_result <= (OTHERS => '0'); |
r.dat_d <= (OTHERS => '0'); |
execute_seq: process(clk_i) |
procedure proc_execute_reset is |
begin |
r.alu_result <= (others => '0'); |
r.dat_d <= (others => '0'); |
r.branch <= '0'; |
r.program_counter <= (OTHERS => '0'); |
r.program_counter <= (others => '0'); |
r.flush_id <= '0'; |
r.ctrl_mem.mem_write <= '0'; |
r.ctrl_mem.mem_read <= '0'; |
r.ctrl_mem.transfer_size <= WORD; |
r.ctrl_wb.reg_d <= (OTHERS => '0'); |
r.ctrl_wb.reg_write <= '0'; |
r.ctrl_wrb.reg_d <= (others => '0'); |
r.ctrl_wrb.reg_write <= '0'; |
reg.carry <= '0'; |
reg.flush_ex <= '0'; |
END PROCEDURE proc_execute_reset; |
BEGIN |
IF rising_edge(clk_i) THEN |
IF rst_i = '1' THEN |
end procedure proc_execute_reset; |
begin |
if rising_edge(clk_i) then |
if rst_i = '1' then |
proc_execute_reset; |
ELSIF ena_i = '1' THEN |
r <= rin; |
elsif ena_i = '1' then |
r <= rin; |
reg <= regin; |
END IF; |
END IF; |
END PROCESS; |
END arch; |
end if; |
end if; |
end process; |
end arch; |
/trunk/hw/core/decode.vhd
14,16 → 14,16
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY decode IS GENERIC |
entity decode is generic |
( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
30,41 → 30,41
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
PORT |
port |
( |
decode_o : OUT decode_out_type; |
gprf_o : OUT gprf_out_type; |
decode_i : IN decode_in_type; |
ena_i : IN std_logic; |
rst_i : IN std_logic; |
clk_i : IN std_logic |
decode_o : out decode_out_type; |
gprf_o : out gprf_out_type; |
decode_i : in decode_in_type; |
ena_i : in std_logic; |
rst_i : in std_logic; |
clk_i : in std_logic |
); |
END decode; |
end decode; |
|
ARCHITECTURE arch OF decode IS |
architecture arch of decode is |
|
TYPE decode_reg_type IS RECORD |
instruction : std_logic_vector(CFG_IMEM_WIDTH - 1 DOWNTO 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
immediate : std_logic_vector(15 DOWNTO 0); |
is_immediate : std_logic; |
type decode_reg_type is record |
instruction : std_logic_vector(CFG_IMEM_WIDTH - 1 downto 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
immediate : std_logic_vector(15 downto 0); |
is_immediate : std_logic; |
msr_interrupt_enable : std_logic; |
interrupt : std_logic; |
delay_interrupt : std_logic; |
END RECORD; |
interrupt : std_logic; |
delay_interrupt : std_logic; |
end record; |
|
SIGNAL r, rin : decode_out_type; |
SIGNAL reg, regin : decode_reg_type; |
signal r, rin : decode_out_type; |
signal reg, regin : decode_reg_type; |
|
SIGNAL wb_dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
signal wb_dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
|
BEGIN |
begin |
|
decode_o.imm <= r.imm; |
|
decode_o.ctrl_ex <= r.ctrl_ex; |
decode_o.ctrl_mem <= r.ctrl_mem; |
decode_o.ctrl_wb <= r.ctrl_wb; |
decode_o.ctrl_wrb <= r.ctrl_wrb; |
|
decode_o.reg_a <= r.reg_a; |
decode_o.reg_b <= r.reg_b; |
74,70 → 74,72
decode_o.fwd_dec_result <= r.fwd_dec_result; |
decode_o.fwd_dec <= r.fwd_dec; |
|
decode_comb: PROCESS(decode_i,decode_i.ctrl_wb, |
decode_i.ctrl_mem_wb, |
decode_i.ctrl_mem_wb.transfer_size, |
decode_comb: process(decode_i,decode_i.ctrl_wrb, |
decode_i.ctrl_mem_wrb, |
decode_i.instruction, |
decode_i.ctrl_mem_wrb.transfer_size, |
r,r.ctrl_ex,r.ctrl_mem, |
r.ctrl_mem.transfer_size,r.ctrl_wb, |
r.ctrl_mem.transfer_size,r.ctrl_wrb, |
r.ctrl_wrb.reg_d, |
r.fwd_dec,reg) |
|
VARIABLE v : decode_out_type; |
VARIABLE v_reg : decode_reg_type; |
VARIABLE opcode : std_logic_vector(5 DOWNTO 0); |
VARIABLE instruction : std_logic_vector(CFG_IMEM_WIDTH - 1 DOWNTO 0); |
VARIABLE program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
VARIABLE mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
variable v : decode_out_type; |
variable v_reg : decode_reg_type; |
variable opcode : std_logic_vector(5 downto 0); |
variable instruction : std_logic_vector(CFG_IMEM_WIDTH - 1 downto 0); |
variable program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
variable mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
|
BEGIN |
begin |
v := r; |
v_reg := reg; |
|
-- Default register values (NOP) |
v_reg.immediate := (OTHERS => '0'); |
v_reg.immediate := (others => '0'); |
v_reg.is_immediate := '0'; |
v_reg.program_counter := decode_i.program_counter; |
v_reg.instruction := decode_i.instruction; |
|
IF decode_i.ctrl_mem_wb.mem_read = '1' THEN |
mem_result := align_mem_load(decode_i.mem_result, decode_i.ctrl_mem_wb.transfer_size, decode_i.alu_result(1 DOWNTO 0)); |
ELSE |
if decode_i.ctrl_mem_wrb.mem_read = '1' then |
mem_result := align_mem_load(decode_i.mem_result, decode_i.ctrl_mem_wrb.transfer_size, decode_i.alu_result(1 downto 0)); |
else |
mem_result := decode_i.alu_result; |
END IF; |
end if; |
|
wb_dat_d <= mem_result; |
|
IF G_INTERRUPT = true THEN |
if G_INTERRUPT = true then |
v_reg.delay_interrupt := '0'; |
END IF; |
end if; |
|
IF CFG_REG_FWD_WB = true THEN |
if CFG_REG_FWD_WRB = true then |
v.fwd_dec_result := mem_result; |
v.fwd_dec := decode_i.ctrl_wb; |
ELSE |
v.fwd_dec_result := (OTHERS => '0'); |
v.fwd_dec.reg_d := (OTHERS => '0'); |
v.fwd_dec := decode_i.ctrl_wrb; |
else |
v.fwd_dec_result := (others => '0'); |
v.fwd_dec.reg_d := (others => '0'); |
v.fwd_dec.reg_write := '0'; |
END IF; |
end if; |
|
IF (NOT decode_i.flush_id AND r.ctrl_mem.mem_read AND (compare(decode_i.instruction(20 DOWNTO 16), r.ctrl_wb.reg_d) OR compare(decode_i.instruction(15 DOWNTO 11), r.ctrl_wb.reg_d))) = '1' THEN |
if (not decode_i.flush_id and r.ctrl_mem.mem_read and (compare(decode_i.instruction(20 downto 16), r.ctrl_wrb.reg_d) or compare(decode_i.instruction(15 downto 11), r.ctrl_wrb.reg_d))) = '1' then |
-- A hazard occurred on register a or b |
|
-- set current instruction and program counter to 0 |
instruction := (OTHERS => '0'); |
program_counter := (OTHERS => '0'); |
instruction := (others => '0'); |
program_counter := (others => '0'); |
|
v.hazard := '1'; |
|
ELSIF CFG_MEM_FWD_WB = false AND (NOT decode_i.flush_id AND r.ctrl_mem.mem_read AND compare(decode_i.instruction(25 DOWNTO 21), r.ctrl_wb.reg_d)) = '1' THEN |
elsif CFG_MEM_FWD_WRB = false and (not decode_i.flush_id and r.ctrl_mem.mem_read and compare(decode_i.instruction(25 downto 21), r.ctrl_wrb.reg_d)) = '1' then |
-- A hazard occurred on register d |
|
-- set current instruction and program counter to 0 |
instruction := (OTHERS => '0'); |
program_counter := (OTHERS => '0'); |
instruction := (others => '0'); |
program_counter := (others => '0'); |
|
v.hazard := '1'; |
|
ELSIF r.hazard = '1' THEN |
elsif r.hazard = '1' then |
-- Recover from hazard. Insert latched instruction |
|
instruction := reg.instruction; |
144,34 → 146,34
program_counter := reg.program_counter; |
v.hazard := '0'; |
|
ELSE |
else |
|
instruction := decode_i.instruction; |
program_counter := decode_i.program_counter; |
v.hazard := '0'; |
|
END IF; |
end if; |
|
v.program_counter := program_counter; |
opcode := instruction(31 DOWNTO 26); |
v.ctrl_wb.reg_d := instruction(25 DOWNTO 21); |
v.reg_a := instruction(20 DOWNTO 16); |
v.reg_b := instruction(15 DOWNTO 11); |
opcode := instruction(31 downto 26); |
v.ctrl_wrb.reg_d := instruction(25 downto 21); |
v.reg_a := instruction(20 downto 16); |
v.reg_b := instruction(15 downto 11); |
|
-- SET IMM value |
IF reg.is_immediate = '1' THEN |
v.imm := reg.immediate & instruction(15 DOWNTO 0); |
ELSE |
v.imm := sign_extend(instruction(15 DOWNTO 0), instruction(15), 32); |
END IF; |
if reg.is_immediate = '1' then |
v.imm := reg.immediate & instruction(15 downto 0); |
else |
v.imm := sign_extend(instruction(15 downto 0), instruction(15), 32); |
end if; |
|
-- Register if an interrupt occurs |
IF G_INTERRUPT = true THEN |
IF v_reg.msr_interrupt_enable = '1' AND decode_i.interrupt = '1' THEN |
if G_INTERRUPT = true then |
if v_reg.msr_interrupt_enable = '1' and decode_i.interrupt = '1' then |
v_reg.interrupt := '1'; |
v_reg.msr_interrupt_enable := '0'; |
END IF; |
END IF; |
end if; |
end if; |
|
v.ctrl_ex.alu_op := ALU_ADD; |
v.ctrl_ex.alu_src_a := ALU_SRC_REGA; |
178,15 → 180,15
v.ctrl_ex.alu_src_b := ALU_SRC_REGB; |
v.ctrl_ex.operation := '0'; |
v.ctrl_ex.carry := CARRY_ZERO; |
v.ctrl_ex.carry_keep := CARRY_NOT_KEEP; |
v.ctrl_ex.carry_keep := CARRY_KEEP; |
v.ctrl_ex.delay := '0'; |
v.ctrl_ex.branch_cond := NOP; |
v.ctrl_mem.mem_write := '0'; |
v.ctrl_mem.transfer_size := WORD; |
v.ctrl_mem.mem_read := '0'; |
v.ctrl_wb.reg_write := '0'; |
v.ctrl_wrb.reg_write := '0'; |
|
IF G_INTERRUPT = true AND (v_reg.interrupt = '1' AND reg.delay_interrupt = '0' AND decode_i.flush_id = '0' AND v.hazard = '0' AND r.ctrl_ex.delay = '0' AND reg.is_immediate = '0') THEN |
if G_INTERRUPT = true and (v_reg.interrupt = '1' and reg.delay_interrupt = '0' and decode_i.flush_id = '0' and v.hazard = '0' and r.ctrl_ex.delay = '0' and reg.is_immediate = '0') then |
-- IF an interrupt occured |
-- AND the current instruction is not a branch or return instruction, |
-- AND the current instruction is not in a delay slot, |
194,29 → 196,29
v_reg.msr_interrupt_enable := '0'; |
v_reg.interrupt := '0'; |
|
v.reg_a := (OTHERS => '0'); |
v.reg_b := (OTHERS => '0'); |
v.reg_a := (others => '0'); |
v.reg_b := (others => '0'); |
|
v.imm := X"00000010"; |
v.ctrl_wb.reg_d := "01110"; |
v.ctrl_wrb.reg_d := "01110"; |
|
v.ctrl_ex.branch_cond := BNC; |
v.ctrl_ex.alu_src_a := ALU_SRC_ZERO; |
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
v.ctrl_wb.reg_write := '1'; |
v.ctrl_wrb.reg_write := '1'; |
|
ELSIF (decode_i.flush_id OR v.hazard) = '1' THEN |
elsif (decode_i.flush_id or v.hazard) = '1' then |
-- clearing these registers is not necessary, but facilitates debugging. |
-- On the other hand performance improves when disabled. |
IF G_DEBUG = true THEN |
v.program_counter := (OTHERS => '0'); |
v.ctrl_wb.reg_d := (OTHERS => '0'); |
v.reg_a := (OTHERS => '0'); |
v.reg_b := (OTHERS => '0'); |
v.imm := (OTHERS => '0'); |
END IF; |
if G_DEBUG = true then |
v.program_counter := (others => '0'); |
v.ctrl_wrb.reg_d := (others => '0'); |
v.reg_a := (others => '0'); |
v.reg_b := (others => '0'); |
v.imm := (others => '0'); |
end if; |
|
ELSIF is_zero(opcode(5 DOWNTO 4)) = '1' THEN |
elsif is_zero(opcode(5 downto 4)) = '1' then |
-- ADD, SUBTRACT OR COMPARE |
|
-- Alu operation |
223,141 → 225,142
v.ctrl_ex.alu_op := ALU_ADD; |
|
-- Source operand A |
IF opcode(0) = '1' THEN |
if opcode(0) = '1' then |
v.ctrl_ex.alu_src_a := ALU_SRC_NOT_REGA; |
ELSE |
else |
v.ctrl_ex.alu_src_a := ALU_SRC_REGA; |
END IF; |
end if; |
|
-- Source operand B |
IF opcode(3) = '1' THEN |
if opcode(3) = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
ELSE |
else |
v.ctrl_ex.alu_src_b := ALU_SRC_REGB; |
END IF; |
end if; |
|
IF (compare(opcode, "000101") AND instruction(1)) = '1' THEN |
if (compare(opcode, "000101") and instruction(1)) = '1' then |
v.ctrl_ex.operation := '1'; |
END IF; |
end if; |
|
-- Carry |
CASE opcode(1 DOWNTO 0) IS |
WHEN "00" => v.ctrl_ex.carry := CARRY_ZERO; |
WHEN "01" => v.ctrl_ex.carry := CARRY_ONE; |
WHEN OTHERS => v.ctrl_ex.carry := CARRY_ALU; |
END CASE; |
case opcode(1 downto 0) is |
when "00" => v.ctrl_ex.carry := CARRY_ZERO; |
when "01" => v.ctrl_ex.carry := CARRY_ONE; |
when others => v.ctrl_ex.carry := CARRY_ALU; |
end case; |
|
-- Carry keep |
IF opcode(2) = '1' THEN |
if opcode(2) = '1' then |
v.ctrl_ex.carry_keep := CARRY_KEEP; |
ELSE |
else |
v.ctrl_ex.carry_keep := CARRY_NOT_KEEP; |
END IF; |
end if; |
|
-- Flag writeback if reg_d != 0 |
v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d); |
v.ctrl_wrb.reg_write := is_not_zero(v.ctrl_wrb.reg_d); |
|
ELSIF (compare(opcode(5 DOWNTO 2), "1000") OR compare(opcode(5 DOWNTO 2), "1010")) = '1' THEN |
elsif (compare(opcode(5 downto 2), "1000") or compare(opcode(5 downto 2), "1010")) = '1' then |
-- OR, AND, XOR, ANDN |
-- ORI, ANDI, XORI, ANDNI |
CASE opcode(1 DOWNTO 0) IS |
WHEN "00" => v.ctrl_ex.alu_op := ALU_OR; |
WHEN "10" => v.ctrl_ex.alu_op := ALU_XOR; |
WHEN OTHERS => v.ctrl_ex.alu_op := ALU_AND; |
END CASE; |
case opcode(1 downto 0) is |
when "00" => v.ctrl_ex.alu_op := ALU_OR; |
when "10" => v.ctrl_ex.alu_op := ALU_XOR; |
when others => v.ctrl_ex.alu_op := ALU_AND; |
end case; |
|
IF opcode(3) = '1' AND compare(opcode(1 DOWNTO 0), "11") = '1' THEN |
if opcode(3) = '1' and compare(opcode(1 downto 0), "11") = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_NOT_IMM; |
ELSIF opcode(3) = '1' THEN |
elsif opcode(3) = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
ELSIF opcode(3) = '0' AND compare(opcode(1 DOWNTO 0), "11") = '1' THEN |
elsif opcode(3) = '0' and compare(opcode(1 downto 0), "11") = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_NOT_REGB; |
ELSE |
else |
v.ctrl_ex.alu_src_b := ALU_SRC_REGB; |
END IF; |
end if; |
|
-- Flag writeback if reg_d != 0 |
v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d); |
v.ctrl_wrb.reg_write := is_not_zero(v.ctrl_wrb.reg_d); |
|
ELSIF compare(opcode, "101100") = '1' THEN |
elsif compare(opcode, "101100") = '1' then |
-- IMM instruction |
v_reg.immediate := instruction(15 DOWNTO 0); |
v_reg.immediate := instruction(15 downto 0); |
v_reg.is_immediate := '1'; |
|
ELSIF compare(opcode, "100100") = '1' THEN |
elsif compare(opcode, "100100") = '1' then |
-- SHIFT, SIGN EXTEND |
IF compare(instruction(6 DOWNTO 5), "11") = '1' THEN |
IF instruction(0) = '1' THEN |
if compare(instruction(6 downto 5), "11") = '1' then |
if instruction(0) = '1' then |
v.ctrl_ex.alu_op:= ALU_SEXT16; |
ELSE |
else |
v.ctrl_ex.alu_op:= ALU_SEXT8; |
END IF; |
ELSE |
end if; |
else |
v.ctrl_ex.alu_op:= ALU_SHIFT; |
CASE instruction(6 DOWNTO 5) IS |
WHEN "10" => v.ctrl_ex.carry := CARRY_ZERO; |
WHEN "01" => v.ctrl_ex.carry := CARRY_ALU; |
WHEN OTHERS => v.ctrl_ex.carry := CARRY_ARITH; |
END CASE; |
END IF; |
v.ctrl_ex.carry_keep := CARRY_NOT_KEEP; |
case instruction(6 downto 5) is |
when "10" => v.ctrl_ex.carry := CARRY_ZERO; |
when "01" => v.ctrl_ex.carry := CARRY_ALU; |
when others => v.ctrl_ex.carry := CARRY_ARITH; |
end case; |
end if; |
|
-- Flag writeback if reg_d != 0 |
v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d); |
v.ctrl_wrb.reg_write := is_not_zero(v.ctrl_wrb.reg_d); |
|
ELSIF (compare(opcode, "100110") OR compare(opcode, "101110")) = '1' THEN |
elsif (compare(opcode, "100110") or compare(opcode, "101110")) = '1' then |
-- BRANCH UNCONDITIONAL |
|
v.ctrl_ex.branch_cond := BNC; |
|
IF opcode(3) = '1' THEN |
if opcode(3) = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
ELSE |
else |
v.ctrl_ex.alu_src_b := ALU_SRC_REGB; |
END IF; |
end if; |
|
-- WRITE THE RESULT ALSO TO REGISTER D |
IF v.reg_a(2) = '1' THEN |
if v.reg_a(2) = '1' then |
-- Flag writeback if reg_d != 0 |
v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d); |
END IF; |
v.ctrl_wrb.reg_write := is_not_zero(v.ctrl_wrb.reg_d); |
end if; |
|
IF v.reg_a(3) = '1' THEN |
if v.reg_a(3) = '1' then |
v.ctrl_ex.alu_src_a := ALU_SRC_ZERO; |
ELSE |
else |
v.ctrl_ex.alu_src_a := ALU_SRC_PC; |
END IF; |
end if; |
|
IF G_INTERRUPT = true THEN |
if G_INTERRUPT = true then |
v_reg.delay_interrupt := '1'; |
END IF; |
end if; |
v.ctrl_ex.delay := v.reg_a(4); |
|
ELSIF (compare(opcode, "100111") OR compare(opcode, "101111")) = '1' THEN |
elsif (compare(opcode, "100111") or compare(opcode, "101111")) = '1' then |
-- BRANCH CONDITIONAL |
v.ctrl_ex.alu_op := ALU_ADD; |
v.ctrl_ex.alu_src_a := ALU_SRC_PC; |
|
IF opcode(3) = '1' THEN |
if opcode(3) = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
ELSE |
else |
v.ctrl_ex.alu_src_b := ALU_SRC_REGB; |
END IF; |
end if; |
|
CASE v.ctrl_wb.reg_d(2 DOWNTO 0) IS |
WHEN "000" => v.ctrl_ex.branch_cond := BEQ; |
WHEN "001" => v.ctrl_ex.branch_cond := BNE; |
WHEN "010" => v.ctrl_ex.branch_cond := BLT; |
WHEN "011" => v.ctrl_ex.branch_cond := BLE; |
WHEN "100" => v.ctrl_ex.branch_cond := BGT; |
WHEN OTHERS => v.ctrl_ex.branch_cond := BGE; |
END CASE; |
case v.ctrl_wrb.reg_d(2 downto 0) is |
when "000" => v.ctrl_ex.branch_cond := BEQ; |
when "001" => v.ctrl_ex.branch_cond := BNE; |
when "010" => v.ctrl_ex.branch_cond := BLT; |
when "011" => v.ctrl_ex.branch_cond := BLE; |
when "100" => v.ctrl_ex.branch_cond := BGT; |
when others => v.ctrl_ex.branch_cond := BGE; |
end case; |
|
IF G_INTERRUPT = true THEN |
if G_INTERRUPT = true then |
v_reg.delay_interrupt := '1'; |
END IF; |
v.ctrl_ex.delay := v.ctrl_wb.reg_d(4); |
end if; |
v.ctrl_ex.delay := v.ctrl_wrb.reg_d(4); |
|
ELSIF compare(opcode, "101101") = '1' THEN |
elsif compare(opcode, "101101") = '1' then |
-- RETURN |
|
v.ctrl_ex.branch_cond := BNC; |
364,133 → 367,133
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
v.ctrl_ex.delay := '1'; |
|
IF G_INTERRUPT = true THEN |
IF v.ctrl_wb.reg_d(0) = '1' THEN |
if G_INTERRUPT = true then |
if v.ctrl_wrb.reg_d(0) = '1' then |
v_reg.msr_interrupt_enable := '1'; |
END IF; |
end if; |
v_reg.delay_interrupt := '1'; |
END IF; |
end if; |
|
ELSIF compare(opcode(5 DOWNTO 4), "11") = '1' THEN |
elsif compare(opcode(5 downto 4), "11") = '1' then |
-- SW, LW |
v.ctrl_ex.alu_op := ALU_ADD; |
v.ctrl_ex.alu_src_a := ALU_SRC_REGA; |
|
IF opcode(3) = '1' THEN |
if opcode(3) = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
ELSE |
else |
v.ctrl_ex.alu_src_b := ALU_SRC_REGB; |
END IF; |
end if; |
|
v.ctrl_ex.carry := CARRY_ZERO; |
|
IF opcode(2) = '1' THEN |
if opcode(2) = '1' then |
-- Store |
v.ctrl_mem.mem_write := '1'; |
v.ctrl_mem.mem_read := '0'; |
v.ctrl_wb.reg_write := '0'; |
ELSE |
v.ctrl_mem.mem_read := '0'; |
v.ctrl_wrb.reg_write := '0'; |
else |
-- Load |
v.ctrl_mem.mem_write := '0'; |
v.ctrl_mem.mem_read := '1'; |
v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d); |
END IF; |
v.ctrl_mem.mem_read := '1'; |
v.ctrl_wrb.reg_write := is_not_zero(v.ctrl_wrb.reg_d); |
end if; |
|
CASE opcode(1 DOWNTO 0) IS |
WHEN "00" => v.ctrl_mem.transfer_size := BYTE; |
WHEN "01" => v.ctrl_mem.transfer_size := HALFWORD; |
WHEN OTHERS => v.ctrl_mem.transfer_size := WORD; |
END CASE; |
case opcode(1 downto 0) is |
when "00" => v.ctrl_mem.transfer_size := BYTE; |
when "01" => v.ctrl_mem.transfer_size := HALFWORD; |
when others => v.ctrl_mem.transfer_size := WORD; |
end case; |
|
v.ctrl_ex.delay := '0'; |
|
ELSIF G_USE_HW_MUL = true AND (compare(opcode, "010000") OR compare(opcode, "011000")) = '1' THEN |
elsif G_USE_HW_MUL = true and (compare(opcode, "010000") or compare(opcode, "011000")) = '1' then |
|
v.ctrl_ex.alu_op := ALU_MUL; |
|
IF opcode(3) = '1' THEN |
if opcode(3) = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
ELSE |
else |
v.ctrl_ex.alu_src_b := ALU_SRC_REGB; |
END IF; |
end if; |
|
v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d); |
v.ctrl_wrb.reg_write := is_not_zero(v.ctrl_wrb.reg_d); |
|
ELSIF G_USE_BARREL = true AND (compare(opcode, "010001") OR compare(opcode, "011001")) = '1' THEN |
elsif G_USE_BARREL = true and (compare(opcode, "010001") or compare(opcode, "011001")) = '1' then |
|
v.ctrl_ex.alu_op := ALU_BS; |
|
IF opcode(3) = '1' THEN |
if opcode(3) = '1' then |
v.ctrl_ex.alu_src_b := ALU_SRC_IMM; |
ELSE |
else |
v.ctrl_ex.alu_src_b := ALU_SRC_REGB; |
END IF; |
end if; |
|
v.ctrl_wb.reg_write := is_not_zero(v.ctrl_wb.reg_d); |
v.ctrl_wrb.reg_write := is_not_zero(v.ctrl_wrb.reg_d); |
|
ELSE |
else |
-- UNKNOWN OPCODE |
NULL; |
END IF; |
null; |
end if; |
|
rin <= v; |
regin <= v_reg; |
|
END PROCESS; |
end process; |
|
decode_seq: PROCESS(clk_i) |
PROCEDURE proc_reset_decode IS |
BEGIN |
r.reg_a <= (OTHERS => '0'); |
r.reg_b <= (OTHERS => '0'); |
r.imm <= (OTHERS => '0'); |
r.program_counter <= (OTHERS => '0'); |
r.hazard <= '0'; |
r.ctrl_ex.alu_op <= ALU_ADD; |
r.ctrl_ex.alu_src_a <= ALU_SRC_REGA; |
r.ctrl_ex.alu_src_b <= ALU_SRC_REGB; |
r.ctrl_ex.operation <= '0'; |
r.ctrl_ex.carry <= CARRY_ZERO; |
r.ctrl_ex.carry_keep <= CARRY_NOT_KEEP; |
r.ctrl_ex.delay <= '0'; |
r.ctrl_ex.branch_cond <= NOP; |
r.ctrl_mem.mem_write <= '0'; |
r.ctrl_mem.transfer_size <= WORD; |
r.ctrl_mem.mem_read <= '0'; |
r.ctrl_wb.reg_d <= (OTHERS => '0'); |
r.ctrl_wb.reg_write <= '0'; |
r.fwd_dec_result <= (OTHERS => '0'); |
r.fwd_dec.reg_d <= (OTHERS => '0'); |
r.fwd_dec.reg_write <= '0'; |
reg.instruction <= (OTHERS => '0'); |
reg.program_counter <= (OTHERS => '0'); |
reg.immediate <= (OTHERS => '0'); |
reg.is_immediate <= '0'; |
reg.msr_interrupt_enable <= '1'; |
reg.interrupt <= '0'; |
reg.delay_interrupt <= '0'; |
END PROCEDURE proc_reset_decode; |
BEGIN |
IF rising_edge(clk_i) THEN |
IF rst_i = '1' THEN |
decode_seq: process(clk_i) |
procedure proc_reset_decode is |
begin |
r.reg_a <= (others => '0'); |
r.reg_b <= (others => '0'); |
r.imm <= (others => '0'); |
r.program_counter <= (others => '0'); |
r.hazard <= '0'; |
r.ctrl_ex.alu_op <= ALU_ADD; |
r.ctrl_ex.alu_src_a <= ALU_SRC_REGA; |
r.ctrl_ex.alu_src_b <= ALU_SRC_REGB; |
r.ctrl_ex.operation <= '0'; |
r.ctrl_ex.carry <= CARRY_ZERO; |
r.ctrl_ex.carry_keep <= CARRY_NOT_KEEP; |
r.ctrl_ex.delay <= '0'; |
r.ctrl_ex.branch_cond <= NOP; |
r.ctrl_mem.mem_write <= '0'; |
r.ctrl_mem.transfer_size <= WORD; |
r.ctrl_mem.mem_read <= '0'; |
r.ctrl_wrb.reg_d <= (others => '0'); |
r.ctrl_wrb.reg_write <= '0'; |
r.fwd_dec_result <= (others => '0'); |
r.fwd_dec.reg_d <= (others => '0'); |
r.fwd_dec.reg_write <= '0'; |
reg.instruction <= (others => '0'); |
reg.program_counter <= (others => '0'); |
reg.immediate <= (others => '0'); |
reg.is_immediate <= '0'; |
reg.msr_interrupt_enable <= '1'; |
reg.interrupt <= '0'; |
reg.delay_interrupt <= '0'; |
end procedure proc_reset_decode; |
begin |
if rising_edge(clk_i) then |
if rst_i = '1' then |
proc_reset_decode; |
ELSIF ena_i = '1' THEN |
elsif ena_i = '1' then |
r <= rin; |
reg <= regin; |
END IF; |
END IF; |
END PROCESS; |
end if; |
end if; |
end process; |
|
gprf0 : gprf PORT MAP |
gprf0 : gprf port map |
( |
gprf_o => gprf_o, |
gprf_i.adr_a_i => rin.reg_a, |
gprf_i.adr_b_i => rin.reg_b, |
gprf_i.adr_d_i => rin.ctrl_wb.reg_d, |
gprf_i.adr_d_i => rin.ctrl_wrb.reg_d, |
gprf_i.dat_w_i => wb_dat_d, |
gprf_i.adr_w_i => decode_i.ctrl_wb.reg_d, |
gprf_i.wre_i => decode_i.ctrl_wb.reg_write, |
gprf_i.adr_w_i => decode_i.ctrl_wrb.reg_d, |
gprf_i.wre_i => decode_i.ctrl_wrb.reg_write, |
ena_i => ena_i, |
clk_i => clk_i |
); |
END arch; |
end arch; |
/trunk/hw/core/core.vhd
12,15 → 12,15
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
|
ENTITY core IS GENERIC |
entity core is generic |
( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
27,45 → 27,45
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
PORT |
port |
( |
imem_o : OUT imem_out_type; |
dmem_o : OUT dmem_out_type; |
imem_i : IN imem_in_type; |
dmem_i : IN dmem_in_type; |
int_i : IN std_logic; |
rst_i : IN std_logic; |
clk_i : IN std_logic |
imem_o : out imem_out_type; |
dmem_o : out dmem_out_type; |
imem_i : in imem_in_type; |
dmem_i : in dmem_in_type; |
int_i : in std_logic; |
rst_i : in std_logic; |
clk_i : in std_logic |
); |
END core; |
end core; |
|
ARCHITECTURE arch OF core IS |
architecture arch of core is |
|
SIGNAL fetch_i : fetch_in_type; |
SIGNAL fetch_o : fetch_out_type; |
signal fetch_i : fetch_in_type; |
signal fetch_o : fetch_out_type; |
|
SIGNAL decode_i : decode_in_type; |
SIGNAL decode_o : decode_out_type; |
signal decode_i : decode_in_type; |
signal decode_o : decode_out_type; |
|
SIGNAL gprf_o : gprf_out_type; |
signal gprf_o : gprf_out_type; |
|
SIGNAL exec_i : execute_in_type; |
SIGNAL exec_o : execute_out_type; |
signal exec_i : execute_in_type; |
signal exec_o : execute_out_type; |
|
SIGNAL mem_i : mem_in_type; |
SIGNAL mem_o : mem_out_type; |
signal mem_i : mem_in_type; |
signal mem_o : mem_out_type; |
|
SIGNAL ena_i : std_logic; |
signal ena_i : std_logic; |
|
BEGIN |
begin |
|
ena_i <= dmem_i.ena_i; |
|
fetch_i.hazard <= decode_o.hazard; |
fetch_i.branch <= exec_o.branch; |
fetch_i.branch_target <= exec_o.alu_result(CFG_IMEM_SIZE - 1 DOWNTO 0); |
fetch_i.branch_target <= exec_o.alu_result(CFG_IMEM_SIZE - 1 downto 0); |
|
fetch0 : fetch PORT MAP |
fetch0 : fetch port map |
( |
fetch_o => fetch_o, |
imem_o => imem_o, |
77,14 → 77,14
|
decode_i.program_counter <= fetch_o.program_counter; |
decode_i.instruction <= imem_i.dat_i; |
decode_i.ctrl_wb <= mem_o.ctrl_wb; |
decode_i.ctrl_mem_wb <= mem_o.ctrl_mem_wb; |
decode_i.ctrl_wrb <= mem_o.ctrl_wrb; |
decode_i.ctrl_mem_wrb <= mem_o.ctrl_mem_wrb; |
decode_i.mem_result <= dmem_i.dat_i; |
decode_i.alu_result <= mem_o.alu_result; |
decode_i.interrupt <= int_i; |
decode_i.flush_id <= exec_o.flush_id; |
|
decode0: decode GENERIC MAP |
decode0: decode generic map |
( |
G_INTERRUPT => G_INTERRUPT, |
G_USE_HW_MUL => G_USE_HW_MUL, |
91,7 → 91,7
G_USE_BARREL => G_USE_BARREL, |
G_DEBUG => G_DEBUG |
) |
PORT MAP |
port map |
( |
decode_o => decode_o, |
decode_i => decode_i, |
112,21 → 112,21
|
exec_i.imm <= decode_o.imm; |
exec_i.program_counter <= decode_o.program_counter; |
exec_i.ctrl_wb <= decode_o.ctrl_wb; |
exec_i.ctrl_wrb <= decode_o.ctrl_wrb; |
exec_i.ctrl_mem <= decode_o.ctrl_mem; |
exec_i.ctrl_ex <= decode_o.ctrl_ex; |
|
exec_i.fwd_mem <= mem_o.ctrl_wb; |
exec_i.fwd_mem <= mem_o.ctrl_wrb; |
exec_i.mem_result <= dmem_i.dat_i; |
exec_i.alu_result <= mem_o.alu_result; |
exec_i.ctrl_mem_wb <= mem_o.ctrl_mem_wb; |
exec_i.ctrl_mem_wrb <= mem_o.ctrl_mem_wrb; |
|
execute0 : execute GENERIC MAP |
execute0 : execute generic map |
( |
G_USE_HW_MUL => G_USE_HW_MUL, |
G_USE_BARREL => G_USE_BARREL |
) |
PORT MAP |
port map |
( |
exec_o => exec_o, |
exec_i => exec_i, |
139,11 → 139,11
mem_i.program_counter <= exec_o.program_counter; |
mem_i.branch <= exec_o.branch; |
mem_i.dat_d <= exec_o.dat_d; |
mem_i.ctrl_wb <= exec_o.ctrl_wb; |
mem_i.ctrl_wrb <= exec_o.ctrl_wrb; |
mem_i.ctrl_mem <= exec_o.ctrl_mem; |
mem_i.mem_result <= dmem_i.dat_i; |
|
mem0 : mem PORT MAP |
mem0 : mem port map |
( |
mem_o => mem_o, |
dmem_o => dmem_o, |
153,4 → 153,4
clk_i => clk_i |
); |
|
END arch; |
end arch; |
/trunk/hw/core/core_Pkg.vhd
13,29 → 13,33
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.std_Pkg.all; |
|
PACKAGE core_Pkg IS |
package core_Pkg is |
|
constant C_8_ZEROS : std_logic_vector ( 7 downto 0) := (others => '0'); |
constant C_16_ZEROS : std_logic_vector (15 downto 0) := (others => '0'); |
constant C_24_ZEROS : std_logic_vector (23 downto 0) := (others => '0'); |
constant C_32_ZEROS : std_logic_vector (31 downto 0) := (others => '0'); |
---------------------------------------------------------------------------------------------- |
-- TYPES USED IN MB-LITE |
---------------------------------------------------------------------------------------------- |
|
TYPE alu_operation IS (ALU_ADD, ALU_OR, ALU_AND, ALU_XOR, ALU_SHIFT, ALU_SEXT8, ALU_SEXT16, ALU_MUL, ALU_BS); |
TYPE src_type_a IS (ALU_SRC_REGA, ALU_SRC_NOT_REGA, ALU_SRC_PC, ALU_SRC_ZERO); |
TYPE src_type_b IS (ALU_SRC_REGB, ALU_SRC_NOT_REGB, ALU_SRC_IMM, ALU_SRC_NOT_IMM); |
TYPE carry_type IS (CARRY_ZERO, CARRY_ONE, CARRY_ALU, CARRY_ARITH); |
TYPE carry_keep_type IS (CARRY_NOT_KEEP, CARRY_KEEP); |
TYPE branch_condition IS (NOP, BNC, BEQ, BNE, BLT, BLE, BGT, BGE); |
TYPE transfer_size IS (WORD, HALFWORD, BYTE); |
type alu_operation is (ALU_ADD, ALU_OR, ALU_AND, ALU_XOR, ALU_SHIFT, ALU_SEXT8, ALU_SEXT16, ALU_MUL, ALU_BS); |
type src_type_a is (ALU_SRC_REGA, ALU_SRC_NOT_REGA, ALU_SRC_PC, ALU_SRC_ZERO); |
type src_type_b is (ALU_SRC_REGB, ALU_SRC_NOT_REGB, ALU_SRC_IMM, ALU_SRC_NOT_IMM); |
type carry_type is (CARRY_ZERO, CARRY_ONE, CARRY_ALU, CARRY_ARITH); |
type carry_keep_type is (CARRY_NOT_KEEP, CARRY_KEEP); |
type branch_condition is (NOP, BNC, BEQ, BNE, BLT, BLE, BGT, BGE); |
type transfer_size is (WORD, HALFWORD, BYTE); |
|
TYPE ctrl_execution IS RECORD |
type ctrl_execution is record |
alu_op : alu_operation; |
alu_src_a : src_type_a; |
alu_src_b : src_type_b; |
44,455 → 48,404
carry_keep : carry_keep_type; |
branch_cond : branch_condition; |
delay : std_logic; |
END RECORD; |
end record; |
|
TYPE ctrl_memory IS RECORD |
type ctrl_memory is record |
mem_write : std_logic; |
mem_read : std_logic; |
transfer_size : transfer_size; |
END RECORD; |
end record; |
|
TYPE ctrl_memory_writeback_type IS RECORD |
type ctrl_memory_writeback_type is record |
mem_read : std_logic; |
transfer_size : transfer_size; |
END RECORD; |
end record; |
|
TYPE forward_type IS RECORD |
reg_d : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
type forward_type is record |
reg_d : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
reg_write : std_logic; |
END RECORD; |
end record; |
|
TYPE imem_in_type IS RECORD |
dat_i : std_logic_vector(CFG_IMEM_WIDTH - 1 DOWNTO 0); |
END RECORD; |
type imem_in_type is record |
dat_i : std_logic_vector(CFG_IMEM_WIDTH - 1 downto 0); |
end record; |
|
TYPE imem_out_type IS RECORD |
adr_o : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
type imem_out_type is record |
adr_o : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
ena_o : std_logic; |
END RECORD; |
end record; |
|
TYPE fetch_in_type IS RECORD |
hazard : std_logic; |
branch : std_logic; |
branch_target : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
END RECORD; |
type fetch_in_type is record |
hazard : std_logic; |
branch : std_logic; |
branch_target : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
end record; |
|
TYPE fetch_out_type IS RECORD |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
END RECORD; |
type fetch_out_type is record |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
end record; |
|
TYPE gprf_out_type IS RECORD |
dat_a_o : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
dat_b_o : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
dat_d_o : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
END RECORD; |
type gprf_out_type is record |
dat_a_o : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
dat_b_o : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
dat_d_o : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
end record; |
|
TYPE decode_in_type IS RECORD |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
instruction : std_logic_vector(CFG_IMEM_WIDTH - 1 DOWNTO 0); |
ctrl_wb : forward_type; |
ctrl_mem_wb : ctrl_memory_writeback_type; |
mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
type decode_in_type is record |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
instruction : std_logic_vector(CFG_IMEM_WIDTH - 1 downto 0); |
ctrl_wrb : forward_type; |
ctrl_mem_wrb : ctrl_memory_writeback_type; |
mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
interrupt : std_logic; |
flush_id : std_logic; |
END RECORD; |
end record; |
|
TYPE decode_out_type IS RECORD |
reg_a : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
reg_b : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
imm : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
type decode_out_type is record |
reg_a : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
reg_b : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
imm : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
hazard : std_logic; |
ctrl_ex : ctrl_execution; |
ctrl_mem : ctrl_memory; |
ctrl_wb : forward_type; |
fwd_dec_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
ctrl_wrb : forward_type; |
fwd_dec_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
fwd_dec : forward_type; |
END RECORD; |
end record; |
|
TYPE gprf_in_type IS RECORD |
adr_a_i : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
adr_b_i : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
adr_d_i : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
dat_w_i : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
adr_w_i : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
type gprf_in_type is record |
adr_a_i : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
adr_b_i : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
adr_d_i : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
dat_w_i : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
adr_w_i : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
wre_i : std_logic; |
END RECORD; |
end record; |
|
TYPE execute_out_type IS RECORD |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
type execute_out_type is record |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
branch : std_logic; |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
flush_id : std_logic; |
ctrl_mem : ctrl_memory; |
ctrl_wb : forward_type; |
END RECORD; |
ctrl_wrb : forward_type; |
end record; |
|
TYPE execute_in_type IS RECORD |
reg_a : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
dat_a : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
reg_b : std_logic_vector(CFG_GPRF_SIZE - 1 DOWNTO 0); |
dat_b : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
imm : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
type execute_in_type is record |
reg_a : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
dat_a : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
reg_b : std_logic_vector(CFG_GPRF_SIZE - 1 downto 0); |
dat_b : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
imm : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
fwd_dec : forward_type; |
fwd_dec_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
fwd_dec_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
fwd_mem : forward_type; |
ctrl_ex : ctrl_execution; |
ctrl_mem : ctrl_memory; |
ctrl_wb : forward_type; |
ctrl_mem_wb : ctrl_memory_writeback_type; |
mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
ctrl_wrb : forward_type; |
ctrl_mem_wrb : ctrl_memory_writeback_type; |
mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
|
END RECORD; |
end record; |
|
TYPE mem_in_type IS RECORD |
dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 DOWNTO 0); |
type mem_in_type is record |
dat_d : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
program_counter : std_logic_vector(CFG_IMEM_SIZE - 1 downto 0); |
branch : std_logic; |
ctrl_mem : ctrl_memory; |
ctrl_wb : forward_type; |
END RECORD; |
ctrl_wrb : forward_type; |
end record; |
|
TYPE mem_out_type IS RECORD |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
ctrl_wb : forward_type; |
ctrl_mem_wb : ctrl_memory_writeback_type; |
END RECORD; |
type mem_out_type is record |
alu_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
ctrl_wrb : forward_type; |
ctrl_mem_wrb : ctrl_memory_writeback_type; |
end record; |
|
TYPE dmem_in_type IS RECORD |
dat_i : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
type dmem_in_type is record |
dat_i : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
ena_i : std_logic; |
END RECORD; |
end record; |
|
TYPE dmem_out_type IS RECORD |
dat_o : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
adr_o : std_logic_vector(CFG_DMEM_SIZE - 1 DOWNTO 0); |
sel_o : std_logic_vector(3 DOWNTO 0); |
type dmem_out_type is record |
dat_o : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
adr_o : std_logic_vector(CFG_DMEM_SIZE - 1 downto 0); |
sel_o : std_logic_vector(3 downto 0); |
we_o : std_logic; |
ena_o : std_logic; |
END RECORD; |
end record; |
|
TYPE dmem_in_array_type IS ARRAY(NATURAL RANGE <>) OF dmem_in_type; |
TYPE dmem_out_array_type IS ARRAY(NATURAL RANGE <>) OF dmem_out_type; |
type dmem_in_array_type is array(natural range <>) of dmem_in_type; |
type dmem_out_array_type is array(natural range <>) of dmem_out_type; |
|
-- WB-master inputs from the wb-slaves |
TYPE wb_mst_in_type IS RECORD |
clk_i : std_logic; -- master clock input |
rst_i : std_logic; -- synchronous active high reset |
dat_i : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); -- databus input |
ack_i : std_logic; -- buscycle acknowledge input |
int_i : std_logic; -- interrupt request input |
END RECORD; |
type wb_mst_in_type is record |
clk_i : std_logic; -- master clock input |
rst_i : std_logic; -- synchronous active high reset |
dat_i : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); -- databus input |
ack_i : std_logic; -- buscycle acknowledge input |
int_i : std_logic; -- interrupt request input |
end record; |
|
-- WB-master outputs to the wb-slaves |
TYPE wb_mst_out_type IS RECORD |
adr_o : std_logic_vector(CFG_DMEM_SIZE - 1 DOWNTO 0); -- address bits |
dat_o : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); -- databus output |
we_o : std_logic; -- write enable output |
stb_o : std_logic; -- strobe signals |
sel_o : std_logic_vector(3 DOWNTO 0); -- select output array |
cyc_o : std_logic; -- valid BUS cycle output |
END RECORD; |
type wb_mst_out_type is record |
adr_o : std_logic_vector(CFG_DMEM_SIZE - 1 downto 0); -- address bits |
dat_o : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); -- databus output |
we_o : std_logic; -- write enable output |
stb_o : std_logic; -- strobe signals |
sel_o : std_logic_vector(3 downto 0); -- select output array |
cyc_o : std_logic; -- valid BUS cycle output |
end record; |
|
-- WB-slave inputs, from the WB-master |
TYPE wb_slv_in_type IS RECORD |
clk_i : std_logic; -- master clock input |
rst_i : std_logic; -- synchronous active high reset |
adr_i : std_logic_vector(CFG_DMEM_SIZE - 1 DOWNTO 0); -- address bits |
dat_i : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); -- Databus input |
we_i : std_logic; -- Write enable input |
stb_i : std_logic; -- strobe signals / core select signal |
sel_i : std_logic_vector(3 DOWNTO 0); -- select output array |
cyc_i : std_logic; -- valid BUS cycle input |
END RECORD; |
type wb_slv_in_type is record |
clk_i : std_logic; -- master clock input |
rst_i : std_logic; -- synchronous active high reset |
adr_i : std_logic_vector(CFG_DMEM_SIZE - 1 downto 0); -- address bits |
dat_i : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); -- Databus input |
we_i : std_logic; -- Write enable input |
stb_i : std_logic; -- strobe signals / core select signal |
sel_i : std_logic_vector(3 downto 0); -- select output array |
cyc_i : std_logic; -- valid BUS cycle input |
end record; |
|
-- WB-slave outputs to the WB-master |
TYPE wb_slv_out_type IS RECORD |
dat_o : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); -- Databus output |
ack_o : std_logic; -- Bus cycle acknowledge output |
int_o : std_logic; -- interrupt request output |
END RECORD; |
type wb_slv_out_type is record |
dat_o : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); -- Databus output |
ack_o : std_logic; -- Bus cycle acknowledge output |
int_o : std_logic; -- interrupt request output |
end record; |
|
---------------------------------------------------------------------------------------------- |
-- COMPONENTS USED IN MB-LITE |
---------------------------------------------------------------------------------------------- |
|
COMPONENT core GENERIC |
( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
PORT |
( |
imem_o : OUT imem_out_type; |
dmem_o : OUT dmem_out_type; |
imem_i : IN imem_in_type; |
dmem_i : IN dmem_in_type; |
int_i : IN std_logic; |
rst_i : IN std_logic; |
clk_i : IN std_logic |
); |
END COMPONENT; |
component core |
generic ( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
port ( |
imem_o : out imem_out_type; |
dmem_o : out dmem_out_type; |
imem_i : in imem_in_type; |
dmem_i : in dmem_in_type; |
int_i : in std_logic; |
rst_i : in std_logic; |
clk_i : in std_logic |
); |
end component; |
|
COMPONENT core_wb GENERIC |
( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
PORT |
( |
imem_o : OUT imem_out_type; |
wb_o : OUT wb_mst_out_type; |
imem_i : IN imem_in_type; |
wb_i : IN wb_mst_in_type |
); |
END COMPONENT; |
component core_wb |
generic ( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
port ( |
imem_o : out imem_out_type; |
wb_o : out wb_mst_out_type; |
imem_i : in imem_in_type; |
wb_i : in wb_mst_in_type |
); |
end component; |
|
COMPONENT core_wb_adapter PORT |
( |
dmem_i : OUT dmem_in_type; |
wb_o : OUT wb_mst_out_type; |
dmem_o : IN dmem_out_type; |
wb_i : IN wb_mst_in_type |
); |
END COMPONENT; |
component core_wb_adapter |
port ( |
dmem_i : out dmem_in_type; |
wb_o : out wb_mst_out_type; |
dmem_o : in dmem_out_type; |
wb_i : in wb_mst_in_type |
); |
end component; |
|
COMPONENT core_wb_async_adapter PORT |
( |
dmem_i : OUT dmem_in_type; |
wb_o : OUT wb_mst_out_type; |
dmem_o : IN dmem_out_type; |
wb_i : IN wb_mst_in_type |
); |
END COMPONENT; |
component core_wb_async_adapter |
port ( |
dmem_i : out dmem_in_type; |
wb_o : out wb_mst_out_type; |
dmem_o : in dmem_out_type; |
wb_i : in wb_mst_in_type |
); |
end component; |
|
COMPONENT fetch PORT |
( |
fetch_o : OUT fetch_out_type; |
imem_o : OUT imem_out_type; |
fetch_i : IN fetch_in_type; |
rst_i : IN std_logic; |
ena_i : IN std_logic; |
clk_i : IN std_logic |
); |
END COMPONENT; |
component fetch |
port ( |
fetch_o : out fetch_out_type; |
imem_o : out imem_out_type; |
fetch_i : in fetch_in_type; |
rst_i : in std_logic; |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
end component; |
|
COMPONENT decode GENERIC |
( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
PORT |
( |
decode_o : OUT decode_out_type; |
gprf_o : OUT gprf_out_type; |
decode_i : IN decode_in_type; |
ena_i : IN std_logic; |
rst_i : IN std_logic; |
clk_i : IN std_logic |
); |
END COMPONENT; |
component decode |
generic ( |
G_INTERRUPT : boolean := CFG_INTERRUPT; |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL; |
G_DEBUG : boolean := CFG_DEBUG |
); |
port ( |
decode_o : out decode_out_type; |
gprf_o : out gprf_out_type; |
decode_i : in decode_in_type; |
ena_i : in std_logic; |
rst_i : in std_logic; |
clk_i : in std_logic |
); |
end component; |
|
COMPONENT gprf PORT |
( |
gprf_o : OUT gprf_out_type; |
gprf_i : IN gprf_in_type; |
ena_i : IN std_logic; |
clk_i : IN std_logic |
); |
END COMPONENT; |
component gprf |
port ( |
gprf_o : out gprf_out_type; |
gprf_i : in gprf_in_type; |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
end component; |
|
COMPONENT execute GENERIC |
( |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL |
); |
PORT |
( |
exec_o : OUT execute_out_type; |
exec_i : IN execute_in_type; |
ena_i : IN std_logic; |
rst_i : IN std_logic; |
clk_i : IN std_logic |
); |
END COMPONENT; |
component execute |
generic ( |
G_USE_HW_MUL : boolean := CFG_USE_HW_MUL; |
G_USE_BARREL : boolean := CFG_USE_BARREL |
); |
port ( |
exec_o : out execute_out_type; |
exec_i : in execute_in_type; |
ena_i : in std_logic; |
rst_i : in std_logic; |
clk_i : in std_logic |
); |
end component; |
|
COMPONENT mem PORT |
( |
mem_o : OUT mem_out_type; |
dmem_o : OUT dmem_out_type; |
mem_i : IN mem_in_type; |
ena_i : IN std_logic; |
rst_i : IN std_logic; |
clk_i : IN std_logic |
); |
END COMPONENT; |
component mem |
port ( |
mem_o : out mem_out_type; |
dmem_o : out dmem_out_type; |
mem_i : in mem_in_type; |
ena_i : in std_logic; |
rst_i : in std_logic; |
clk_i : in std_logic |
); |
end component; |
|
COMPONENT core_address_decoder GENERIC |
( |
G_NUM_SLAVES : positive := CFG_NUM_SLAVES |
); |
PORT |
( |
m_dmem_i : OUT dmem_in_type; |
s_dmem_o : OUT dmem_out_array_type; |
m_dmem_o : IN dmem_out_type; |
s_dmem_i : IN dmem_in_array_type; |
clk_i : IN std_logic |
); |
END COMPONENT; |
component core_address_decoder |
generic ( |
G_NUM_SLAVES : positive := CFG_NUM_SLAVES |
); |
port ( |
m_dmem_i : out dmem_in_type; |
s_dmem_o : out dmem_out_array_type; |
m_dmem_o : in dmem_out_type; |
s_dmem_i : in dmem_in_array_type; |
clk_i : in std_logic |
); |
end component; |
---------------------------------------------------------------------------------------------- |
-- FUNCTIONS USED IN MB-LITE |
---------------------------------------------------------------------------------------------- |
|
FUNCTION select_register_data(reg_dat, reg, wb_dat : std_logic_vector; write : std_logic) RETURN std_logic_vector; |
FUNCTION forward_condition(reg_write : std_logic; reg_a, reg_d : std_logic_vector) RETURN std_logic; |
FUNCTION align_mem_load(data : std_logic_vector; size : transfer_size; address : std_logic_vector) RETURN std_logic_vector; |
FUNCTION align_mem_store(data : std_logic_vector; size : transfer_size) RETURN std_logic_vector; |
FUNCTION decode_mem_store(address : std_logic_vector(1 DOWNTO 0); size : transfer_size) RETURN std_logic_vector; |
function select_register_data (reg_dat, reg, wb_dat : std_logic_vector; write : std_logic) return std_logic_vector; |
function forward_condition (reg_write : std_logic; reg_a, reg_d : std_logic_vector) return std_logic; |
function align_mem_load (data : std_logic_vector; size : transfer_size; address : std_logic_vector) return std_logic_vector; |
function align_mem_store (data : std_logic_vector; size : transfer_size) return std_logic_vector; |
function decode_mem_store (address : std_logic_vector(1 downto 0); size : transfer_size) return std_logic_vector; |
|
END core_Pkg; |
end core_Pkg; |
|
PACKAGE BODY core_Pkg IS |
package body core_Pkg is |
|
-- This function select the register value: |
-- A) zero |
-- B) bypass value read from register file |
-- C) value from register file |
FUNCTION select_register_data(reg_dat, reg, wb_dat : std_logic_vector; write : std_logic) RETURN std_logic_vector IS |
VARIABLE tmp : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
BEGIN |
IF CFG_REG_FORCE_ZERO = true AND is_zero(reg) = '1' THEN |
tmp := (OTHERS => '0'); |
ELSIF CFG_REG_FWD_WB = true AND write = '1' THEN |
function select_register_data (reg_dat, reg, wb_dat : std_logic_vector; write : std_logic) return std_logic_vector is |
variable tmp : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
begin |
if CFG_REG_FORCE_ZERO = true and is_zero(reg) = '1' then |
tmp := (others => '0'); |
elsif CFG_REG_FWD_WRB = true and write = '1' then |
tmp := wb_dat; |
ELSE |
else |
tmp := reg_dat; |
END IF; |
RETURN tmp; |
END select_register_data; |
end if; |
return tmp; |
end select_register_data; |
|
-- This function checks if a forwarding condition is met. The condition is met of register A and D match |
-- and the signal needs to be written back to the register file. |
FUNCTION forward_condition(reg_write : std_logic; reg_a, reg_d : std_logic_vector ) RETURN std_logic IS |
BEGIN |
RETURN reg_write AND compare(reg_a, reg_d); |
END forward_condition; |
function forward_condition (reg_write : std_logic; reg_a, reg_d : std_logic_vector ) return std_logic is |
begin |
return reg_write and compare(reg_a, reg_d); |
end forward_condition; |
|
-- This function aligns the memory load operation. The load byte-order is defined here. |
FUNCTION align_mem_load(data : std_logic_vector; size : transfer_size; address : std_logic_vector ) RETURN std_logic_vector IS |
BEGIN |
IF CFG_BYTE_ORDER = false THEN |
-- Little endian decoding |
CASE size IS |
WHEN byte => |
CASE address(1 DOWNTO 0) IS |
WHEN "00" => RETURN "000000000000000000000000" & data(CFG_DMEM_WIDTH/4 - 1 DOWNTO 0); |
WHEN "01" => RETURN "000000000000000000000000" & data(CFG_DMEM_WIDTH/2 - 1 DOWNTO CFG_DMEM_WIDTH/4); |
WHEN "10" => RETURN "000000000000000000000000" & data(3*CFG_DMEM_WIDTH/4 - 1 DOWNTO CFG_DMEM_WIDTH/2); |
WHEN "11" => RETURN "000000000000000000000000" & data(CFG_DMEM_WIDTH - 1 DOWNTO 3*CFG_DMEM_WIDTH/4); |
WHEN OTHERS => RETURN "00000000000000000000000000000000"; |
END CASE; |
WHEN halfword => |
CASE address(1 DOWNTO 0) IS |
WHEN "00" => RETURN "0000000000000000" & data(CFG_DMEM_WIDTH/2 - 1 DOWNTO 0); |
WHEN "10" => RETURN "0000000000000000" & data(CFG_DMEM_WIDTH - 1 DOWNTO CFG_DMEM_WIDTH/2); |
WHEN OTHERS => RETURN "00000000000000000000000000000000"; |
END CASE; |
WHEN OTHERS => |
RETURN data; |
END CASE; |
ELSE |
-- Big endian decoding |
CASE size IS |
WHEN byte => |
CASE address(1 DOWNTO 0) IS |
WHEN "00" => RETURN "000000000000000000000000" & data(CFG_DMEM_WIDTH - 1 DOWNTO 3*CFG_DMEM_WIDTH/4); |
WHEN "01" => RETURN "000000000000000000000000" & data(3*CFG_DMEM_WIDTH/4 - 1 DOWNTO CFG_DMEM_WIDTH/2); |
WHEN "10" => RETURN "000000000000000000000000" & data(CFG_DMEM_WIDTH/2 - 1 DOWNTO CFG_DMEM_WIDTH/4); |
WHEN "11" => RETURN "000000000000000000000000" & data(CFG_DMEM_WIDTH/4 - 1 DOWNTO 0); |
WHEN OTHERS => RETURN "00000000000000000000000000000000"; |
END CASE; |
WHEN halfword => |
CASE address(1 DOWNTO 0) IS |
WHEN "00" => RETURN "0000000000000000" & data(CFG_DMEM_WIDTH - 1 DOWNTO CFG_DMEM_WIDTH/2); |
WHEN "10" => RETURN "0000000000000000" & data(CFG_DMEM_WIDTH/2 - 1 DOWNTO 0); |
WHEN OTHERS => RETURN "00000000000000000000000000000000"; |
END CASE; |
WHEN OTHERS => |
RETURN data; |
END CASE; |
END IF; |
END align_mem_load; |
-- This function aligns the memory load operation (Big endian decoding). |
function align_mem_load (data : std_logic_vector; size : transfer_size; address : std_logic_vector ) return std_logic_vector is |
begin |
case size is |
when byte => |
case address(1 downto 0) is |
when "00" => return C_24_ZEROS & data(31 downto 24); |
when "01" => return C_24_ZEROS & data(23 downto 16); |
when "10" => return C_24_ZEROS & data(15 downto 8); |
when "11" => return C_24_ZEROS & data( 7 downto 0); |
when others => return C_32_ZEROS; |
end case; |
when halfword => |
case address(1 downto 0) is |
when "00" => return C_16_ZEROS & data(31 downto 16); |
when "10" => return C_16_ZEROS & data(15 downto 0); |
when others => return C_32_ZEROS; |
end case; |
when others => |
return data; |
end case; |
end align_mem_load; |
|
-- This function repeats the operand to all positions memory store operation. |
FUNCTION align_mem_store(data : std_logic_vector; size : transfer_size) RETURN std_logic_vector IS |
BEGIN |
CASE size IS |
WHEN byte => RETURN data( 7 DOWNTO 0) & data( 7 DOWNTO 0) & data(7 DOWNTO 0) & data(7 DOWNTO 0); |
WHEN halfword => RETURN data(15 DOWNTO 0) & data(15 DOWNTO 0); |
WHEN OTHERS => RETURN data; |
END CASE; |
END align_mem_store; |
-- This function repeats the operand to all positions in a memory store operation. |
function align_mem_store (data : std_logic_vector; size : transfer_size) return std_logic_vector is |
begin |
case size is |
when byte => return data( 7 downto 0) & data( 7 downto 0) & data(7 downto 0) & data(7 downto 0); |
when halfword => return data(15 downto 0) & data(15 downto 0); |
when others => return data; |
end case; |
end align_mem_store; |
|
-- This function selects the correct bytes for memory writes. The store byte-order (MSB / LSB) can be defined here. |
FUNCTION decode_mem_store(address : std_logic_vector(1 DOWNTO 0); size : transfer_size) RETURN std_logic_vector IS |
BEGIN |
IF CFG_BYTE_ORDER = false THEN |
-- Little endian encoding |
CASE size IS |
WHEN BYTE => |
CASE address IS |
WHEN "00" => RETURN "0001"; |
WHEN "01" => RETURN "0010"; |
WHEN "10" => RETURN "0100"; |
WHEN "11" => RETURN "1000"; |
WHEN OTHERS => RETURN "0000"; |
END CASE; |
WHEN HALFWORD => |
CASE address IS |
WHEN "00" => RETURN "0011"; |
WHEN "10" => RETURN "1100"; |
WHEN OTHERS => RETURN "0000"; |
END CASE; |
WHEN OTHERS => |
RETURN "1111"; |
END CASE; |
ELSE |
-- Big endian encoding |
CASE size IS |
WHEN BYTE => |
CASE address IS |
WHEN "00" => RETURN "1000"; |
WHEN "01" => RETURN "0100"; |
WHEN "10" => RETURN "0010"; |
WHEN "11" => RETURN "0001"; |
WHEN OTHERS => RETURN "0000"; |
END CASE; |
WHEN HALFWORD => |
CASE address IS |
-- Big endian encoding |
WHEN "10" => RETURN "0011"; |
WHEN "00" => RETURN "1100"; |
WHEN OTHERS => RETURN "0000"; |
END CASE; |
WHEN OTHERS => |
RETURN "1111"; |
END CASE; |
END IF; |
END decode_mem_store; |
-- This function selects the correct bytes for memory writes (Big endian encoding). |
function decode_mem_store (address : std_logic_vector(1 downto 0); size : transfer_size) return std_logic_vector is |
begin |
case size is |
when BYTE => |
case address is |
when "00" => return "1000"; |
when "01" => return "0100"; |
when "10" => return "0010"; |
when "11" => return "0001"; |
when others => return "0000"; |
end case; |
when HALFWORD => |
case address is |
-- Big endian encoding |
when "10" => return "0011"; |
when "00" => return "1100"; |
when others => return "0000"; |
end case; |
when others => |
return "1111"; |
end case; |
end decode_mem_store; |
|
END core_Pkg; |
end core_Pkg; |
/trunk/hw/core/fetch.vhd
14,57 → 14,57
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY fetch IS PORT |
entity fetch is port |
( |
fetch_o : OUT fetch_out_type; |
imem_o : OUT imem_out_type; |
fetch_i : IN fetch_in_type; |
rst_i : IN std_logic; |
ena_i : IN std_logic; |
clk_i : IN std_logic |
fetch_o : out fetch_out_type; |
imem_o : out imem_out_type; |
fetch_i : in fetch_in_type; |
rst_i : in std_logic; |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END fetch; |
end fetch; |
|
ARCHITECTURE arch OF fetch IS |
SIGNAL r, rin : fetch_out_type; |
BEGIN |
architecture arch of fetch is |
signal r, rin : fetch_out_type; |
begin |
|
fetch_o.program_counter <= r.program_counter; |
imem_o.adr_o <= rin.program_counter; |
imem_o.ena_o <= ena_i; |
|
fetch_comb: PROCESS(fetch_i, r, rst_i) |
VARIABLE v : fetch_out_type; |
BEGIN |
fetch_comb: process(fetch_i, r, rst_i) |
variable v : fetch_out_type; |
begin |
v := r; |
IF fetch_i.hazard = '1' THEN |
if fetch_i.hazard = '1' then |
v.program_counter := r.program_counter; |
ELSIF fetch_i.branch = '1' THEN |
elsif fetch_i.branch = '1' then |
v.program_counter := fetch_i.branch_target; |
ELSE |
v.program_counter := increment(r.program_counter(CFG_IMEM_SIZE - 1 DOWNTO 2)) & "00"; |
END IF; |
else |
v.program_counter := increment(r.program_counter(CFG_IMEM_SIZE - 1 downto 2)) & "00"; |
end if; |
rin <= v; |
END PROCESS; |
end process; |
|
fetch_seq: PROCESS(clk_i) |
BEGIN |
IF rising_edge(clk_i) THEN |
IF rst_i = '1' THEN |
r.program_counter <= (OTHERS => '0'); |
ELSIF ena_i = '1' THEN |
fetch_seq: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if rst_i = '1' then |
r.program_counter <= (others => '0'); |
elsif ena_i = '1' then |
r <= rin; |
END IF; |
END IF; |
END PROCESS; |
end if; |
end if; |
end process; |
|
END arch; |
end arch; |
/trunk/hw/core/gprf.vhd
13,36 → 13,36
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY gprf IS PORT |
entity gprf is port |
( |
gprf_o : OUT gprf_out_type; |
gprf_i : IN gprf_in_type; |
ena_i : IN std_logic; |
clk_i : IN std_logic |
gprf_o : out gprf_out_type; |
gprf_i : in gprf_in_type; |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END gprf; |
end gprf; |
|
-- This architecture is the default implementation. It |
-- consists of three dual port memories. Other |
-- architectures can be added while configurations can |
-- control the implemented architecture. |
ARCHITECTURE arch OF gprf IS |
BEGIN |
a : dsram GENERIC MAP |
architecture arch of gprf is |
begin |
a : dsram generic map |
( |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => CFG_GPRF_SIZE |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => CFG_GPRF_SIZE |
) |
PORT MAP |
port map |
( |
dat_o => gprf_o.dat_a_o, |
adr_i => gprf_i.adr_a_i, |
53,12 → 53,12
clk_i => clk_i |
); |
|
b : dsram GENERIC MAP |
b : dsram generic map |
( |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => CFG_GPRF_SIZE |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => CFG_GPRF_SIZE |
) |
PORT MAP |
port map |
( |
dat_o => gprf_o.dat_b_o, |
adr_i => gprf_i.adr_b_i, |
69,12 → 69,12
clk_i => clk_i |
); |
|
d : dsram GENERIC MAP |
d : dsram generic map |
( |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => CFG_GPRF_SIZE |
WIDTH => CFG_DMEM_WIDTH, |
SIZE => CFG_GPRF_SIZE |
) |
PORT MAP |
port map |
( |
dat_o => gprf_o.dat_d_o, |
adr_i => gprf_i.adr_d_i, |
84,4 → 84,4
wre_i => gprf_i.wre_i, |
clk_i => clk_i |
); |
END arch; |
end arch; |
/trunk/hw/core/mem.vhd
20,88 → 20,88
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.config_Pkg.ALL; |
USE mblite.core_Pkg.ALL; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.config_Pkg.all; |
use mblite.core_Pkg.all; |
use mblite.std_Pkg.all; |
|
ENTITY mem IS PORT |
entity mem is port |
( |
mem_o : OUT mem_out_type; |
dmem_o : OUT dmem_out_type; |
mem_i : IN mem_in_type; |
ena_i : IN std_logic; |
rst_i : IN std_logic; |
clk_i : IN std_logic |
mem_o : out mem_out_type; |
dmem_o : out dmem_out_type; |
mem_i : in mem_in_type; |
ena_i : in std_logic; |
rst_i : in std_logic; |
clk_i : in std_logic |
); |
END mem; |
end mem; |
|
ARCHITECTURE arch OF mem IS |
SIGNAL r, rin : mem_out_type; |
SIGNAL mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
BEGIN |
architecture arch of mem is |
signal r, rin : mem_out_type; |
signal mem_result : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
begin |
-- connect pipline signals |
mem_o.ctrl_wb <= r.ctrl_wb; |
mem_o.ctrl_mem_wb <= r.ctrl_mem_wb; |
mem_o.ctrl_wrb <= r.ctrl_wrb; |
mem_o.ctrl_mem_wrb <= r.ctrl_mem_wrb; |
mem_o.alu_result <= r.alu_result; |
|
-- connect memory interface signals |
dmem_o.dat_o <= mem_result; |
dmem_o.sel_o <= decode_mem_store(mem_i.alu_result(1 DOWNTO 0), mem_i.ctrl_mem.transfer_size); |
dmem_o.sel_o <= decode_mem_store(mem_i.alu_result(1 downto 0), mem_i.ctrl_mem.transfer_size); |
dmem_o.we_o <= mem_i.ctrl_mem.mem_write; |
dmem_o.adr_o <= mem_i.alu_result(CFG_DMEM_SIZE - 1 DOWNTO 0); |
dmem_o.ena_o <= mem_i.ctrl_mem.mem_read OR mem_i.ctrl_mem.mem_write; |
dmem_o.adr_o <= mem_i.alu_result(CFG_DMEM_SIZE - 1 downto 0); |
dmem_o.ena_o <= mem_i.ctrl_mem.mem_read or mem_i.ctrl_mem.mem_write; |
|
mem_comb: PROCESS(mem_i, mem_i.ctrl_wb, mem_i.ctrl_mem, r, r.ctrl_wb, r.ctrl_mem_wb) |
VARIABLE v : mem_out_type; |
VARIABLE intermediate : std_logic_vector(CFG_DMEM_WIDTH - 1 DOWNTO 0); |
BEGIN |
mem_comb: process(mem_i, mem_i.ctrl_wrb, mem_i.ctrl_mem, r, r.ctrl_wrb, r.ctrl_mem_wrb) |
variable v : mem_out_type; |
variable intermediate : std_logic_vector(CFG_DMEM_WIDTH - 1 downto 0); |
begin |
|
v := r; |
v.ctrl_wb := mem_i.ctrl_wb; |
v.ctrl_wrb := mem_i.ctrl_wrb; |
|
IF mem_i.branch = '1' THEN |
if mem_i.branch = '1' then |
-- set alu result for branch and load instructions |
v.alu_result := sign_extend(mem_i.program_counter, '0', 32); |
ELSE |
else |
v.alu_result := mem_i.alu_result; |
END IF; |
end if; |
|
-- Forward memory result |
IF CFG_MEM_FWD_WB = true AND ( r.ctrl_mem_wb.mem_read AND compare(mem_i.ctrl_wb.reg_d, r.ctrl_wb.reg_d)) = '1' THEN |
intermediate := align_mem_load(mem_i.mem_result, r.ctrl_mem_wb.transfer_size, r.alu_result(1 DOWNTO 0)); |
if CFG_MEM_FWD_WRB = true and ( r.ctrl_mem_wrb.mem_read and compare(mem_i.ctrl_wrb.reg_d, r.ctrl_wrb.reg_d)) = '1' then |
intermediate := align_mem_load(mem_i.mem_result, r.ctrl_mem_wrb.transfer_size, r.alu_result(1 downto 0)); |
mem_result <= align_mem_store(intermediate, mem_i.ctrl_mem.transfer_size); |
ELSE |
else |
mem_result <= mem_i.dat_d; |
END IF; |
end if; |
|
v.ctrl_mem_wb.mem_read := mem_i.ctrl_mem.mem_read; |
v.ctrl_mem_wb.transfer_size := mem_i.ctrl_mem.transfer_size; |
v.ctrl_mem_wrb.mem_read := mem_i.ctrl_mem.mem_read; |
v.ctrl_mem_wrb.transfer_size := mem_i.ctrl_mem.transfer_size; |
|
rin <= v; |
|
END PROCESS; |
end process; |
|
mem_seq: PROCESS(clk_i) |
PROCEDURE proc_mem_reset IS |
BEGIN |
r.alu_result <= (OTHERS => '0'); |
r.ctrl_wb.reg_d <= (OTHERS => '0'); |
r.ctrl_wb.reg_write <= '0'; |
r.ctrl_mem_wb.mem_read <= '0'; |
r.ctrl_mem_wb.transfer_size <= WORD; |
END PROCEDURE proc_mem_reset; |
BEGIN |
IF rising_edge(clk_i) THEN |
IF rst_i = '1' THEN |
mem_seq: process(clk_i) |
procedure proc_mem_reset is |
begin |
r.alu_result <= (others => '0'); |
r.ctrl_wrb.reg_d <= (others => '0'); |
r.ctrl_wrb.reg_write <= '0'; |
r.ctrl_mem_wrb.mem_read <= '0'; |
r.ctrl_mem_wrb.transfer_size <= WORD; |
end procedure proc_mem_reset; |
begin |
if rising_edge(clk_i) then |
if rst_i = '1' then |
proc_mem_reset; |
ELSIF ena_i = '1' THEN |
elsif ena_i = '1' then |
r <= rin; |
END IF; |
END IF; |
END PROCESS; |
END arch; |
end if; |
end if; |
end process; |
end arch; |
/trunk/hw/std/sram.vhd
11,43 → 11,42
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.std_Pkg.all; |
|
ENTITY sram IS GENERIC |
entity sram is generic |
( |
WIDTH : positive := 32; |
SIZE : positive := 16 |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
dat_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic; |
ena_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
dat_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic; |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END sram; |
end sram; |
|
ARCHITECTURE arch OF sram IS |
TYPE ram_type IS array(2 ** SIZE - 1 DOWNTO 0) OF std_logic_vector(WIDTH - 1 DOWNTO 0); |
SIGNAL ram : ram_type; |
BEGIN |
PROCESS(clk_i) |
BEGIN |
IF rising_edge(clk_i) THEN |
IF ena_i = '1' THEN |
IF wre_i = '1' THEN |
architecture arch of sram is |
type ram_type is array(2 ** SIZE - 1 downto 0) of std_logic_vector(WIDTH - 1 downto 0); |
signal ram : ram_type; |
begin |
process(clk_i) |
begin |
if rising_edge(clk_i) then |
if ena_i = '1' then |
if wre_i = '1' then |
ram(my_conv_integer(adr_i)) <= dat_i; |
END IF; |
end if; |
dat_o <= ram(my_conv_integer(adr_i)); |
END IF; |
END IF; |
END PROCESS; |
END arch; |
|
end if; |
end if; |
end process; |
end arch; |
/trunk/hw/std/dsram.vhd
13,43 → 13,43
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.std_Pkg.all; |
|
ENTITY dsram IS GENERIC |
entity dsram is generic |
( |
WIDTH : positive := 32; |
SIZE : positive := 8 |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
ena_i : IN std_logic; |
dat_w_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_w_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
ena_i : in std_logic; |
dat_w_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_w_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic; |
clk_i : in std_logic |
); |
END dsram; |
end dsram; |
|
ARCHITECTURE arch OF dsram IS |
TYPE ram_type IS array(2 ** SIZE - 1 DOWNTO 0) OF std_logic_vector(WIDTH - 1 DOWNTO 0); |
SIGNAL ram : ram_type; |
BEGIN |
PROCESS(clk_i) |
BEGIN |
IF rising_edge(clk_i) THEN |
IF ena_i = '1' THEN |
IF wre_i = '1' THEN |
architecture arch of dsram is |
type ram_type is array(2 ** SIZE - 1 downto 0) of std_logic_vector(WIDTH - 1 downto 0); |
signal ram : ram_type; |
begin |
process(clk_i) |
begin |
if rising_edge(clk_i) then |
if ena_i = '1' then |
if wre_i = '1' then |
ram(my_conv_integer(adr_w_i)) <= dat_w_i; |
END IF; |
end if; |
dat_o <= ram(my_conv_integer(adr_i)); |
END IF; |
END IF; |
END PROCESS; |
END arch; |
end if; |
end if; |
end process; |
end arch; |
/trunk/hw/std/sram_4en.vhd
14,80 → 14,80
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
|
LIBRARY mblite; |
USE mblite.std_Pkg.ALL; |
library mblite; |
use mblite.std_Pkg.all; |
|
ENTITY sram_4en IS GENERIC |
entity sram_4en is generic |
( |
WIDTH : positive := 32; |
SIZE : positive := 16 |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
dat_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic_vector(WIDTH/8 - 1 DOWNTO 0); |
ena_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
dat_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic_vector(WIDTH/8 - 1 downto 0); |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END sram_4en; |
end sram_4en; |
|
-- Although this memory is very easy to use in conjunction with Modelsims mem load, it is not |
-- supported by many devices (although it comes straight from the library. Many devices give |
-- cryptic synthesization errors on this implementation, so it is not the default. |
ARCHITECTURE arch2 OF sram_4en IS |
architecture arch2 of sram_4en is |
|
TYPE ram_type IS array(2 ** SIZE - 1 DOWNTO 0) OF std_logic_vector(WIDTH - 1 DOWNTO 0); |
TYPE sel_type IS array(WIDTH/8 - 1 DOWNTO 0) OF std_logic_vector(7 DOWNTO 0); |
type ram_type is array(2 ** SIZE - 1 downto 0) of std_logic_vector(WIDTH - 1 downto 0); |
type sel_type is array(WIDTH/8 - 1 downto 0) of std_logic_vector(7 downto 0); |
|
SIGNAL ram: ram_type; |
SIGNAL di: sel_type; |
BEGIN |
PROCESS(wre_i, dat_i, adr_i) |
BEGIN |
FOR i IN 0 TO WIDTH/8 - 1 LOOP |
IF wre_i(i) = '1' THEN |
di(i) <= dat_i((i+1)*8 - 1 DOWNTO i*8); |
ELSE |
di(i) <= ram(my_conv_integer(adr_i))((i+1)*8 - 1 DOWNTO i*8); |
END IF; |
END LOOP; |
END PROCESS; |
signal ram: ram_type; |
signal di: sel_type; |
begin |
process(wre_i, dat_i, adr_i) |
begin |
for i in 0 to WIDTH/8 - 1 loop |
if wre_i(i) = '1' then |
di(i) <= dat_i((i+1)*8 - 1 downto i*8); |
else |
di(i) <= ram(my_conv_integer(adr_i))((i+1)*8 - 1 downto i*8); |
end if; |
end loop; |
end process; |
|
PROCESS(clk_i) |
BEGIN |
IF rising_edge(clk_i) THEN |
IF ena_i = '1' THEN |
process(clk_i) |
begin |
if rising_edge(clk_i) then |
if ena_i = '1' then |
ram(my_conv_integer(adr_i)) <= di(3) & di(2) & di(1) & di(0); |
dat_o <= di(3) & di(2) & di(1) & di(0); |
END IF; |
END IF; |
END PROCESS; |
END arch2; |
end if; |
end if; |
end process; |
end arch2; |
|
-- Less convenient but very general memory block with four separate write |
-- enable signals. (4x8 bit) |
ARCHITECTURE arch OF sram_4en IS |
BEGIN |
mem: FOR i IN 0 TO WIDTH/8 - 1 GENERATE |
mem : sram GENERIC MAP |
architecture arch of sram_4en is |
begin |
mem: for i in 0 to WIDTH/8 - 1 generate |
mem : sram generic map |
( |
WIDTH => 8, |
SIZE => SIZE |
) |
PORT MAP |
port map |
( |
dat_o => dat_o((i+1)*8 - 1 DOWNTO i*8), |
dat_i => dat_i((i+1)*8 - 1 DOWNTO i*8), |
dat_o => dat_o((i+1)*8 - 1 downto i*8), |
dat_i => dat_i((i+1)*8 - 1 downto i*8), |
adr_i => adr_i, |
wre_i => wre_i(i), |
ena_i => ena_i, |
clk_i => clk_i |
); |
END GENERATE; |
END arch; |
end generate; |
end arch; |
/trunk/hw/std/std_Pkg.vhd
11,9 → 11,9
-- |
---------------------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.numeric_std.ALL; |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
PACKAGE std_Pkg IS |
|
21,147 → 21,145
-- STANDARD COMPONENTS IN STD_PKG |
---------------------------------------------------------------------------------------------- |
|
COMPONENT sram GENERIC |
component sram generic |
( |
WIDTH : positive; |
SIZE : positive |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
dat_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic; |
ena_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
dat_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic; |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END COMPONENT; |
end component; |
|
COMPONENT sram_4en GENERIC |
component sram_4en generic |
( |
WIDTH : positive; |
SIZE : positive |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
dat_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic_vector(3 DOWNTO 0); |
ena_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
dat_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic_vector(3 downto 0); |
ena_i : in std_logic; |
clk_i : in std_logic |
); |
END COMPONENT; |
end component; |
|
COMPONENT dsram GENERIC |
component dsram generic |
( |
WIDTH : positive; |
SIZE : positive |
); |
PORT |
port |
( |
dat_o : OUT std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
ena_i : IN std_logic; |
dat_w_i : IN std_logic_vector(WIDTH - 1 DOWNTO 0); |
adr_w_i : IN std_logic_vector(SIZE - 1 DOWNTO 0); |
wre_i : IN std_logic; |
clk_i : IN std_logic |
dat_o : out std_logic_vector(WIDTH - 1 downto 0); |
adr_i : in std_logic_vector(SIZE - 1 downto 0); |
ena_i : in std_logic; |
dat_w_i : in std_logic_vector(WIDTH - 1 downto 0); |
adr_w_i : in std_logic_vector(SIZE - 1 downto 0); |
wre_i : in std_logic; |
clk_i : in std_logic |
); |
END COMPONENT; |
end component; |
|
---------------------------------------------------------------------------------------------- |
-- FUNCTIONS IN STD_PKG |
---------------------------------------------------------------------------------------------- |
|
FUNCTION v_or(d : std_logic_vector) RETURN std_logic; |
FUNCTION is_zero(d : std_logic_vector) RETURN std_logic; |
FUNCTION is_not_zero(d : std_logic_vector) RETURN std_logic; |
FUNCTION my_conv_integer(a: std_logic_vector) RETURN integer; |
FUNCTION notx(d : std_logic_vector) RETURN boolean; |
FUNCTION compare(a, b : std_logic_vector) RETURN std_logic; |
FUNCTION multiply(a, b : std_logic_vector) RETURN std_logic_vector; |
FUNCTION sign_extend(value: std_logic_vector; fill: std_logic; size: positive) RETURN std_logic_vector; |
FUNCTION add(a, b : std_logic_vector; ci: std_logic) RETURN std_logic_vector; |
FUNCTION increment(a : std_logic_vector) RETURN std_logic_vector; |
FUNCTION shift(value : std_logic_vector(31 DOWNTO 0); shamt: std_logic_vector(4 DOWNTO 0); s: std_logic; t: std_logic) RETURN std_logic_vector; |
FUNCTION shift_left(value : std_logic_vector(31 DOWNTO 0); shamt : std_logic_vector(4 DOWNTO 0)) RETURN std_logic_vector; |
FUNCTION shift_right(value : std_logic_vector(31 DOWNTO 0); shamt : std_logic_vector(4 DOWNTO 0); padding: std_logic) RETURN std_logic_vector; |
function v_or(d : std_logic_vector) return std_logic; |
function is_zero(d : std_logic_vector) return std_logic; |
function is_not_zero(d : std_logic_vector) return std_logic; |
function my_conv_integer(a: std_logic_vector) return integer; |
function notx(d : std_logic_vector) return boolean; |
function compare(a, b : std_logic_vector) return std_logic; |
function multiply(a, b : std_logic_vector) return std_logic_vector; |
function sign_extend(value: std_logic_vector; fill: std_logic; size: positive) return std_logic_vector; |
function add(a, b : std_logic_vector; ci: std_logic) return std_logic_vector; |
function increment(a : std_logic_vector) return std_logic_vector; |
function shift(value : std_logic_vector(31 downto 0); shamt: std_logic_vector(4 downto 0); s: std_logic; t: std_logic) return std_logic_vector; |
function shift_left(value : std_logic_vector(31 downto 0); shamt : std_logic_vector(4 downto 0)) return std_logic_vector; |
function shift_right(value : std_logic_vector(31 downto 0); shamt : std_logic_vector(4 downto 0); padding: std_logic) return std_logic_vector; |
|
END std_Pkg; |
end std_Pkg; |
|
PACKAGE BODY std_Pkg IS |
|
-- Unary OR reduction |
FUNCTION v_or(d : std_logic_vector) RETURN std_logic IS |
VARIABLE z : std_logic; |
BEGIN |
function v_or(d : std_logic_vector) return std_logic is |
variable z : std_logic; |
begin |
z := '0'; |
IF notx (d) THEN |
FOR i IN d'range LOOP |
z := z OR d(i); |
END LOOP; |
END IF; |
RETURN z; |
END; |
if notx (d) then |
for i in d'range loop |
z := z or d(i); |
end loop; |
end if; |
return z; |
end; |
|
-- Check for ones in the vector |
FUNCTION is_not_zero(d : std_logic_vector) RETURN std_logic IS |
VARIABLE z : std_logic_vector(d'range); |
BEGIN |
z := (OTHERS => '0'); |
IF notx(d) THEN |
function is_not_zero(d : std_logic_vector) return std_logic is |
variable z : std_logic_vector(d'range); |
begin |
z := (others => '0'); |
if notx(d) then |
|
IF d = z THEN |
RETURN '0'; |
ELSE |
RETURN '1'; |
END IF; |
if d = z then |
return '0'; |
else |
return '1'; |
end if; |
|
ELSE |
RETURN '0'; |
END IF; |
END; |
else |
return '0'; |
end if; |
end; |
|
-- Check for ones in the vector |
FUNCTION is_zero(d : std_logic_vector) RETURN std_logic IS |
BEGIN |
RETURN NOT is_not_zero(d); |
END; |
function is_zero(d : std_logic_vector) return std_logic is |
begin |
return not is_not_zero(d); |
end; |
|
-- rewrite conv_integer to avoid modelsim warnings |
FUNCTION my_conv_integer(a : std_logic_vector) RETURN integer IS |
VARIABLE res : integer RANGE 0 TO 2**a'length-1; |
BEGIN |
function my_conv_integer(a : std_logic_vector) return integer is |
variable res : integer range 0 to 2**a'length-1; |
begin |
res := 0; |
IF (notx(a)) THEN |
if (notx(a)) then |
res := to_integer(unsigned(a)); |
END IF; |
RETURN res; |
END; |
end if; |
return res; |
end; |
|
FUNCTION compare(a, b : std_logic_vector) RETURN std_logic IS |
VARIABLE z : std_logic; |
BEGIN |
function compare(a, b : std_logic_vector) return std_logic is |
variable z : std_logic; |
begin |
if notx(a & b) and a = b then |
return '1'; |
else |
return '0'; |
end if; |
end; |
|
IF notx(a & b) AND a = b THEN |
RETURN '1'; |
ELSE |
RETURN '0'; |
END IF; |
|
END; |
|
-- Unary NOT X test |
FUNCTION notx(d : std_logic_vector) RETURN boolean IS |
VARIABLE res : boolean; |
BEGIN |
function notx(d : std_logic_vector) return boolean is |
variable res : boolean; |
begin |
res := true; |
-- pragma translate_off |
res := NOT is_x(d); |
res := not is_x(d); |
-- pragma translate_on |
RETURN (res); |
END; |
return (res); |
end; |
|
-- -- 32 bit shifter |
-- -- SYNOPSIS: |
171,98 → 169,94
-- -- t 0 / 1: shift logical / arithmetic |
-- -- PSEUDOCODE (from microblaze reference guide) |
-- -- if S = 1 then |
-- -- (rD) ← (rA) << (rB)[27:31] |
-- -- (rD) = (rA) << (rB)[27:31] |
-- -- else |
-- -- if T = 1 then |
-- -- if ((rB)[27:31]) ≠ 0 then |
-- -- (rD)[0:(rB)[27:31]-1] ← (rA)[0] |
-- -- (rD)[(rB)[27:31]:31] ← (rA) >> (rB)[27:31] |
-- -- if ((rB)[27:31]) != 0 then |
-- -- (rD)[0:(rB)[27:31]-1] = (rA)[0] |
-- -- (rD)[(rB)[27:31]:31] = (rA) >> (rB)[27:31] |
-- -- else |
-- -- (rD) ← (rA) |
-- -- (rD) = (rA) |
-- -- else |
-- -- (rD) ← (rA) >> (rB)[27:31] |
-- -- (rD) = (rA) >> (rB)[27:31] |
|
FUNCTION shift(value: std_logic_vector(31 DOWNTO 0); shamt: std_logic_vector(4 DOWNTO 0); s: std_logic; t: std_logic) RETURN std_logic_vector IS |
BEGIN |
IF s = '1' THEN |
function shift(value: std_logic_vector(31 downto 0); shamt: std_logic_vector(4 downto 0); s: std_logic; t: std_logic) return std_logic_vector is |
begin |
if s = '1' then |
-- left arithmetic or logical shift |
RETURN shift_left(value, shamt); |
ELSE |
IF t = '1' THEN |
return shift_left(value, shamt); |
else |
if t = '1' then |
-- right arithmetic shift |
RETURN shift_right(value, shamt, value(31)); |
ELSE |
return shift_right(value, shamt, value(31)); |
else |
-- right logical shift |
RETURN shift_right(value, shamt, '0'); |
END IF; |
END IF; |
END; |
return shift_right(value, shamt, '0'); |
end if; |
end if; |
end; |
|
FUNCTION shift_left(value: std_logic_vector(31 DOWNTO 0); shamt: std_logic_vector(4 DOWNTO 0)) RETURN std_logic_vector IS |
VARIABLE result: std_logic_vector(31 DOWNTO 0); |
VARIABLE paddings: std_logic_vector(15 DOWNTO 0); |
BEGIN |
|
paddings := (OTHERS => '0'); |
function shift_left(value: std_logic_vector(31 downto 0); shamt: std_logic_vector(4 downto 0)) return std_logic_vector is |
variable result: std_logic_vector(31 downto 0); |
variable paddings: std_logic_vector(15 downto 0); |
begin |
paddings := (others => '0'); |
result := value; |
IF (shamt(4) = '1') THEN result := result(15 DOWNTO 0) & paddings(15 DOWNTO 0); END IF; |
IF (shamt(3) = '1') THEN result := result(23 DOWNTO 0) & paddings( 7 DOWNTO 0); END IF; |
IF (shamt(2) = '1') THEN result := result(27 DOWNTO 0) & paddings( 3 DOWNTO 0); END IF; |
IF (shamt(1) = '1') THEN result := result(29 DOWNTO 0) & paddings( 1 DOWNTO 0); END IF; |
IF (shamt(0) = '1') THEN result := result(30 DOWNTO 0) & paddings( 0 ); END IF; |
RETURN result; |
if (shamt(4) = '1') then result := result(15 downto 0) & paddings(15 downto 0); end if; |
if (shamt(3) = '1') then result := result(23 downto 0) & paddings( 7 downto 0); end if; |
if (shamt(2) = '1') then result := result(27 downto 0) & paddings( 3 downto 0); end if; |
if (shamt(1) = '1') then result := result(29 downto 0) & paddings( 1 downto 0); end if; |
if (shamt(0) = '1') then result := result(30 downto 0) & paddings( 0 ); end if; |
return result; |
end; |
|
END; |
|
FUNCTION shift_right(value: std_logic_vector(31 DOWNTO 0); shamt: std_logic_vector(4 DOWNTO 0); padding: std_logic) RETURN std_logic_vector IS |
VARIABLE result: std_logic_vector(31 DOWNTO 0); |
VARIABLE paddings: std_logic_vector(15 DOWNTO 0); |
BEGIN |
|
paddings := (OTHERS => padding); |
function shift_right(value: std_logic_vector(31 downto 0); shamt: std_logic_vector(4 downto 0); padding: std_logic) return std_logic_vector is |
variable result: std_logic_vector(31 downto 0); |
variable paddings: std_logic_vector(15 downto 0); |
begin |
paddings := (others => padding); |
result := value; |
IF (shamt(4) = '1') THEN result := paddings(15 DOWNTO 0) & result(31 DOWNTO 16); END IF; |
IF (shamt(3) = '1') THEN result := paddings( 7 DOWNTO 0) & result(31 DOWNTO 8); END IF; |
IF (shamt(2) = '1') THEN result := paddings( 3 DOWNTO 0) & result(31 DOWNTO 4); END IF; |
IF (shamt(1) = '1') THEN result := paddings( 1 DOWNTO 0) & result(31 DOWNTO 2); END IF; |
IF (shamt(0) = '1') THEN result := paddings( 0 ) & result(31 DOWNTO 1); END IF; |
RETURN result; |
if (shamt(4) = '1') then result := paddings(15 downto 0) & result(31 downto 16); end if; |
if (shamt(3) = '1') then result := paddings( 7 downto 0) & result(31 downto 8); end if; |
if (shamt(2) = '1') then result := paddings( 3 downto 0) & result(31 downto 4); end if; |
if (shamt(1) = '1') then result := paddings( 1 downto 0) & result(31 downto 2); end if; |
if (shamt(0) = '1') then result := paddings( 0 ) & result(31 downto 1); end if; |
return result; |
end; |
|
END; |
|
FUNCTION multiply(a, b: std_logic_vector) RETURN std_logic_vector IS |
VARIABLE x: std_logic_vector (a'length + b'length - 1 DOWNTO 0); |
BEGIN |
function multiply(a, b: std_logic_vector) return std_logic_vector is |
variable x: std_logic_vector (a'length + b'length - 1 downto 0); |
begin |
x := std_logic_vector(signed(a) * signed(b)); |
RETURN x(31 DOWNTO 0); |
END; |
return x(31 downto 0); |
end; |
|
FUNCTION sign_extend(value: std_logic_vector; fill: std_logic; size: positive) RETURN std_logic_vector IS |
VARIABLE a: std_logic_vector (size - 1 DOWNTO 0); |
BEGIN |
a(size - 1 DOWNTO value'length) := (OTHERS => fill); |
a(value'length - 1 DOWNTO 0) := value; |
function sign_extend(value: std_logic_vector; fill: std_logic; size: positive) return std_logic_vector is |
variable a: std_logic_vector (size - 1 downto 0); |
begin |
a(size - 1 downto value'length) := (others => fill); |
a(value'length - 1 downto 0) := value; |
return a; |
END; |
end; |
|
FUNCTION add(a, b : std_logic_vector; ci: std_logic) RETURN std_logic_vector IS |
VARIABLE x : std_logic_vector(a'length + 1 DOWNTO 0); |
BEGIN |
x := (OTHERS => '0'); |
IF notx (a & b & ci) THEN |
function add(a, b : std_logic_vector; ci: std_logic) return std_logic_vector is |
variable x : std_logic_vector(a'length + 1 downto 0); |
begin |
x := (others => '0'); |
if notx (a & b & ci) then |
x := std_logic_vector(signed('0' & a & '1') + signed('0' & b & ci)); |
END IF; |
RETURN x(a'length + 1 DOWNTO 1); |
END; |
end if; |
return x(a'length + 1 downto 1); |
end; |
|
FUNCTION increment(a : std_logic_vector) RETURN std_logic_vector IS |
VARIABLE x : std_logic_vector(a'length-1 DOWNTO 0); |
BEGIN |
x := (OTHERS => '0'); |
IF notx (a) THEN |
function increment(a : std_logic_vector) return std_logic_vector is |
variable x : std_logic_vector(a'length-1 downto 0); |
begin |
x := (others => '0'); |
if notx (a) then |
x := std_logic_vector(signed(a) + 1); |
END IF; |
RETURN x; |
END; |
end if; |
return x; |
end; |
|
END std_Pkg; |
end std_Pkg; |