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

Subversion Repositories mblite

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /mblite/trunk/hw/core
    from Rev 7 to Rev 8
    Reverse comparison

Rev 7 → Rev 8

/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;
/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;
/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;
/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;
/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;
/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;
/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;
/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;
/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;
/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;

powered by: WebSVN 2.1.0

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