forked from Firebee/FPGA_Config
This commit is contained in:
79
FPGA_Quartus_13.1/DSP/DSP.vhd
Normal file
79
FPGA_Quartus_13.1/DSP/DSP.vhd
Normal file
@@ -0,0 +1,79 @@
|
||||
-- WARNING: Do NOT edit the input and output ports in this file in a text
|
||||
-- editor if you plan to continue editing the block that represents it in
|
||||
-- the Block Editor! File corruption is VERY likely to occur.
|
||||
|
||||
-- Copyright (C) 1991-2008 Altera Corporation
|
||||
-- Your use of Altera Corporation's design tools, logic functions
|
||||
-- and other software and tools, and its AMPP partner logic
|
||||
-- functions, and any output files from any of the foregoing
|
||||
-- (including device programming or simulation files), and any
|
||||
-- associated documentation or information are expressly subject
|
||||
-- to the terms and conditions of the Altera Program License
|
||||
-- Subscription Agreement, Altera MegaCore Function License
|
||||
-- Agreement, or other applicable license agreement, including,
|
||||
-- without limitation, that your use is for the sole purpose of
|
||||
-- programming logic devices manufactured by Altera and sold by
|
||||
-- Altera or its authorized distributors. Please refer to the
|
||||
-- applicable agreement for further details.
|
||||
|
||||
|
||||
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
|
||||
-- Created on Tue Sep 08 16:24:57 2009
|
||||
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
|
||||
-- Entity Declaration
|
||||
|
||||
ENTITY DSP IS
|
||||
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
|
||||
PORT
|
||||
(
|
||||
CLK33M : IN STD_LOGIC;
|
||||
MAIN_CLK : IN STD_LOGIC;
|
||||
nFB_OE : IN STD_LOGIC;
|
||||
nFB_WR : IN STD_LOGIC;
|
||||
nFB_CS1 : IN STD_LOGIC;
|
||||
nFB_CS2 : IN STD_LOGIC;
|
||||
FB_SIZE0 : IN STD_LOGIC;
|
||||
FB_SIZE1 : IN STD_LOGIC;
|
||||
nFB_BURST : IN STD_LOGIC;
|
||||
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
|
||||
nRSTO : IN STD_LOGIC;
|
||||
nFB_CS3 : IN STD_LOGIC;
|
||||
nSRCS : INOUT STD_LOGIC;
|
||||
nSRBLE : OUT STD_LOGIC;
|
||||
nSRBHE : OUT STD_LOGIC;
|
||||
nSRWE : OUT STD_LOGIC;
|
||||
nSROE : OUT STD_LOGIC;
|
||||
DSP_INT : OUT STD_LOGIC;
|
||||
DSP_TA : OUT STD_LOGIC;
|
||||
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
|
||||
IO : INOUT STD_LOGIC_VECTOR(17 downto 0);
|
||||
SRD : INOUT STD_LOGIC_VECTOR(15 downto 0)
|
||||
);
|
||||
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
|
||||
|
||||
END DSP;
|
||||
|
||||
|
||||
-- Architecture Body
|
||||
|
||||
ARCHITECTURE DSP_architecture OF DSP IS
|
||||
|
||||
|
||||
BEGIN
|
||||
nSRCS <= '0' when nFB_CS2 = '0' and FB_ADR(27 downto 24) = x"4" else '1'; --nFB_CS3;
|
||||
nSRBHE <= '0' when FB_ADR(0 downto 0) = "0" else '1';
|
||||
nSRBLE <= '1' when FB_ADR(0 downto 0) = "0" and FB_SIZE1 = '0' and FB_SIZE0 = '1' else '0';
|
||||
nSRWE <= '0' when nFB_WR = '0' and nSRCS = '0' and MAIN_CLK = '0' else '1';
|
||||
nSROE <= '0' when nFB_OE = '0' and nSRCS = '0' else '1';
|
||||
DSP_INT <= '0';
|
||||
DSP_TA <= '0';
|
||||
IO(17 downto 0) <= FB_ADR(18 downto 1);
|
||||
SRD(15 downto 0) <= FB_AD(31 downto 16) when nFB_WR = '0' and nSRCS = '0' else "ZZZZZZZZZZZZZZZZ";
|
||||
FB_AD(31 downto 16) <= SRD(15 downto 0) when nFB_OE = '0' and nSRCS = '0' else "ZZZZZZZZZZZZZZZZ";
|
||||
|
||||
|
||||
END DSP_architecture;
|
||||
79
FPGA_Quartus_13.1/DSP/DSP.vhd.bak
Normal file
79
FPGA_Quartus_13.1/DSP/DSP.vhd.bak
Normal file
@@ -0,0 +1,79 @@
|
||||
-- WARNING: Do NOT edit the input and output ports in this file in a text
|
||||
-- editor if you plan to continue editing the block that represents it in
|
||||
-- the Block Editor! File corruption is VERY likely to occur.
|
||||
|
||||
-- Copyright (C) 1991-2008 Altera Corporation
|
||||
-- Your use of Altera Corporation's design tools, logic functions
|
||||
-- and other software and tools, and its AMPP partner logic
|
||||
-- functions, and any output files from any of the foregoing
|
||||
-- (including device programming or simulation files), and any
|
||||
-- associated documentation or information are expressly subject
|
||||
-- to the terms and conditions of the Altera Program License
|
||||
-- Subscription Agreement, Altera MegaCore Function License
|
||||
-- Agreement, or other applicable license agreement, including,
|
||||
-- without limitation, that your use is for the sole purpose of
|
||||
-- programming logic devices manufactured by Altera and sold by
|
||||
-- Altera or its authorized distributors. Please refer to the
|
||||
-- applicable agreement for further details.
|
||||
|
||||
|
||||
-- Generated by Quartus II Version 8.1 (Build Build 163 10/28/2008)
|
||||
-- Created on Tue Sep 08 16:24:57 2009
|
||||
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
|
||||
-- Entity Declaration
|
||||
|
||||
ENTITY DSP IS
|
||||
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
|
||||
PORT
|
||||
(
|
||||
CLK33M : IN STD_LOGIC;
|
||||
MAIN_CLK : IN STD_LOGIC;
|
||||
nFB_OE : IN STD_LOGIC;
|
||||
nFB_WR : IN STD_LOGIC;
|
||||
nFB_CS1 : IN STD_LOGIC;
|
||||
nFB_CS2 : IN STD_LOGIC;
|
||||
FB_SIZE0 : IN STD_LOGIC;
|
||||
FB_SIZE1 : IN STD_LOGIC;
|
||||
nFB_BURST : IN STD_LOGIC;
|
||||
FB_ADR : IN STD_LOGIC_VECTOR(31 downto 0);
|
||||
nRSTO : IN STD_LOGIC;
|
||||
nFB_CS3 : IN STD_LOGIC;
|
||||
nSRCS : OUT STD_LOGIC;
|
||||
nSRBLE : OUT STD_LOGIC;
|
||||
nSRBHE : OUT STD_LOGIC;
|
||||
nSRWE : OUT STD_LOGIC;
|
||||
nSROE : OUT STD_LOGIC;
|
||||
DSP_INT : OUT STD_LOGIC;
|
||||
DSP_TA : OUT STD_LOGIC;
|
||||
FB_AD : INOUT STD_LOGIC_VECTOR(31 downto 0);
|
||||
IO : INOUT STD_LOGIC_VECTOR(17 downto 0);
|
||||
SRD : INOUT STD_LOGIC_VECTOR(15 downto 0)
|
||||
);
|
||||
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
|
||||
|
||||
END DSP;
|
||||
|
||||
|
||||
-- Architecture Body
|
||||
|
||||
ARCHITECTURE DSP_architecture OF DSP IS
|
||||
|
||||
|
||||
BEGIN
|
||||
nSRCS <= '0' when nFB_CS2 = '0' and FB_ADR(27 downto 24) = x"4" else '1'; --nFB_CS3;
|
||||
nSRBHE <= '0' when FB_ADR(0 downto 0) = "0" else '1';
|
||||
nSRBLE <= '1' when FB_ADR(0 downto 0) = "0" and FB_SIZE1 = '0' and FB_SIZE0 = '1' else '0';
|
||||
nSRWE <= '0' when nFB_WR = '0' and nSRCS = '0' and MAIN_CLK = '0' else '1';
|
||||
nSROE <= '0' when nFB_OE = '0' and nSRCS = '0' else '1';
|
||||
DSP_INT <= '0';
|
||||
DSP_TA <= '0';
|
||||
IO(17 downto 0) <= FB_ADR(18 downto 1);
|
||||
SRD(15 downto 0) <= FB_AD(31 downto 16) when nFB_WR = '0' and nSRCS = '0' else "ZZZZZZZZZZZZZZZZ";
|
||||
FB_AD(31 downto 16) <= SRD(15 downto 0) when nFB_OE = '0' and nSRCS = '0' else "ZZZZZZZZZZZZZZZZ";
|
||||
|
||||
|
||||
END DSP_architecture;
|
||||
BIN
FPGA_Quartus_13.1/DSP/dsp56k.zip
Normal file
BIN
FPGA_Quartus_13.1/DSP/dsp56k.zip
Normal file
Binary file not shown.
216
FPGA_Quartus_13.1/DSP/src/adgen_stage.vhd
Normal file
216
FPGA_Quartus_13.1/DSP/src/adgen_stage.vhd
Normal file
@@ -0,0 +1,216 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity adgen_stage is port(
|
||||
activate_adgen : in std_logic;
|
||||
activate_x_mem : in std_logic;
|
||||
activate_y_mem : in std_logic;
|
||||
activate_l_mem : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
optional_ea_word : in std_logic_vector(23 downto 0);
|
||||
register_file : in register_file_type;
|
||||
adgen_mode_a : in adgen_mode_type;
|
||||
adgen_mode_b : in adgen_mode_type;
|
||||
address_out_x : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
address_out_y : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
wr_R_port_A_valid : out std_logic;
|
||||
wr_R_port_A : out addr_wr_port_type;
|
||||
wr_R_port_B_valid : out std_logic;
|
||||
wr_R_port_B : out addr_wr_port_type
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of adgen_stage is
|
||||
|
||||
signal address_out_x_int : unsigned(BW_ADDRESS-1 downto 0);
|
||||
|
||||
|
||||
begin
|
||||
|
||||
address_out_x <= address_out_x_int;
|
||||
|
||||
address_generator_X: process(activate_adgen, instr_word, register_file, adgen_mode_a) is
|
||||
variable r_reg_local : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable n_reg_local : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable m_reg_local : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable op1 : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable op2 : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable addr_mod : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable new_r_reg : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable new_r_reg_interm : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable modulo_bitmask : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
variable bit_set : std_logic;
|
||||
begin
|
||||
r_reg_local := register_file.addr_r(to_integer(unsigned(instr_word(10 downto 8))));
|
||||
n_reg_local := register_file.addr_n(to_integer(unsigned(instr_word(10 downto 8))));
|
||||
m_reg_local := register_file.addr_m(to_integer(unsigned(instr_word(10 downto 8))));
|
||||
|
||||
-- select the operands for the calculation
|
||||
case adgen_mode_a is
|
||||
-- (Rn) - Nn
|
||||
when POST_MIN_N => addr_mod := unsigned(- signed(n_reg_local));
|
||||
-- (Rn) + Nn
|
||||
when POST_PLUS_N => addr_mod := n_reg_local;
|
||||
-- (Rn)-
|
||||
when POST_MIN_1 => addr_mod := (others => '1'); -- -1
|
||||
-- (Rn)+
|
||||
when POST_PLUS_1 => addr_mod := to_unsigned(1, BW_ADDRESS);
|
||||
-- (Rn)
|
||||
when NOP => addr_mod := (others => '0');
|
||||
-- (Rn + Nn)
|
||||
when INDEXED_N => addr_mod := n_reg_local;
|
||||
-- -(Rn)
|
||||
when PRE_MIN_1 => addr_mod := (others => '1'); -- - 1
|
||||
-- absolute address (appended to instruction word)
|
||||
when ABSOLUTE => addr_mod := (others => '0');
|
||||
when IMMEDIATE => addr_mod := (others => '0');
|
||||
end case;
|
||||
|
||||
op1 := r_reg_local;
|
||||
op2 := addr_mod;
|
||||
-- linear addressing
|
||||
if m_reg_local = 2**BW_ADDRESS-1 then
|
||||
op1 := r_reg_local;
|
||||
op2 := addr_mod;
|
||||
-- bit reverse operation
|
||||
elsif m_reg_local = 0 then
|
||||
-- reverse the input to the adder bit wise
|
||||
-- so we just need to use a single adder
|
||||
for i in 0 to BW_ADDRESS-1 loop
|
||||
op1(BW_ADDRESS - 1 - i) := r_reg_local(i);
|
||||
op2(BW_ADDRESS - 1 - i) := addr_mod(i);
|
||||
end loop;
|
||||
-- modulo arithmetic
|
||||
else
|
||||
bit_set := '0';
|
||||
for i in BW_ADDRESS-1 downto 0 loop
|
||||
if m_reg_local(i) = '1' then
|
||||
bit_set := '1';
|
||||
end if;
|
||||
if bit_set = '1' then
|
||||
modulo_bitmask(i) := '0';
|
||||
else
|
||||
modulo_bitmask(i) := '1';
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
new_r_reg_interm := op1 + op2;
|
||||
|
||||
new_r_reg := new_r_reg_interm;
|
||||
-- linear addressing
|
||||
if m_reg_local = 2**BW_ADDRESS-1 then
|
||||
new_r_reg := new_r_reg_interm;
|
||||
-- bit reverse operation
|
||||
elsif m_reg_local = 0 then
|
||||
for i in 0 to BW_ADDRESS-1 loop
|
||||
new_r_reg(BW_ADDRESS - 1 - i) := new_r_reg_interm(i);
|
||||
end loop;
|
||||
else
|
||||
|
||||
end if;
|
||||
|
||||
-- store the updated register in the global register file
|
||||
-- do not store when we do nothing or there is nothing to update
|
||||
-- LUA instructions DO NOT UPDATE the source register!!
|
||||
if (adgen_mode_a = NOP or adgen_mode_a = ABSOLUTE or adgen_mode_a = IMMEDIATE or instr_array = INSTR_LUA) then
|
||||
wr_R_port_A_valid <= '0';
|
||||
else
|
||||
wr_R_port_A_valid <= '1';
|
||||
end if;
|
||||
wr_R_port_A.reg_number <= unsigned(instr_word(10 downto 8));
|
||||
wr_R_port_A.reg_value <= new_r_reg;
|
||||
|
||||
-- select the output of the AGU
|
||||
case adgen_mode_a is
|
||||
-- (Rn) - Nn
|
||||
when POST_MIN_N => address_out_x_int <= r_reg_local;
|
||||
-- (Rn) + Nn
|
||||
when POST_PLUS_N => address_out_x_int <= r_reg_local;
|
||||
-- (Rn)-
|
||||
when POST_MIN_1 => address_out_x_int <= r_reg_local;
|
||||
-- (Rn)+
|
||||
when POST_PLUS_1 => address_out_x_int <= r_reg_local;
|
||||
-- (Rn)
|
||||
when NOP => address_out_x_int <= r_reg_local;
|
||||
-- (Rn + Nn)
|
||||
when INDEXED_N => address_out_x_int <= new_r_reg;
|
||||
-- -(Rn)
|
||||
when PRE_MIN_1 => address_out_x_int <= new_r_reg;
|
||||
-- absolute address (appended to instruction word)
|
||||
when ABSOLUTE => address_out_x_int <= unsigned(optional_ea_word(BW_ADDRESS-1 downto 0));
|
||||
when IMMEDIATE => address_out_x_int <= r_reg_local; -- Done externally, value never used
|
||||
end case;
|
||||
-- LUA instructions only use the updated address!
|
||||
if instr_array = INSTR_LUA then
|
||||
address_out_x_int <= new_r_reg;
|
||||
end if;
|
||||
|
||||
end process address_generator_X;
|
||||
|
||||
address_generator_Y: process(activate_adgen, activate_x_mem, activate_y_mem, activate_l_mem, instr_word,
|
||||
register_file, adgen_mode_b, address_out_x_int) is
|
||||
variable r_reg_local : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable n_reg_local : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable m_reg_local : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable op2 : unsigned(BW_ADDRESS-1 downto 0);
|
||||
variable new_r_reg : unsigned(BW_ADDRESS-1 downto 0);
|
||||
begin
|
||||
r_reg_local := register_file.addr_r(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
|
||||
n_reg_local := register_file.addr_n(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
|
||||
m_reg_local := register_file.addr_m(to_integer(unsigned((not instr_word(10)) & instr_word(14 downto 13))));
|
||||
|
||||
-- select the operands for the calculation
|
||||
case adgen_mode_b is
|
||||
-- (Rn) + Nn
|
||||
when POST_PLUS_N => op2 := n_reg_local;
|
||||
-- (Rn)-
|
||||
when POST_MIN_1 => op2 := (others => '1'); -- -1
|
||||
-- (Rn)+
|
||||
when POST_PLUS_1 => op2 := to_unsigned(1, BW_ADDRESS);
|
||||
-- (Rn)
|
||||
when others => op2 := (others => '0');
|
||||
end case;
|
||||
|
||||
new_r_reg := r_reg_local + op2;
|
||||
-- TODO: USE modifier register!
|
||||
|
||||
-- store the updated register in the global register file
|
||||
-- do not store when we do nothing or there is nothing to update
|
||||
if adgen_mode_b = NOP then
|
||||
wr_R_port_B_valid <= '0';
|
||||
else
|
||||
wr_R_port_B_valid <= '1';
|
||||
end if;
|
||||
wr_R_port_B.reg_number <= unsigned((not instr_word(10)) & instr_word(14 downto 13));
|
||||
wr_R_port_B.reg_value <= new_r_reg;
|
||||
|
||||
-- the address for the y memory is calculated in the first AGU if the x memory is not accessed!
|
||||
-- so use the other output as address output for the y memory!
|
||||
-- Furthermore, use the same address for L memory accesses (X and Y memory access the same address!)
|
||||
if (activate_y_mem = '1' and activate_x_mem = '0') or activate_l_mem = '1' then
|
||||
address_out_y <= address_out_x_int;
|
||||
-- in any other case use the locally computed value
|
||||
else
|
||||
-- select the output of the AGU
|
||||
case adgen_mode_b is
|
||||
-- (Rn) + Nn
|
||||
when POST_PLUS_N => address_out_y <= r_reg_local;
|
||||
-- (Rn)-
|
||||
when POST_MIN_1 => address_out_y <= r_reg_local;
|
||||
-- (Rn)+
|
||||
when POST_PLUS_1 => address_out_y <= r_reg_local;
|
||||
-- (Rn)
|
||||
when others => address_out_y <= r_reg_local;
|
||||
end case;
|
||||
end if;
|
||||
end process address_generator_Y;
|
||||
|
||||
end architecture;
|
||||
62
FPGA_Quartus_13.1/DSP/src/constants_pkg.vhd
Normal file
62
FPGA_Quartus_13.1/DSP/src/constants_pkg.vhd
Normal file
@@ -0,0 +1,62 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
|
||||
|
||||
package constants_pkg is
|
||||
|
||||
-------------------------
|
||||
-- Flags in CCR register
|
||||
-------------------------
|
||||
constant C_FLAG : natural := 0;
|
||||
constant V_FLAG : natural := 1;
|
||||
constant Z_FLAG : natural := 2;
|
||||
constant N_FLAG : natural := 3;
|
||||
constant U_FLAG : natural := 4;
|
||||
constant E_FLAG : natural := 5;
|
||||
constant L_FLAG : natural := 6;
|
||||
constant S_FLAG : natural := 7;
|
||||
|
||||
-------------------
|
||||
-- Pipeline stages
|
||||
-------------------
|
||||
constant ST_FETCH : natural := 0;
|
||||
constant ST_FETCH2 : natural := 1;
|
||||
constant ST_DECODE : natural := 2;
|
||||
constant ST_ADGEN : natural := 3;
|
||||
constant ST_EXEC : natural := 4;
|
||||
|
||||
----------------------
|
||||
-- Activation signals
|
||||
----------------------
|
||||
constant ACT_ADGEN : natural := 0; -- Run the address generator
|
||||
constant ACT_ALU : natural := 1; -- Activation of ALU results in modification of the status register
|
||||
constant ACT_EXEC_BRA : natural := 2; -- Branch (in execute stage)
|
||||
constant ACT_EXEC_CR_MOD : natural := 3; -- Control Register Modification (in execute stage)
|
||||
constant ACT_EXEC_LOOP : natural := 4; -- Loop instruction (REP, DO)
|
||||
constant ACT_X_MEM_RD : natural := 5; -- Init read from X memory
|
||||
constant ACT_Y_MEM_RD : natural := 6; -- Init read from Y memory
|
||||
constant ACT_P_MEM_RD : natural := 7; -- Init read from P memory
|
||||
constant ACT_X_MEM_WR : natural := 8; -- Init write to X memory
|
||||
constant ACT_Y_MEM_WR : natural := 9; -- Init write to Y memory
|
||||
constant ACT_P_MEM_WR : natural := 10; -- Init write to P memory
|
||||
constant ACT_REG_RD : natural := 11; -- Read from register (6 bit addressing)
|
||||
constant ACT_REG_WR : natural := 12; -- Write to register (6 bit addressing)
|
||||
constant ACT_IMM_8BIT : natural := 13; -- 8 bit immediate operand (in instruction word)
|
||||
constant ACT_IMM_12BIT : natural := 14; -- 12 bit immediate operand (in instruction word)
|
||||
constant ACT_IMM_LONG : natural := 15; -- 24 bit immediate operant (in optional instruction word)
|
||||
constant ACT_X_BUS_RD : natural := 16; -- Read data via X-bus (from x0,x1,a,b)
|
||||
constant ACT_X_BUS_WR : natural := 17; -- Write data via X-bus (to x0,x1,a,b)
|
||||
constant ACT_Y_BUS_RD : natural := 18; -- Read data via Y-bus (from y0,y1,a,b)
|
||||
constant ACT_Y_BUS_WR : natural := 19; -- Write data via Y-bus (to y0,y1,a,b)
|
||||
constant ACT_L_BUS_RD : natural := 20; -- Read data via L-bus (from a10, b10,x,y,a,b,ab,ba)
|
||||
constant ACT_L_BUS_WR : natural := 21; -- Write data via L-bus (to a10, b10,x,y,a,b,ab,ba)
|
||||
constant ACT_BIT_MOD_WR : natural := 22; -- Bit modify write (to set for BSET, BCLR, BCHG)
|
||||
constant ACT_REG_WR_CC : natural := 23; -- Write to register file conditionally (Tcc)
|
||||
constant ACT_ALU_WR_CC : natural := 24; -- Write ALU result conditionally (Tcc)
|
||||
constant ACT_NORM : natural := 25; -- NORM instruction needs special handling
|
||||
|
||||
end package constants_pkg;
|
||||
1221
FPGA_Quartus_13.1/DSP/src/decode_stage.vhd
Normal file
1221
FPGA_Quartus_13.1/DSP/src/decode_stage.vhd
Normal file
File diff suppressed because it is too large
Load Diff
603
FPGA_Quartus_13.1/DSP/src/exec_stage_alu.vhd
Normal file
603
FPGA_Quartus_13.1/DSP/src/exec_stage_alu.vhd
Normal file
@@ -0,0 +1,603 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_alu is port(
|
||||
alu_activate : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
alu_ctrl : in alu_ctrl_type;
|
||||
register_file : in register_file_type;
|
||||
addr_r_in : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
addr_r_out : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_accu : out std_logic;
|
||||
dst_accu : out std_logic;
|
||||
modified_accu : out signed(55 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of exec_stage_alu is
|
||||
|
||||
signal alu_shifter_out : signed(55 downto 0);
|
||||
signal alu_shifter_carry_out : std_logic;
|
||||
signal alu_shifter_overflow_out : std_logic;
|
||||
|
||||
signal alu_logic_conj : signed(55 downto 0);
|
||||
signal alu_multiplier_out : signed(55 downto 0);
|
||||
signal alu_src_op : signed(55 downto 0);
|
||||
signal alu_add_result : signed(56 downto 0);
|
||||
signal alu_add_carry_out : std_logic;
|
||||
signal alu_post_adder_result : signed(56 downto 0);
|
||||
|
||||
signal scaling_mode : std_logic_vector(1 downto 0);
|
||||
|
||||
signal modified_accu_int : signed(55 downto 0);
|
||||
|
||||
signal norm_instr_asl : std_logic;
|
||||
signal norm_instr_asr : std_logic;
|
||||
signal norm_instr_nop : std_logic;
|
||||
signal norm_update_ccr : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
|
||||
-- store calculated value?
|
||||
modify_accu <= alu_ctrl.store_result;
|
||||
modified_accu <= modified_accu_int;
|
||||
-- for the norm instruction we first need to determine whether we have to
|
||||
-- update the CCR register or not
|
||||
modify_sr <= alu_activate when alu_ctrl.norm_instr = '0' else
|
||||
norm_update_ccr;
|
||||
dst_accu <= alu_ctrl.dst_accu;
|
||||
|
||||
scaling_mode <= register_file.sr(11 downto 10);
|
||||
|
||||
|
||||
calcule_ccr_flags: process(register_file, alu_ctrl, alu_shifter_carry_out,
|
||||
alu_post_adder_result, modified_accu_int, alu_add_carry_out) is
|
||||
begin
|
||||
-- by default do not modify the flags in the status register
|
||||
modified_sr <= register_file.sr;
|
||||
|
||||
-- Carry flag generation
|
||||
-------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(C_FLAG) is
|
||||
when CLEAR => modified_sr(C_FLAG) <= '0';
|
||||
when SET => modified_sr(C_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- the carry flag can stem from the shifter or from the post adder
|
||||
-- in case we shift and add only a zero to the shift result (ASL, ASR, LSL, LSR, ROL, ROR)
|
||||
-- take the carry flag from the shifter, else from the post adder
|
||||
if (alu_ctrl.shift_mode = SHIFT_LEFT or alu_ctrl.shift_mode = SHIFT_RIGHT) and
|
||||
alu_ctrl.add_src_stage_2 = "00" then -- add zero after shifting?
|
||||
modified_sr(C_FLAG) <= alu_shifter_carry_out;
|
||||
elsif alu_ctrl.div_instr = '1' then
|
||||
modified_sr(C_FLAG) <= not std_logic(alu_post_adder_result(55));
|
||||
else
|
||||
-- modified_sr(C_FLAG) <= std_logic(alu_post_adder_result(57));
|
||||
modified_sr(C_FLAG) <= alu_add_carry_out;
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Overflow flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(V_FLAG) is
|
||||
when CLEAR => modified_sr(V_FLAG) <= '0';
|
||||
when SET => modified_sr(V_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- There are two sources for the overflow flag:
|
||||
-- 1)
|
||||
-- in case the result cannot be represented using 56 bits set
|
||||
-- the overflow flag. this is the case when the two MSBs of
|
||||
-- the 57 bit result are different
|
||||
-- 2)
|
||||
-- The shifter circuit performs a 56 bit left shift. In case the
|
||||
-- two MSBs of the operand are different set the overflow flag as well
|
||||
if (alu_ctrl.div_instr = '0' and alu_post_adder_result(56) /= alu_post_adder_result(55)) or
|
||||
(alu_ctrl.shift_mode = SHIFT_LEFT and alu_ctrl.word_24_update = '0' and
|
||||
alu_shifter_overflow_out = '1' ) then
|
||||
modified_sr(V_FLAG) <= '1';
|
||||
else
|
||||
modified_sr(V_FLAG) <= '0';
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Zero flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(Z_FLAG) is
|
||||
when CLEAR => modified_sr(Z_FLAG) <= '0';
|
||||
when SET => modified_sr(Z_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- in case the result is zero set this flag
|
||||
-- distinguish between 24 bit and 56 bit ALU operations
|
||||
-- 24 bit instructions are LSL, LSR, ROR, ROL, OR, EOR, NOT, AND
|
||||
if (alu_ctrl.word_24_update = '1' and modified_accu_int(47 downto 24) = 0) or
|
||||
(alu_ctrl.word_24_update = '0' and modified_accu_int(55 downto 0) = 0) then
|
||||
modified_sr(Z_FLAG) <= '1';
|
||||
else
|
||||
modified_sr(Z_FLAG) <= '0';
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Negative flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(N_FLAG) is
|
||||
when CLEAR => modified_sr(N_FLAG) <= '0';
|
||||
when SET => modified_sr(N_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- in case the result is negative set this flag
|
||||
-- distinguish between 24 bit and 56 bit ALU operations
|
||||
-- 24 bit instructions are LSL, LSR, ROR, ROL, OR, EOR, NOT, AND
|
||||
if alu_ctrl.word_24_update = '1' then
|
||||
modified_sr(N_FLAG) <= std_logic(modified_accu_int(47));
|
||||
else
|
||||
modified_sr(N_FLAG) <= std_logic(modified_accu_int(55));
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Unnormalized flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(U_FLAG) is
|
||||
when CLEAR => modified_sr(U_FLAG) <= '0';
|
||||
when SET => modified_sr(U_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- Set unnormalized bit according to the scaling mode
|
||||
if (scaling_mode = "00" and alu_post_adder_result(47) = alu_post_adder_result(46)) or
|
||||
(scaling_mode = "01" and alu_post_adder_result(48) = alu_post_adder_result(47)) or
|
||||
(scaling_mode = "10" and alu_post_adder_result(46) = alu_post_adder_result(45)) then
|
||||
modified_sr(U_FLAG) <= '1';
|
||||
else
|
||||
modified_sr(U_FLAG) <= '0';
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Extension flag generation
|
||||
----------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(E_FLAG) is
|
||||
when CLEAR => modified_sr(E_FLAG) <= '0';
|
||||
when SET => modified_sr(E_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- Set extension flag by default
|
||||
modified_sr(E_FLAG) <= '1';
|
||||
-- Clear extension flag according to the scaling mode
|
||||
case scaling_mode is
|
||||
when "00" =>
|
||||
if alu_post_adder_result(55 downto 47) = "111111111" or alu_post_adder_result(55 downto 47) = "000000000" then
|
||||
modified_sr(E_FLAG) <= '0';
|
||||
end if;
|
||||
when "01" =>
|
||||
if alu_post_adder_result(55 downto 48) = "11111111" or alu_post_adder_result(55 downto 48) = "00000000" then
|
||||
modified_sr(E_FLAG) <= '0';
|
||||
end if;
|
||||
when "10" =>
|
||||
if alu_post_adder_result(55 downto 46) = "1111111111" or alu_post_adder_result(55 downto 46) = "0000000000" then
|
||||
modified_sr(E_FLAG) <= '0';
|
||||
end if;
|
||||
when others =>
|
||||
modified_sr(E_FLAG) <= '0';
|
||||
end case;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Limit flag generation (equals overflow flag generaton!)
|
||||
-- Clearing of the Limit flag has to be done by the user!
|
||||
-----------------------------------------------------------
|
||||
case alu_ctrl.ccr_flags_ctrl(L_FLAG) is
|
||||
when CLEAR => modified_sr(L_FLAG) <= '0';
|
||||
when SET => modified_sr(L_FLAG) <= '1';
|
||||
when MODIFY =>
|
||||
-- There are two sources for the overflow flag:
|
||||
-- 1)
|
||||
-- in case the result cannot be represented using 56 bits set
|
||||
-- the overflow flag. this is the case when the two MSBs of
|
||||
-- the 57 bit result are different
|
||||
-- 2)
|
||||
-- The shifter circuit performs a 56 bit left shift. In case the
|
||||
-- two MSBs of the operand are different set the overflow flag as well
|
||||
if (alu_ctrl.div_instr = '0' and alu_post_adder_result(56) /= alu_post_adder_result(55)) or
|
||||
(alu_ctrl.shift_mode = SHIFT_LEFT and alu_ctrl.word_24_update = '0' and
|
||||
alu_shifter_overflow_out = '1' ) then
|
||||
modified_sr(L_FLAG) <= '1';
|
||||
end if;
|
||||
when others => -- Don't touch
|
||||
end case;
|
||||
|
||||
-- Scaling flag generation (DSP56002 and up)
|
||||
--------------------------------------------
|
||||
-- Scaling flag is not generated in the ALU, but when A or B are read to the XDB or YDB
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
src_operand_select: process(register_file, alu_ctrl) is
|
||||
begin
|
||||
-- decoding according similar to JJJ representation
|
||||
case alu_ctrl.add_src_stage_1 is
|
||||
when "000" =>
|
||||
-- select depending on destination accu
|
||||
if alu_ctrl.dst_accu = '0' then
|
||||
alu_src_op <= register_file.a;
|
||||
else
|
||||
alu_src_op <= register_file.b;
|
||||
end if;
|
||||
when "001" => -- A,B or B,A
|
||||
-- select depending on destination accu
|
||||
if alu_ctrl.dst_accu = '0' then
|
||||
alu_src_op <= register_file.b;
|
||||
else
|
||||
alu_src_op <= register_file.a;
|
||||
end if;
|
||||
when "010" => -- X
|
||||
alu_src_op(55 downto 48) <= (others => register_file.x1(23));
|
||||
alu_src_op(47 downto 0) <= register_file.x1 & register_file.x0;
|
||||
when "011" => -- Y
|
||||
alu_src_op(55 downto 48) <= (others => register_file.y1(23));
|
||||
alu_src_op(47 downto 0) <= register_file.y1 & register_file.y0;
|
||||
when "100" => -- x0
|
||||
alu_src_op(55 downto 48) <= (others => register_file.x0(23));
|
||||
alu_src_op(47 downto 24) <= register_file.x0;
|
||||
alu_src_op(23 downto 0) <= (others => '0');
|
||||
when "101" => -- y0
|
||||
alu_src_op(55 downto 48) <= (others => register_file.y0(23));
|
||||
alu_src_op(47 downto 24) <= register_file.y0;
|
||||
alu_src_op(23 downto 0) <= (others => '0');
|
||||
when "110" => -- x1
|
||||
alu_src_op(55 downto 48) <= (others => register_file.x1(23));
|
||||
alu_src_op(47 downto 24) <= register_file.x1;
|
||||
alu_src_op(23 downto 0) <= (others => '0');
|
||||
when "111" => -- y1
|
||||
alu_src_op(55 downto 48) <= (others => register_file.y1(23));
|
||||
alu_src_op(47 downto 24) <= register_file.y1;
|
||||
alu_src_op(23 downto 0) <= (others => '0');
|
||||
when others =>
|
||||
end case;
|
||||
end process;
|
||||
|
||||
alu_logical_functions: process(alu_ctrl, alu_src_op, alu_shifter_out) is
|
||||
begin
|
||||
alu_logic_conj <= alu_shifter_out;
|
||||
case alu_ctrl.logic_function is
|
||||
when "110" =>
|
||||
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) and alu_src_op(47 downto 24);
|
||||
when "010" =>
|
||||
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) or alu_src_op(47 downto 24);
|
||||
when "011" =>
|
||||
alu_logic_conj(47 downto 24) <= alu_shifter_out(47 downto 24) xor alu_src_op(47 downto 24);
|
||||
when "111" =>
|
||||
alu_logic_conj(47 downto 24) <= not alu_shifter_out(47 downto 24);
|
||||
when others =>
|
||||
end case;
|
||||
end process;
|
||||
|
||||
alu_adder : process(alu_ctrl, alu_src_op, alu_multiplier_out, alu_shifter_out) is
|
||||
variable add_src_op_1 : signed(56 downto 0);
|
||||
variable add_src_op_2 : signed(56 downto 0);
|
||||
variable carry_const : signed(56 downto 0);
|
||||
variable alu_shifter_out_57 : signed(56 downto 0);
|
||||
variable alu_add_result_58 : signed(57 downto 0);
|
||||
variable alu_add_result_interm : signed(56 downto 0);
|
||||
variable invert_carry_flag : std_logic;
|
||||
begin
|
||||
|
||||
-- by default do not invert the carry
|
||||
invert_carry_flag := '0';
|
||||
|
||||
-- determine whether to use multiplier output, the operand defined above, or zeros!
|
||||
-- resizing is done here already. Like that we can see whether an overflow
|
||||
-- occurs due to negating the source operand
|
||||
case alu_ctrl.add_src_stage_2 is
|
||||
when "00" => add_src_op_1 := (others => '0');
|
||||
when "10" => add_src_op_1 := resize(alu_multiplier_out, 57);
|
||||
when others => add_src_op_1 := resize(alu_src_op, 57);
|
||||
end case;
|
||||
|
||||
-- determine the sign for the 1st operand!
|
||||
case alu_ctrl.add_src_sign is
|
||||
-- normal operation
|
||||
when "00" => add_src_op_1 := add_src_op_1;
|
||||
-- negative sign
|
||||
when "01" => add_src_op_1 := - add_src_op_1;
|
||||
invert_carry_flag := not invert_carry_flag;
|
||||
-- change according to sign
|
||||
-- performs - | accu | for the CMPM instruction
|
||||
when "10" =>
|
||||
-- we subtract in any case, so invert the carry!
|
||||
invert_carry_flag := not invert_carry_flag;
|
||||
if add_src_op_1(55) = '0' then
|
||||
add_src_op_1 := - add_src_op_1;
|
||||
else
|
||||
add_src_op_1 := add_src_op_1;
|
||||
end if;
|
||||
-- div instruction!
|
||||
-- sign dependant of D[55] XOR S[23], if 1 => positive , if 0 => negative
|
||||
-- add_src_op_1 holds S[23] (sign extension!)
|
||||
when others =>
|
||||
if (alu_ctrl.shift_src = '0' and add_src_op_1(55) /= register_file.a(55)) or
|
||||
(alu_ctrl.shift_src = '1' and add_src_op_1(55) /= register_file.b(55)) then
|
||||
add_src_op_1 := add_src_op_1;
|
||||
else
|
||||
add_src_op_1 := - add_src_op_1;
|
||||
-- invert_carry_flag := not invert_carry_flag;
|
||||
end if;
|
||||
end case;
|
||||
|
||||
alu_shifter_out_57 := resize(alu_shifter_out, 57);
|
||||
|
||||
-- determine the sign for the 2nd operand (coming from the shifter)!
|
||||
case alu_ctrl.shift_src_sign is
|
||||
-- negative sign
|
||||
when "01" =>
|
||||
add_src_op_2 := - alu_shifter_out_57;
|
||||
-- change according to sign
|
||||
-- this allows to build the magnitude (ABS, CMPM)
|
||||
when "10" =>
|
||||
if alu_shifter_out(55) = '1' then
|
||||
add_src_op_2 := - alu_shifter_out_57;
|
||||
else
|
||||
add_src_op_2 := alu_shifter_out_57;
|
||||
end if;
|
||||
when others =>
|
||||
add_src_op_2 := alu_shifter_out_57;
|
||||
end case;
|
||||
|
||||
-- determine whether carry flag has to be added or subtracted
|
||||
if alu_ctrl.rounding_used = "10" then
|
||||
-- add carry flag
|
||||
carry_const(0) := register_file.sr(C_FLAG);
|
||||
elsif alu_ctrl.rounding_used = "11" then
|
||||
-- subtract carry flag
|
||||
carry_const := (others => register_file.sr(0)); -- carry flag
|
||||
else
|
||||
carry_const := (others => '0');
|
||||
end if;
|
||||
|
||||
-- add the values and calculate the carry bit
|
||||
alu_add_result_interm := ('0' & add_src_op_1(55 downto 0)) +
|
||||
('0' & add_src_op_2(55 downto 0)) +
|
||||
('0' & carry_const(55 downto 0));
|
||||
|
||||
-- here pops the new carry out of the adder
|
||||
if invert_carry_flag = '0' then
|
||||
alu_add_carry_out <= alu_add_result_interm(56);
|
||||
else
|
||||
alu_add_carry_out <= not alu_add_result_interm(56);
|
||||
end if;
|
||||
|
||||
-- calculate the last bit (56), in order to test for overflow later on
|
||||
alu_add_result(55 downto 0) <= alu_add_result_interm(55 downto 0);
|
||||
-- alu_add_result(56) <= add_src_op_1(56) xor add_src_op_2(56) xor alu_add_result_interm(56);
|
||||
alu_add_result(56) <= add_src_op_1(56) xor add_src_op_2(56)
|
||||
xor carry_const(56) xor alu_add_result_interm(56);
|
||||
|
||||
end process alu_adder;
|
||||
|
||||
|
||||
-- Adder after the normal arithmetic adder
|
||||
-- This adder is responsible for
|
||||
-- -- 1) carry addition
|
||||
-- -- 2) carry subtration
|
||||
-- 3) convergent rounding
|
||||
alu_post_adder: process(alu_add_result, scaling_mode, alu_ctrl) is
|
||||
variable post_adder_constant : signed(56 downto 0);
|
||||
variable testing_constant : signed(24 downto 0);
|
||||
begin
|
||||
-- by default add nothing
|
||||
post_adder_constant := (others => '0');
|
||||
|
||||
case alu_ctrl.rounding_used is
|
||||
-- rounding dependant on scaling bits
|
||||
when "01" =>
|
||||
case scaling_mode is
|
||||
-- no scaling
|
||||
when "00" => testing_constant := alu_add_result(23 downto 0) & '0';
|
||||
-- scale down
|
||||
when "01" => testing_constant := alu_add_result(24 downto 0);
|
||||
-- scale up
|
||||
when "10" => testing_constant := alu_add_result(22 downto 0) & "00";
|
||||
when others =>
|
||||
testing_constant := alu_add_result(23 downto 0) & '0';
|
||||
end case;
|
||||
|
||||
-- Special case!
|
||||
if testing_constant(24) = '1' and testing_constant(23 downto 0) = X"000000" then
|
||||
-- add depending on bit left to the rounding position
|
||||
case scaling_mode is
|
||||
-- no scaling
|
||||
when "00" => post_adder_constant(23) := alu_add_result(24);
|
||||
-- scale down
|
||||
when "01" => post_adder_constant(24) := alu_add_result(25);
|
||||
-- scale up
|
||||
when "10" => post_adder_constant(22) := alu_add_result(23);
|
||||
when others =>
|
||||
end case;
|
||||
else -- testing_constant /= X"1000000"
|
||||
-- add rounding constant depending on scaling mode
|
||||
-- results in round up if MSB of testing constant is set, else nothing happens
|
||||
case scaling_mode is
|
||||
-- no scaling
|
||||
when "00" => post_adder_constant(23) := '1';
|
||||
-- scale down
|
||||
when "01" => post_adder_constant(24) := '1';
|
||||
-- scale up
|
||||
when "10" => post_adder_constant(22) := '1';
|
||||
when others =>
|
||||
end case;
|
||||
end if;
|
||||
-- no rounding
|
||||
when others =>
|
||||
post_adder_constant := (others => '0');
|
||||
|
||||
end case;
|
||||
|
||||
-- Add the result of the first adder to the constant (e.g., carry flag)
|
||||
alu_post_adder_result <= alu_add_result + post_adder_constant;
|
||||
|
||||
-- When rounding is used set 24 LSBs to zero!
|
||||
if alu_ctrl.rounding_used = "01" then
|
||||
alu_post_adder_result(23 downto 0) <= (others => '0');
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
|
||||
alu_select_new_accu: process(alu_post_adder_result, alu_logic_conj, alu_ctrl) is
|
||||
begin
|
||||
if alu_ctrl.logic_function /= "000" then
|
||||
modified_accu_int <= alu_logic_conj;
|
||||
else
|
||||
modified_accu_int <= alu_post_adder_result(55 downto 0);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-- contains the 24*24 bit fractional multiplier
|
||||
alu_multiplier : process(register_file, alu_ctrl) is
|
||||
variable src_op1: signed(23 downto 0);
|
||||
variable src_op2: signed(23 downto 0);
|
||||
variable mul_result_interm : signed(47 downto 0);
|
||||
begin
|
||||
-- select source operands for multiplication
|
||||
case alu_ctrl.mul_op1 is
|
||||
when "00" => src_op1 := register_file.x0;
|
||||
when "01" => src_op1 := register_file.x1;
|
||||
when "10" => src_op1 := register_file.y0;
|
||||
when others => src_op1 := register_file.y1;
|
||||
end case;
|
||||
case alu_ctrl.mul_op2 is
|
||||
when "00" => src_op2 := register_file.x0;
|
||||
when "01" => src_op2 := register_file.x1;
|
||||
when "10" => src_op2 := register_file.y0;
|
||||
when others => src_op2 := register_file.y1;
|
||||
end case;
|
||||
|
||||
-- perform integer multiplication
|
||||
mul_result_interm := src_op1 * src_op2;
|
||||
|
||||
-- sign extension of result
|
||||
alu_multiplier_out(55 downto 48) <= (others => mul_result_interm(47));
|
||||
-- convert from two's complement representation to fractional format
|
||||
-- signed integer multiplication delivers twice the sign bit, but only one is needed for the
|
||||
-- fractional multiplication, so remove one and append a zero to the result
|
||||
alu_multiplier_out(47 downto 0) <= mul_result_interm(46 downto 0) & '0';
|
||||
|
||||
end process alu_multiplier;
|
||||
|
||||
|
||||
-- contains the data shifter
|
||||
alu_shifter: process(register_file, alu_ctrl, norm_instr_asl, norm_instr_asr) is
|
||||
variable src_accu : signed(55 downto 0);
|
||||
variable shift_to_perform : alu_shift_mode;
|
||||
begin
|
||||
-- read source accumulator
|
||||
if alu_ctrl.shift_src = '0' then
|
||||
src_accu := register_file.a;
|
||||
else
|
||||
src_accu := register_file.b;
|
||||
end if;
|
||||
|
||||
alu_shifter_carry_out <= '0';
|
||||
alu_shifter_overflow_out <= '0';
|
||||
|
||||
-- NORM instruction determines the shift value just
|
||||
-- in time, so overwrite the flag from the alu_ctrl
|
||||
-- for this instruction by the calculated value
|
||||
if alu_ctrl.norm_instr = '0' then
|
||||
shift_to_perform := alu_ctrl.shift_mode;
|
||||
else
|
||||
if norm_instr_asl = '1' then
|
||||
shift_to_perform := SHIFT_LEFT;
|
||||
elsif norm_instr_asr = '1' then
|
||||
shift_to_perform := SHIFT_RIGHT;
|
||||
else
|
||||
shift_to_perform := NO_SHIFT;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
case shift_to_perform is
|
||||
when NO_SHIFT =>
|
||||
alu_shifter_out <= src_accu;
|
||||
when SHIFT_LEFT =>
|
||||
-- ASL, ADDL, DIV?
|
||||
if alu_ctrl.word_24_update = '0' then
|
||||
-- special handling for div instruction required
|
||||
if alu_ctrl.div_instr = '1' then
|
||||
alu_shifter_out <= src_accu(54 downto 0) & register_file.sr(C_FLAG);
|
||||
else
|
||||
alu_shifter_out <= src_accu(54 downto 0) & '0';
|
||||
end if;
|
||||
alu_shifter_carry_out <= src_accu(55);
|
||||
-- detect overflow that results from left shifting
|
||||
-- Needed for ASL, ADDL, DIV instructions
|
||||
if src_accu(55) /= src_accu(54) then
|
||||
alu_shifter_overflow_out <= '1';
|
||||
end if;
|
||||
-- LSL/ROL?
|
||||
elsif alu_ctrl.word_24_update = '1' then
|
||||
alu_shifter_out(55 downto 48) <= src_accu(55 downto 48);
|
||||
alu_shifter_out(23 downto 0) <= src_accu(23 downto 0);
|
||||
alu_shifter_carry_out <= src_accu(47);
|
||||
if alu_ctrl.rotate = '0' then -- LSL ?
|
||||
alu_shifter_out(47 downto 24) <= src_accu(46 downto 24) & '0';
|
||||
else -- ROL ?
|
||||
alu_shifter_out(47 downto 24) <= src_accu(46 downto 24) & register_file.sr(C_FLAG);
|
||||
end if;
|
||||
end if;
|
||||
when SHIFT_RIGHT =>
|
||||
-- ASR?
|
||||
if alu_ctrl.word_24_update = '0' then
|
||||
alu_shifter_out <= src_accu(55) & src_accu(55 downto 1);
|
||||
alu_shifter_carry_out <= src_accu(0);
|
||||
-- LSR/ROR?
|
||||
elsif alu_ctrl.word_24_update = '1' then
|
||||
alu_shifter_out(55 downto 48) <= src_accu(55 downto 48);
|
||||
alu_shifter_out(23 downto 0) <= src_accu(23 downto 0);
|
||||
alu_shifter_carry_out <= src_accu(24);
|
||||
if alu_ctrl.rotate = '0' then -- LSR
|
||||
alu_shifter_out(47 downto 24) <= '0' & src_accu(47 downto 25);
|
||||
else -- ROR
|
||||
alu_shifter_out(47 downto 24) <= register_file.sr(C_FLAG) & src_accu(47 downto 25);
|
||||
end if;
|
||||
end if;
|
||||
when ZEROS =>
|
||||
alu_shifter_out <= (others => '0');
|
||||
end case;
|
||||
end process alu_shifter;
|
||||
|
||||
|
||||
-- Special handling for NORM instruction
|
||||
-- Determine which case occurs (see User's Manual for more information)
|
||||
norm_instr_logic: process(register_file, addr_r_in) is
|
||||
begin
|
||||
norm_instr_asl <= '0';
|
||||
norm_instr_asr <= '0';
|
||||
|
||||
-- Either left shift
|
||||
if register_file.sr(E_FLAG) = '0' and
|
||||
register_file.sr(U_FLAG) = '1' and
|
||||
register_file.sr(Z_FLAG) = '0' then
|
||||
norm_instr_asl <= '1';
|
||||
norm_update_ccr <= '1';
|
||||
addr_r_out <= addr_r_in - 1;
|
||||
-- Or right shift
|
||||
elsif register_file.sr(E_FLAG) = '1' then
|
||||
norm_instr_asr <= '1';
|
||||
norm_update_ccr <= '1';
|
||||
addr_r_out <= addr_r_in + 1;
|
||||
-- Or do nothing!
|
||||
else
|
||||
norm_update_ccr <= '0';
|
||||
addr_r_out <= addr_r_in;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
79
FPGA_Quartus_13.1/DSP/src/exec_stage_bit_modify.vhd
Normal file
79
FPGA_Quartus_13.1/DSP/src/exec_stage_bit_modify.vhd
Normal file
@@ -0,0 +1,79 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_bit_modify is port(
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
src_operand : in std_logic_vector(23 downto 0);
|
||||
register_file : in register_file_type;
|
||||
dst_operand : out std_logic_vector(23 downto 0);
|
||||
bit_cond_met : out std_logic;
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_bit_modify is
|
||||
|
||||
signal operand_bit : std_logic;
|
||||
signal src_operand_32 : std_logic_vector(31 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- this is just a helper signal to prevent the simulator
|
||||
-- to stop when accessing a bit > 23.
|
||||
src_operand_32 <= "00000000" & src_operand;
|
||||
-- read the bit we want to test (and modify)
|
||||
operand_bit <= src_operand_32(to_integer(unsigned(instr_word(4 downto 0))));
|
||||
|
||||
-- modify the Carry flag only for the bit modify instructions!
|
||||
modify_sr <= '1' when instr_array = INSTR_BCLR or instr_array = INSTR_BSET or instr_array = INSTR_BCHG or instr_array = INSTR_BTST else '0';
|
||||
modified_sr <= register_file.sr(15 downto 1) & operand_bit;
|
||||
|
||||
bit_operation: process(instr_word, instr_array, src_operand, operand_bit) is
|
||||
variable new_bit : std_logic;
|
||||
begin
|
||||
-- do nothing by default!
|
||||
dst_operand <= src_operand;
|
||||
bit_cond_met <= '0';
|
||||
|
||||
-- determine which bit to write
|
||||
if instr_array = INSTR_BCLR then
|
||||
new_bit := '0';
|
||||
elsif instr_array = INSTR_BSET then
|
||||
new_bit := '1';
|
||||
else -- BCHG
|
||||
new_bit := not operand_bit;
|
||||
end if;
|
||||
|
||||
if instr_array = INSTR_BCLR or instr_array = INSTR_BSET or instr_array = INSTR_BCHG then
|
||||
dst_operand(to_integer(unsigned(instr_word(4 downto 0)))) <= new_bit;
|
||||
end if;
|
||||
|
||||
|
||||
-- check for the jump instructions whether condition is met or not!
|
||||
if instr_array = INSTR_JCLR or instr_array = INSTR_JSCLR then
|
||||
if operand_bit = '0' then
|
||||
bit_cond_met <= '1';
|
||||
else
|
||||
bit_cond_met <= '0';
|
||||
end if;
|
||||
end if;
|
||||
if instr_array = INSTR_JSET or instr_array = INSTR_JSSET then
|
||||
if operand_bit = '0' then
|
||||
bit_cond_met <= '0';
|
||||
else
|
||||
bit_cond_met <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
end architecture;
|
||||
117
FPGA_Quartus_13.1/DSP/src/exec_stage_branch.vhd
Normal file
117
FPGA_Quartus_13.1/DSP/src/exec_stage_branch.vhd
Normal file
@@ -0,0 +1,117 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_branch is port(
|
||||
activate_exec_bra : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
jump_address : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
bit_cond_met : in std_logic;
|
||||
cc_flag_set : in std_logic;
|
||||
push_stack : out push_stack_type;
|
||||
pop_stack : out pop_stack_type;
|
||||
modify_pc : out std_logic;
|
||||
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_branch is
|
||||
|
||||
signal branch_condition_met : std_logic;
|
||||
signal modify_pc_int : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
modify_pc_int <= '1' when activate_exec_bra = '1' and branch_condition_met = '1' else '0';
|
||||
modify_pc <= modify_pc_int;
|
||||
|
||||
calculate_branch_condition : process(instr_word, instr_array, register_file, bit_cond_met)
|
||||
begin
|
||||
branch_condition_met <= '0';
|
||||
|
||||
-- unconditional jumps
|
||||
if instr_array = INSTR_JMP or
|
||||
instr_array = INSTR_JSR or
|
||||
instr_array = INSTR_RTI or
|
||||
instr_array = INSTR_RTS then
|
||||
-- jump always
|
||||
branch_condition_met <= '1';
|
||||
end if;
|
||||
-- then see whether the branch condition is satisfied
|
||||
if instr_array = INSTR_JCC or instr_array = INSTR_JSCC then
|
||||
branch_condition_met <= cc_flag_set;
|
||||
end if;
|
||||
-- jmp that is executed according to a certain bit condition
|
||||
if instr_array = INSTR_JCLR or instr_array = INSTR_JSCLR or
|
||||
instr_array = INSTR_JSET or instr_array = INSTR_JSSET then
|
||||
branch_condition_met <= bit_cond_met;
|
||||
end if;
|
||||
end process calculate_branch_condition;
|
||||
|
||||
|
||||
calculate_branch_target : process(instr_array, instr_word, jump_address)
|
||||
begin
|
||||
modified_pc <= jump_address;
|
||||
|
||||
-- address calculation is the same for the following instructions
|
||||
if instr_array = INSTR_JMP or
|
||||
instr_array = INSTR_JCC or
|
||||
instr_array = INSTR_JSCC or
|
||||
instr_array = INSTR_JSR then
|
||||
if instr_word(18) = '1' then
|
||||
-- short jump address included in opcode (bits 11 downto 0)
|
||||
modified_pc(11 downto 0) <= unsigned(instr_word(11 downto 0));
|
||||
elsif instr_word(18) = '0' then
|
||||
-- effective address defined by opcode and coming from address generator unit
|
||||
modified_pc <= jump_address;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- jump address contains the obligatory address of the second
|
||||
-- instruction word
|
||||
if instr_array = INSTR_JCLR or
|
||||
instr_array = INSTR_JSET or
|
||||
instr_array = INSTR_JSCLR or
|
||||
instr_array = INSTR_JSSET then
|
||||
modified_pc <= jump_address;
|
||||
end if;
|
||||
|
||||
-- target address is stored on the stack
|
||||
if instr_array = INSTR_RTS or
|
||||
instr_array = INSTR_RTI then
|
||||
modified_pc <= unsigned(register_file.current_ssh);
|
||||
end if;
|
||||
end process calculate_branch_target;
|
||||
|
||||
-- Subroutine functions need to store PC and SR on the stack
|
||||
push_stack.valid <= '1' when modify_pc_int = '1' and (instr_array = INSTR_JSCC or instr_array = INSTR_JSR or
|
||||
instr_array = INSTR_JSCLR or instr_array = INSTR_JSSET) else '0';
|
||||
push_stack.content <= PC_AND_SR;
|
||||
-- pc is set externally!
|
||||
push_stack.pc <= (others => '0');
|
||||
|
||||
-- RTI/RTS instructions need to read from the stack
|
||||
pop_stack.valid <= '1' when modify_pc_int = '1' and (instr_array = INSTR_RTI or instr_array = INSTR_RTS) else '0';
|
||||
|
||||
-- some instructions require to set the SR
|
||||
calculate_status_register : process(instr_array)
|
||||
begin
|
||||
modify_sr <= '0';
|
||||
modified_sr <= (others => '0');
|
||||
if instr_array = INSTR_RTI then
|
||||
modify_sr <= '1';
|
||||
modified_sr <= register_file.current_ssl;
|
||||
end if;
|
||||
end process calculate_status_register;
|
||||
|
||||
|
||||
end architecture rtl;
|
||||
75
FPGA_Quartus_13.1/DSP/src/exec_stage_cc_flag_calc.vhd
Normal file
75
FPGA_Quartus_13.1/DSP/src/exec_stage_cc_flag_calc.vhd
Normal file
@@ -0,0 +1,75 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_cc_flag_calc is port(
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
cc_flag_set : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_cc_flag_calc is
|
||||
|
||||
|
||||
begin
|
||||
|
||||
calculate_cc_flag : process(instr_word, instr_array, register_file)
|
||||
|
||||
variable cc_select : std_logic_vector(3 downto 0);
|
||||
|
||||
procedure calculate_cc_flag(cc: std_logic_vector(3 downto 0)) is
|
||||
variable c_flag : std_logic := register_file.ccr(0);
|
||||
variable v_flag : std_logic := register_file.ccr(1);
|
||||
variable z_flag : std_logic := register_file.ccr(2);
|
||||
variable n_flag : std_logic := register_file.ccr(3);
|
||||
variable u_flag : std_logic := register_file.ccr(4);
|
||||
variable e_flag : std_logic := register_file.ccr(5);
|
||||
variable l_flag : std_logic := register_file.ccr(6);
|
||||
|
||||
begin
|
||||
if (cc = "0000" and c_flag = '0') or -- CC: carry clear
|
||||
(cc = "1000" and c_flag = '1') or -- CS: carry set
|
||||
(cc = "0101" and e_flag = '0') or -- EC: extension clear
|
||||
(cc = "1010" and z_flag = '1') or -- EQ: equal
|
||||
(cc = "1101" and e_flag = '1') or -- ES: extension set
|
||||
(cc = "0001" and (n_flag = v_flag)) or -- GE: greater than or equal
|
||||
(cc = "0001" and ((n_flag xor v_flag) or z_flag) = '0') or -- GT: greater than
|
||||
(cc = "0110" and l_flag = '0') or -- LC: limit clear
|
||||
(cc = "1111" and ((n_flag xor v_flag) or z_flag ) = '1') or -- LE: less or equal
|
||||
(cc = "1110" and l_flag = '1') or -- LS: limit set
|
||||
(cc = "1001" and (n_flag /= v_flag)) or -- LT: less than
|
||||
(cc = "1011" and n_flag = '1') or -- MI: minus
|
||||
(cc = "0010" and z_flag = '0') or -- NE: not equal
|
||||
(cc = "1100" and (( not u_flag and not e_flag) or z_flag) = '1') or -- NR: normalized
|
||||
(cc = "0011" and n_flag = '0') or -- PL: plus
|
||||
(cc = "0100" and (( not u_flag and not e_flag ) or z_flag) = '0') -- NN: not normalized
|
||||
then
|
||||
cc_flag_set <= '1';
|
||||
end if;
|
||||
end procedure;
|
||||
|
||||
begin
|
||||
|
||||
cc_flag_set <= '0';
|
||||
|
||||
-- Rip the flags we have to test for from the instruction word
|
||||
if (instr_array = INSTR_JCC and instr_word(18) = '0') or
|
||||
(instr_array = INSTR_JSCC) then
|
||||
cc_select := instr_word(3 downto 0);
|
||||
else
|
||||
cc_select := instr_word(15 downto 12);
|
||||
end if;
|
||||
|
||||
calculate_cc_flag(cc_select);
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
end architecture;
|
||||
72
FPGA_Quartus_13.1/DSP/src/exec_stage_cr_mod.vhd
Normal file
72
FPGA_Quartus_13.1/DSP/src/exec_stage_cr_mod.vhd
Normal file
@@ -0,0 +1,72 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_cr_mod is port (
|
||||
activate_exec_cr_mod : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0);
|
||||
modify_omr : out std_logic;
|
||||
modified_omr : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end exec_stage_cr_mod;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_cr_mod is
|
||||
|
||||
begin
|
||||
|
||||
process(activate_exec_cr_mod, instr_word, instr_array, register_file) is
|
||||
variable imm8 : std_logic_vector(7 downto 0);
|
||||
variable op8 : std_logic_vector(7 downto 0);
|
||||
variable res8 : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
modify_sr <= '0';
|
||||
modify_omr <= '0';
|
||||
modified_sr <= (others => '0');
|
||||
modified_omr <= (others => '0');
|
||||
|
||||
imm8 := instr_word(15 downto 8);
|
||||
if instr_word(1 downto 0) = "00" then
|
||||
-- read MR
|
||||
op8 := register_file.mr;
|
||||
elsif instr_word(1 downto 0) = "01" then
|
||||
-- read CCR
|
||||
op8 := register_file.ccr;
|
||||
else -- instr_word(1 downto 0) = "10"
|
||||
-- read OMR
|
||||
op8 := register_file.omr;
|
||||
end if;
|
||||
|
||||
if instr_array = INSTR_ANDI then
|
||||
res8 := imm8 and op8;
|
||||
else -- instr_array = INSTR_ORI
|
||||
res8 := imm8 or op8;
|
||||
end if;
|
||||
|
||||
-- only write the result when activated
|
||||
if activate_exec_cr_mod = '1' then
|
||||
if instr_word(1 downto 0) = "00" then
|
||||
-- update MR
|
||||
modify_sr <= '1';
|
||||
modified_sr <= res8 & register_file.ccr;
|
||||
elsif instr_word(1 downto 0) = "01" then
|
||||
-- update CCR
|
||||
modify_sr <= '1';
|
||||
modified_sr <= register_file.mr & res8;
|
||||
elsif instr_word(1 downto 0) = "10" then
|
||||
-- update OMR
|
||||
modify_omr <= '1';
|
||||
modified_omr <= res8;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
200
FPGA_Quartus_13.1/DSP/src/exec_stage_loops.vhd
Normal file
200
FPGA_Quartus_13.1/DSP/src/exec_stage_loops.vhd
Normal file
@@ -0,0 +1,200 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity exec_stage_loop is port(
|
||||
clk, rst : in std_logic;
|
||||
activate_exec_loop : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
loop_iterations : in unsigned(15 downto 0);
|
||||
loop_address : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
loop_start_address: in unsigned(BW_ADDRESS-1 downto 0);
|
||||
register_file : in register_file_type;
|
||||
fetch_perform_enddo: in std_logic;
|
||||
memory_stall : in std_logic;
|
||||
push_stack : out push_stack_type;
|
||||
pop_stack : out pop_stack_type;
|
||||
stall_rep : out std_logic;
|
||||
stall_do : out std_logic;
|
||||
decrement_lc : out std_logic;
|
||||
modify_lc : out std_logic;
|
||||
modified_lc : out unsigned(15 downto 0);
|
||||
modify_la : out std_logic;
|
||||
modified_la : out unsigned(15 downto 0);
|
||||
modify_pc : out std_logic;
|
||||
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of exec_stage_loop is
|
||||
|
||||
signal rep_loop_polling : std_logic;
|
||||
signal do_loop_polling : std_logic;
|
||||
signal enddo_polling : std_logic;
|
||||
signal lc_temp : unsigned(15 downto 0);
|
||||
signal rf_lc_eq_1 : std_logic;
|
||||
signal memory_stall_t : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
modified_pc <= loop_start_address;
|
||||
|
||||
|
||||
-- loop counter in register file equal to 1?
|
||||
rf_lc_eq_1 <= '1' when register_file.lc = 1 else '0';
|
||||
|
||||
process(activate_exec_loop, instr_array, register_file, fetch_perform_enddo,
|
||||
rep_loop_polling, loop_iterations, rf_lc_eq_1, loop_start_address) is
|
||||
begin
|
||||
stall_rep <= '0';
|
||||
stall_do <= '0';
|
||||
|
||||
modify_la <= '0';
|
||||
modify_lc <= '0';
|
||||
modify_pc <= '0';
|
||||
modify_sr <= '0';
|
||||
modified_la <= loop_address;
|
||||
modified_lc <= loop_iterations; -- default
|
||||
-- set the loop flag LF (bit 15) of Status register
|
||||
modified_sr(15) <= '1';
|
||||
modified_sr(14 downto 0) <= register_file.sr(14 downto 0);
|
||||
|
||||
push_stack.valid <= '0'; -- push PC and SR on the stack
|
||||
push_stack.pc <= loop_start_address;
|
||||
push_stack.content <= LA_AND_LC;
|
||||
|
||||
pop_stack.valid <= '0';
|
||||
decrement_lc <= '0';
|
||||
------------------
|
||||
-- DO instruction
|
||||
------------------
|
||||
if activate_exec_loop = '1' and instr_array = INSTR_DO then
|
||||
-- first instruction of the do loop instruction?
|
||||
if do_loop_polling = '0' then
|
||||
stall_do <= '1';
|
||||
modify_lc <= '1'; -- store the new loop counter
|
||||
modify_la <= '1'; -- store the new loop address
|
||||
push_stack.valid <= '1'; -- push LA and LC on the stack
|
||||
push_stack.content <= LA_AND_LC;
|
||||
else -- second clock cycle of the do loop instruction ?
|
||||
push_stack.valid <= '1'; -- push PC and SR on the stack
|
||||
push_stack.pc <= loop_start_address;
|
||||
push_stack.content <= PC_AND_SR;
|
||||
-- set the PC to the first instruction of the loop
|
||||
-- the already fetched instruction are flushed from the pipeline
|
||||
-- this prevents problems, when the loop consists of only one or two instructions
|
||||
modify_pc <= '1';
|
||||
-- set the loop flag
|
||||
modify_sr <= '1';
|
||||
end if;
|
||||
end if;
|
||||
-----------------------------------------------
|
||||
-- ENDDO instruction / loop end in fetch stage
|
||||
-----------------------------------------------
|
||||
if (activate_exec_loop = '1' and instr_array = INSTR_ENDDO) or fetch_perform_enddo = '1' or enddo_polling = '1' then
|
||||
pop_stack.valid <= '1';
|
||||
if enddo_polling = '0' then
|
||||
-- only restore the LF from the stack
|
||||
modified_sr(15) <= register_file.current_ssl(15);
|
||||
modify_sr <= '1';
|
||||
stall_do <= '1'; -- stall one clock cycle
|
||||
else
|
||||
-- restore loop counter and loop address in second clock cycle
|
||||
modified_lc <= unsigned(register_file.current_ssl);
|
||||
modify_lc <= '1';
|
||||
modified_la <= unsigned(register_file.current_ssh);
|
||||
modify_la <= '1';
|
||||
end if;
|
||||
end if;
|
||||
-------------------
|
||||
-- REP instruction
|
||||
-------------------
|
||||
if activate_exec_loop = '1' and instr_array = INSTR_REP then
|
||||
-- only do something when there are more than 1 iterations
|
||||
-- the first execution is already on the way
|
||||
if loop_iterations /= 1 then
|
||||
stall_rep <= '1'; -- stall the fetch and decode stages
|
||||
modify_lc <= '1'; -- store the loop counter
|
||||
modified_lc <= loop_iterations - 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- keep processing the single instruction
|
||||
if rep_loop_polling = '1' then
|
||||
stall_rep <= '1';
|
||||
-- if the REP instruction cause a stall do not modify the lc!
|
||||
if memory_stall_t = '0' then
|
||||
if rf_lc_eq_1 = '0' then
|
||||
decrement_lc <= '1';
|
||||
-- when the instruction to repeat caused a memory stall
|
||||
-- do not continue!
|
||||
else
|
||||
-- finish the REP instruction by restoring the LC
|
||||
stall_rep <= '0';
|
||||
modify_lc <= '1';
|
||||
modified_lc <= lc_temp;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
-- process that allows to remember that we are processing a REP/DO instruction
|
||||
-- even though the REP instruction is not available in the pipeline anymore
|
||||
-- also store the old loop counter
|
||||
process(clk) is
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
rep_loop_polling <= '0';
|
||||
do_loop_polling <= '0';
|
||||
enddo_polling <= '0';
|
||||
lc_temp <= (others => '0');
|
||||
memory_stall_t <= '0';
|
||||
else
|
||||
memory_stall_t <= memory_stall;
|
||||
|
||||
if activate_exec_loop = '1' and instr_array = INSTR_REP then
|
||||
-- only do something when there are more than 1 iterations
|
||||
-- the first execution is already on the way
|
||||
if loop_iterations /= 1 then
|
||||
rep_loop_polling <= '1';
|
||||
lc_temp <= register_file.lc;
|
||||
end if;
|
||||
end if;
|
||||
-- test whether the REP instruction has been executed
|
||||
if rep_loop_polling = '1' and rf_lc_eq_1 = '1' and memory_stall_t = '0' then
|
||||
rep_loop_polling <= '0';
|
||||
end if;
|
||||
|
||||
-- do loop execution takes two clock cycles
|
||||
-- in the first clock cycle we store loop address and loop counter on the stack
|
||||
-- in the second clock cycle we store programm counter and status register on the stack
|
||||
if activate_exec_loop = '1' and instr_array = INSTR_DO then
|
||||
do_loop_polling <= '1';
|
||||
end if;
|
||||
-- clear the flag immediately again (only two cycles execution time!)
|
||||
if do_loop_polling = '1' then
|
||||
do_loop_polling <= '0';
|
||||
end if;
|
||||
|
||||
-- ENDDO instructions take two clock cycles as well!
|
||||
if (activate_exec_loop = '1' and instr_array = INSTR_ENDDO) or fetch_perform_enddo = '1' then
|
||||
enddo_polling <= '1';
|
||||
end if;
|
||||
if enddo_polling = '1' then
|
||||
enddo_polling <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
60
FPGA_Quartus_13.1/DSP/src/fetch_stage.vhd
Normal file
60
FPGA_Quartus_13.1/DSP/src/fetch_stage.vhd
Normal file
@@ -0,0 +1,60 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
|
||||
|
||||
entity fetch_stage is port(
|
||||
|
||||
pc_old : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
pc_new : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_pc : in std_logic;
|
||||
modified_pc : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
register_file : in register_file_type;
|
||||
decrement_lc : out std_logic;
|
||||
perform_enddo : out std_logic
|
||||
|
||||
);
|
||||
end fetch_stage;
|
||||
|
||||
|
||||
architecture rtl of fetch_stage is
|
||||
|
||||
|
||||
begin
|
||||
|
||||
pc_calculation: process(pc_old, modify_pc, modified_pc, register_file) is
|
||||
begin
|
||||
decrement_lc <= '0';
|
||||
perform_enddo <= '0';
|
||||
|
||||
-- by default increment pc by one
|
||||
pc_new <= pc_old + 1;
|
||||
if modify_pc = '1' then
|
||||
pc_new <= modified_pc;
|
||||
end if;
|
||||
-- Loop Flag set?
|
||||
if register_file.sr(15) = '1' then
|
||||
if register_file.la = pc_old then
|
||||
-- Loop not finished?
|
||||
-- => start from the beginning if necessary
|
||||
if register_file.lc /= 1 then
|
||||
-- if the last address was LA and the loop is not finished yet, we have to
|
||||
-- read now from the beginning of the loop again
|
||||
pc_new <= unsigned(register_file.current_ssh(BW_ADDRESS-1 downto 0));
|
||||
-- decrement loop counter
|
||||
decrement_lc <= '1';
|
||||
else
|
||||
-- loop done!
|
||||
-- => tell the loop controller in the exec stage to perform the enddo operation
|
||||
-- (without flushing of the pipeline!)
|
||||
perform_enddo <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process pc_calculation;
|
||||
|
||||
end architecture rtl;
|
||||
|
||||
1519
FPGA_Quartus_13.1/DSP/src/mem_control.vhd
Normal file
1519
FPGA_Quartus_13.1/DSP/src/mem_control.vhd
Normal file
File diff suppressed because it is too large
Load Diff
206
FPGA_Quartus_13.1/DSP/src/memory_management.vhd
Normal file
206
FPGA_Quartus_13.1/DSP/src/memory_management.vhd
Normal file
@@ -0,0 +1,206 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity memory_management is port (
|
||||
clk, rst : in std_logic;
|
||||
stall_flags : in std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
memory_stall : out std_logic;
|
||||
data_rom_enable: in std_logic;
|
||||
pmem_ctrl_in : in mem_ctrl_type_in;
|
||||
pmem_ctrl_out : out mem_ctrl_type_out;
|
||||
xmem_ctrl_in : in mem_ctrl_type_in;
|
||||
xmem_ctrl_out : out mem_ctrl_type_out;
|
||||
ymem_ctrl_in : in mem_ctrl_type_in;
|
||||
ymem_ctrl_out : out mem_ctrl_type_out
|
||||
);
|
||||
end memory_management;
|
||||
|
||||
|
||||
architecture rtl of memory_management is
|
||||
|
||||
|
||||
component mem_control is
|
||||
generic(
|
||||
mem_type : memory_type
|
||||
);
|
||||
port(
|
||||
clk, rst : in std_logic;
|
||||
rd_addr : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
rd_en : in std_logic;
|
||||
data_out : out std_logic_vector(23 downto 0);
|
||||
data_out_valid : out std_logic;
|
||||
wr_addr : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
wr_en : in std_logic;
|
||||
wr_accomplished : out std_logic;
|
||||
data_in : in std_logic_vector(23 downto 0)
|
||||
);
|
||||
end component mem_control;
|
||||
|
||||
signal pmem_data_out : std_logic_vector(23 downto 0);
|
||||
signal pmem_data_out_valid : std_logic;
|
||||
|
||||
signal pmem_rd_addr : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal pmem_rd_en : std_logic;
|
||||
|
||||
signal xmem_rd_en : std_logic;
|
||||
signal xmem_data_out : std_logic_vector(23 downto 0);
|
||||
signal xmem_data_out_valid : std_logic;
|
||||
signal xmem_rd_polling : std_logic;
|
||||
|
||||
signal ymem_rd_en : std_logic;
|
||||
signal ymem_data_out : std_logic_vector(23 downto 0);
|
||||
signal ymem_data_out_valid : std_logic;
|
||||
signal ymem_rd_polling : std_logic;
|
||||
|
||||
signal pmem_stall_buffer : std_logic_vector(23 downto 0);
|
||||
signal pmem_stall_buffer_valid : std_logic;
|
||||
signal xmem_stall_buffer : std_logic_vector(23 downto 0);
|
||||
signal ymem_stall_buffer : std_logic_vector(23 downto 0);
|
||||
|
||||
signal stall_flags_d : std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
-- here it is necessary to store the output of the pmem/xmem/ymem when the pipeline enters a stall
|
||||
-- when the pipeline wakes up, this temporal result is inserted into the pipeline
|
||||
stall_buffer: process(clk) is
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
pmem_stall_buffer <= (others => '0');
|
||||
pmem_stall_buffer_valid <= '0';
|
||||
xmem_stall_buffer <= (others => '0');
|
||||
ymem_stall_buffer <= (others => '0');
|
||||
stall_flags_d <= (others => '0');
|
||||
else
|
||||
stall_flags_d <= stall_flags;
|
||||
if stall_flags(ST_FETCH2) = '1' and stall_flags_d(ST_FETCH2) = '0' then
|
||||
if pmem_data_out_valid = '1' then
|
||||
pmem_stall_buffer <= pmem_data_out;
|
||||
pmem_stall_buffer_valid <= '1';
|
||||
end if;
|
||||
end if;
|
||||
if stall_flags(ST_FETCH2) = '0' and stall_flags_d(ST_FETCH2) = '1' then
|
||||
pmem_stall_buffer_valid <= '0';
|
||||
end if;
|
||||
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process stall_buffer;
|
||||
|
||||
memory_stall <= '1' when ( xmem_rd_en = '1' or (xmem_rd_polling = '1' and xmem_data_out_valid = '0') ) or
|
||||
( ymem_rd_en = '1' or (ymem_rd_polling = '1' and ymem_data_out_valid = '0') ) else
|
||||
'0';
|
||||
|
||||
-------------------------------
|
||||
-- PMEM CONTROLLER
|
||||
-------------------------------
|
||||
inst_pmem_ctrl : mem_control
|
||||
generic map(
|
||||
mem_type => P_MEM
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
rd_addr => pmem_ctrl_in.rd_addr,
|
||||
rd_en => pmem_ctrl_in.rd_en,
|
||||
data_out => pmem_data_out,
|
||||
data_out_valid => pmem_data_out_valid,
|
||||
wr_addr => pmem_ctrl_in.wr_addr,
|
||||
wr_en => pmem_ctrl_in.wr_en,
|
||||
data_in => pmem_ctrl_in.data_in
|
||||
);
|
||||
|
||||
-- In case we wake up from a stall use the buffered value
|
||||
pmem_ctrl_out.data_out <= pmem_stall_buffer when stall_flags(ST_FETCH2) = '0' and
|
||||
stall_flags_d(ST_FETCH2) = '1' and
|
||||
pmem_stall_buffer_valid = '1' else
|
||||
pmem_data_out;
|
||||
|
||||
pmem_ctrl_out.data_out_valid <= pmem_stall_buffer_valid when stall_flags(ST_FETCH2) = '0' and
|
||||
stall_flags_d(ST_FETCH2) = '1' else
|
||||
'0' when stall_flags(ST_FETCH2) = '1' else
|
||||
pmem_data_out_valid;
|
||||
|
||||
-------------------------------
|
||||
-- XMEM CONTROLLER
|
||||
-------------------------------
|
||||
inst_xmem_ctrl : mem_control
|
||||
generic map(
|
||||
mem_type => X_MEM
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
rd_addr => xmem_ctrl_in.rd_addr,
|
||||
rd_en => xmem_rd_en,
|
||||
data_out => xmem_data_out,
|
||||
data_out_valid => xmem_data_out_valid,
|
||||
wr_addr => xmem_ctrl_in.wr_addr,
|
||||
wr_en => xmem_ctrl_in.wr_en,
|
||||
data_in => xmem_ctrl_in.data_in
|
||||
);
|
||||
|
||||
xmem_rd_en <= '1' when xmem_rd_polling = '0' and xmem_ctrl_in.rd_en = '1' else '0';
|
||||
|
||||
xmem_ctrl_out.data_out <= xmem_data_out;
|
||||
xmem_ctrl_out.data_out_valid <= xmem_data_out_valid;
|
||||
|
||||
-------------------------------
|
||||
-- YMEM CONTROLLER
|
||||
-------------------------------
|
||||
inst_ymem_ctrl : mem_control
|
||||
generic map(
|
||||
mem_type => Y_MEM
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
rd_addr => ymem_ctrl_in.rd_addr,
|
||||
rd_en => ymem_rd_en,
|
||||
data_out => ymem_data_out,
|
||||
data_out_valid => ymem_data_out_valid,
|
||||
wr_addr => ymem_ctrl_in.wr_addr,
|
||||
wr_en => ymem_ctrl_in.wr_en,
|
||||
data_in => ymem_ctrl_in.data_in
|
||||
);
|
||||
|
||||
ymem_rd_en <= '1' when ymem_rd_polling = '0' and ymem_ctrl_in.rd_en = '1' else '0';
|
||||
|
||||
ymem_ctrl_out.data_out <= ymem_data_out;
|
||||
ymem_ctrl_out.data_out_valid <= ymem_data_out_valid;
|
||||
|
||||
mem_stall_control: process(clk) is
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
xmem_rd_polling <= '0';
|
||||
ymem_rd_polling <= '0';
|
||||
else
|
||||
if xmem_rd_en = '1' then
|
||||
xmem_rd_polling <= '1';
|
||||
end if;
|
||||
|
||||
if xmem_data_out_valid = '1' then
|
||||
xmem_rd_polling <= '0';
|
||||
end if;
|
||||
|
||||
if ymem_rd_en = '1' then
|
||||
ymem_rd_polling <= '1';
|
||||
end if;
|
||||
|
||||
if ymem_data_out_valid = '1' then
|
||||
ymem_rd_polling <= '0';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end architecture;
|
||||
|
||||
10
FPGA_Quartus_13.1/DSP/src/parameter_pkg.vhd
Normal file
10
FPGA_Quartus_13.1/DSP/src/parameter_pkg.vhd
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
package parameter_pkg is
|
||||
|
||||
constant BW_ADDRESS : natural := 16;
|
||||
|
||||
constant PIPELINE_DEPTH : natural := 5;
|
||||
|
||||
constant NUM_ACT_SIGNALS : natural := 26;
|
||||
|
||||
end package;
|
||||
968
FPGA_Quartus_13.1/DSP/src/pipeline.vhd
Normal file
968
FPGA_Quartus_13.1/DSP/src/pipeline.vhd
Normal file
@@ -0,0 +1,968 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity pipeline is port (
|
||||
clk, rst : in std_logic;
|
||||
register_file_out : out register_file_type
|
||||
|
||||
);
|
||||
end pipeline;
|
||||
|
||||
-- TODOs:
|
||||
-- External memory accesses
|
||||
-- ROM tables
|
||||
-- Reading from SSH flag has to modify stack pointer
|
||||
-- Memory access (x,y,p) and talling accordingly
|
||||
-- Address Generator: ring buffers are not yet supported
|
||||
|
||||
-- List of BUGS:
|
||||
-- - Reading from address one clock cycle after writing to the same address might result in corrupted data!!
|
||||
-- - SBC instruction has errorneous carry flag calculation
|
||||
|
||||
-- List of probable issues:
|
||||
-- - Reading from XMEM/YMEM with stalls probably results in corrupted data
|
||||
-- - ENDDO instruction probably has to flush the pipeline afterwards
|
||||
-- - Writing to memory occurs twice, when stalls occur
|
||||
|
||||
-- Things to optimize:
|
||||
-- - RTS/RTI could be executed in the ADGEN Stage already
|
||||
-- - DO loops always flush the pipeline. This is necessary in case we have a very short loop.
|
||||
-- The single instruction of the loop then has passed the fetch stage already without the branch
|
||||
|
||||
|
||||
architecture rtl of pipeline is
|
||||
|
||||
signal pipeline_regs : pipeline_type;
|
||||
signal stall_flags : std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
|
||||
component fetch_stage is port(
|
||||
pc_old : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
pc_new : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_pc : in std_logic;
|
||||
modified_pc : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
register_file : in register_file_type;
|
||||
decrement_lc : out std_logic;
|
||||
perform_enddo : out std_logic
|
||||
);
|
||||
end component fetch_stage;
|
||||
|
||||
signal pc_old, pc_new : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal fetch_modify_pc : std_logic;
|
||||
signal fetch_modified_pc : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal fetch_perform_enddo: std_logic;
|
||||
signal fetch_decrement_lc: std_logic;
|
||||
|
||||
|
||||
component decode_stage is port(
|
||||
activate_dec : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
dble_word_instr : out std_logic;
|
||||
instr_array : out instructions_type;
|
||||
act_array : out std_logic_vector(NUM_ACT_SIGNALS-1 downto 0);
|
||||
reg_wr_addr : out std_logic_vector(5 downto 0);
|
||||
reg_rd_addr : out std_logic_vector(5 downto 0);
|
||||
x_bus_rd_addr : out std_logic_vector(1 downto 0);
|
||||
x_bus_wr_addr : out std_logic_vector(1 downto 0);
|
||||
y_bus_rd_addr : out std_logic_vector(1 downto 0);
|
||||
y_bus_wr_addr : out std_logic_vector(1 downto 0);
|
||||
l_bus_addr : out std_logic_vector(2 downto 0);
|
||||
adgen_mode_a : out adgen_mode_type;
|
||||
adgen_mode_b : out adgen_mode_type;
|
||||
alu_ctrl : out alu_ctrl_type
|
||||
);
|
||||
end component decode_stage;
|
||||
|
||||
signal dec_activate : std_logic;
|
||||
signal dec_instr_word : std_logic_vector(23 downto 0);
|
||||
signal dec_dble_word_instr : std_logic;
|
||||
signal dec_instr_array : instructions_type;
|
||||
signal dec_act_array : std_logic_vector(NUM_ACT_SIGNALS-1 downto 0);
|
||||
signal dec_reg_wr_addr : std_logic_vector(5 downto 0);
|
||||
signal dec_reg_rd_addr : std_logic_vector(5 downto 0);
|
||||
signal dec_x_bus_wr_addr : std_logic_vector(1 downto 0);
|
||||
signal dec_x_bus_rd_addr : std_logic_vector(1 downto 0);
|
||||
signal dec_y_bus_wr_addr : std_logic_vector(1 downto 0);
|
||||
signal dec_y_bus_rd_addr : std_logic_vector(1 downto 0);
|
||||
signal dec_l_bus_addr : std_logic_vector(2 downto 0);
|
||||
signal dec_adgen_mode_a : adgen_mode_type;
|
||||
signal dec_adgen_mode_b : adgen_mode_type;
|
||||
signal dec_alu_ctrl : alu_ctrl_type;
|
||||
|
||||
component adgen_stage is port(
|
||||
activate_adgen : in std_logic;
|
||||
activate_x_mem : in std_logic;
|
||||
activate_y_mem : in std_logic;
|
||||
activate_l_mem : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
optional_ea_word : in std_logic_vector(23 downto 0);
|
||||
register_file : in register_file_type;
|
||||
adgen_mode_a : in adgen_mode_type;
|
||||
adgen_mode_b : in adgen_mode_type;
|
||||
address_out_x : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
address_out_y : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
wr_R_port_A_valid : out std_logic;
|
||||
wr_R_port_A : out addr_wr_port_type;
|
||||
wr_R_port_B_valid : out std_logic;
|
||||
wr_R_port_B : out addr_wr_port_type
|
||||
);
|
||||
end component adgen_stage;
|
||||
|
||||
signal adgen_activate : std_logic;
|
||||
signal adgen_activate_x_mem : std_logic;
|
||||
signal adgen_activate_y_mem : std_logic;
|
||||
signal adgen_activate_l_mem : std_logic;
|
||||
signal adgen_instr_word : std_logic_vector(23 downto 0);
|
||||
signal adgen_instr_array : instructions_type;
|
||||
signal adgen_optional_ea_word : std_logic_vector(23 downto 0);
|
||||
signal adgen_register_file : register_file_type;
|
||||
signal adgen_mode_a : adgen_mode_type;
|
||||
signal adgen_mode_b : adgen_mode_type;
|
||||
signal adgen_address_out_x : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal adgen_address_out_y : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal adgen_wr_R_port_A_valid : std_logic;
|
||||
signal adgen_wr_R_port_A : addr_wr_port_type;
|
||||
signal adgen_wr_R_port_B_valid : std_logic;
|
||||
signal adgen_wr_R_port_B : addr_wr_port_type;
|
||||
|
||||
component exec_stage_bit_modify is port(
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
src_operand : in std_logic_vector(23 downto 0);
|
||||
register_file : in register_file_type;
|
||||
dst_operand : out std_logic_vector(23 downto 0);
|
||||
bit_cond_met : out std_logic;
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end component exec_stage_bit_modify;
|
||||
|
||||
signal exec_bit_modify_instr_word : std_logic_vector(23 downto 0);
|
||||
signal exec_bit_modify_instr_array : instructions_type;
|
||||
signal exec_bit_modify_src_operand : std_logic_vector(23 downto 0);
|
||||
signal exec_bit_modify_dst_operand : std_logic_vector(23 downto 0);
|
||||
signal exec_bit_modify_bit_cond_met : std_logic;
|
||||
signal exec_bit_modify_modify_sr : std_logic;
|
||||
signal exec_bit_modify_modified_sr : std_logic_vector(15 downto 0);
|
||||
|
||||
component exec_stage_branch is port(
|
||||
activate_exec_bra : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
jump_address : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
bit_cond_met : in std_logic;
|
||||
cc_flag_set : in std_logic;
|
||||
push_stack : out push_stack_type;
|
||||
pop_stack : out pop_stack_type;
|
||||
modify_pc : out std_logic;
|
||||
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end component exec_stage_branch;
|
||||
|
||||
signal exec_bra_activate : std_logic;
|
||||
signal exec_bra_instr_word : std_logic_vector(23 downto 0);
|
||||
signal exec_bra_instr_array : instructions_type;
|
||||
signal exec_bra_jump_address : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal exec_bra_bit_cond_met : std_logic;
|
||||
signal exec_bra_push_stack : push_stack_type;
|
||||
signal exec_bra_pop_stack : pop_stack_type;
|
||||
signal exec_bra_modify_pc : std_logic;
|
||||
signal exec_bra_modified_pc : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal exec_bra_modify_sr : std_logic;
|
||||
signal exec_bra_modified_sr : std_logic_vector(15 downto 0);
|
||||
|
||||
component exec_stage_cr_mod is port(
|
||||
activate_exec_cr_mod : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0);
|
||||
modify_omr : out std_logic;
|
||||
modified_omr : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end component exec_stage_cr_mod;
|
||||
|
||||
signal exec_cr_mod_activate : std_logic;
|
||||
signal exec_cr_mod_instr_word : std_logic_vector(23 downto 0);
|
||||
signal exec_cr_mod_instr_array : instructions_type;
|
||||
signal exec_cr_mod_modify_sr : std_logic;
|
||||
signal exec_cr_mod_modified_sr : std_logic_vector(15 downto 0);
|
||||
signal exec_cr_mod_modify_omr : std_logic;
|
||||
signal exec_cr_mod_modified_omr : std_logic_vector(7 downto 0);
|
||||
|
||||
component exec_stage_loop is port(
|
||||
clk, rst : in std_logic;
|
||||
activate_exec_loop : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
loop_iterations : in unsigned(15 downto 0);
|
||||
loop_address : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
loop_start_address: in unsigned(BW_ADDRESS-1 downto 0);
|
||||
register_file : in register_file_type;
|
||||
fetch_perform_enddo: in std_logic;
|
||||
memory_stall : in std_logic;
|
||||
push_stack : out push_stack_type;
|
||||
pop_stack : out pop_stack_type;
|
||||
stall_rep : out std_logic;
|
||||
stall_do : out std_logic;
|
||||
decrement_lc : out std_logic;
|
||||
modify_lc : out std_logic;
|
||||
modified_lc : out unsigned(15 downto 0);
|
||||
modify_la : out std_logic;
|
||||
modified_la : out unsigned(15 downto 0);
|
||||
modify_pc : out std_logic;
|
||||
modified_pc : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end component exec_stage_loop;
|
||||
|
||||
signal exec_loop_activate : std_logic;
|
||||
signal exec_loop_instr_word : std_logic_vector(23 downto 0);
|
||||
signal exec_loop_instr_array : instructions_type;
|
||||
signal exec_loop_iterations : unsigned(15 downto 0);
|
||||
signal exec_loop_address : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal exec_loop_start_address : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal exec_loop_register_file : register_file_type;
|
||||
signal exec_loop_push_stack : push_stack_type;
|
||||
signal exec_loop_pop_stack : pop_stack_type;
|
||||
signal exec_loop_stall_rep : std_logic;
|
||||
signal exec_loop_stall_do : std_logic;
|
||||
signal exec_loop_decrement_lc : std_logic;
|
||||
signal exec_loop_modify_lc : std_logic;
|
||||
signal exec_loop_modified_lc : unsigned(15 downto 0);
|
||||
signal exec_loop_modify_la : std_logic;
|
||||
signal exec_loop_modified_la : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal exec_loop_modify_pc : std_logic;
|
||||
signal exec_loop_modified_pc : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal exec_loop_modify_sr : std_logic;
|
||||
signal exec_loop_modified_sr : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
|
||||
component exec_stage_alu is port(
|
||||
alu_activate : in std_logic;
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
alu_ctrl : in alu_ctrl_type;
|
||||
register_file : in register_file_type;
|
||||
addr_r_in : in unsigned(BW_ADDRESS-1 downto 0);
|
||||
addr_r_out : out unsigned(BW_ADDRESS-1 downto 0);
|
||||
modify_accu : out std_logic;
|
||||
dst_accu : out std_logic;
|
||||
modified_accu : out signed(55 downto 0);
|
||||
modify_sr : out std_logic;
|
||||
modified_sr : out std_logic_vector(15 downto 0)
|
||||
);
|
||||
end component exec_stage_alu;
|
||||
|
||||
signal exec_alu_activate : std_logic;
|
||||
signal exec_alu_instr_word : std_logic_vector(23 downto 0);
|
||||
signal exec_alu_ctrl : alu_ctrl_type;
|
||||
signal exec_alu_addr_r_in : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal exec_alu_addr_r_out : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal exec_alu_modify_accu : std_logic;
|
||||
signal exec_alu_dst_accu : std_logic;
|
||||
signal exec_alu_modified_accu : signed(55 downto 0);
|
||||
signal exec_alu_modify_sr : std_logic;
|
||||
signal exec_alu_modified_sr : std_logic_vector(15 downto 0);
|
||||
|
||||
signal exec_imm_8bit : std_logic_vector(23 downto 0);
|
||||
signal exec_imm_12bit : std_logic_vector(23 downto 0);
|
||||
signal exec_src_operand : std_logic_vector(23 downto 0);
|
||||
signal exec_dst_operand : std_logic_vector(23 downto 0);
|
||||
|
||||
component exec_stage_cc_flag_calc is port(
|
||||
instr_word : in std_logic_vector(23 downto 0);
|
||||
instr_array : in instructions_type;
|
||||
register_file : in register_file_type;
|
||||
cc_flag_set : out std_logic
|
||||
);
|
||||
end component exec_stage_cc_flag_calc;
|
||||
|
||||
signal exec_cc_flag_calc_instr_word : std_logic_vector(23 downto 0);
|
||||
signal exec_cc_flag_calc_instr_array : instructions_type;
|
||||
signal exec_cc_flag_set : std_logic;
|
||||
|
||||
component reg_file is port(
|
||||
clk, rst : in std_logic;
|
||||
register_file : out register_file_type;
|
||||
wr_R_port_A_valid : in std_logic;
|
||||
wr_R_port_A : in addr_wr_port_type;
|
||||
wr_R_port_B_valid : in std_logic;
|
||||
wr_R_port_B : in addr_wr_port_type;
|
||||
alu_wr_valid : in std_logic;
|
||||
alu_wr_addr : in std_logic;
|
||||
alu_wr_data : in signed(55 downto 0);
|
||||
reg_wr_addr : in std_logic_vector(5 downto 0);
|
||||
reg_wr_addr_valid : in std_logic;
|
||||
reg_wr_data : in std_Logic_vector(23 downto 0);
|
||||
reg_rd_addr : in std_logic_vector(5 downto 0);
|
||||
reg_rd_data : out std_Logic_vector(23 downto 0);
|
||||
X_bus_rd_addr : in std_logic_vector(1 downto 0);
|
||||
X_bus_data_out : out std_logic_vector(23 downto 0);
|
||||
X_bus_wr_addr : in std_logic_vector(1 downto 0);
|
||||
X_bus_wr_valid : in std_logic;
|
||||
X_bus_data_in : in std_logic_vector(23 downto 0);
|
||||
Y_bus_rd_addr : in std_logic_vector(1 downto 0);
|
||||
Y_bus_data_out : out std_logic_vector(23 downto 0);
|
||||
Y_bus_wr_addr : in std_logic_vector(1 downto 0);
|
||||
Y_bus_wr_valid : in std_logic;
|
||||
Y_bus_data_in : in std_logic_vector(23 downto 0);
|
||||
L_bus_rd_addr : in std_logic_vector(2 downto 0);
|
||||
L_bus_rd_valid : in std_logic;
|
||||
L_bus_wr_addr : in std_logic_vector(2 downto 0);
|
||||
L_bus_wr_valid : in std_logic;
|
||||
push_stack : in push_stack_type;
|
||||
pop_stack : in pop_stack_type;
|
||||
set_sr : in std_logic;
|
||||
new_sr : in std_logic_vector(15 downto 0);
|
||||
set_omr : in std_logic;
|
||||
new_omr : in std_logic_vector(7 downto 0);
|
||||
set_lc : in std_logic;
|
||||
new_lc : in unsigned(15 downto 0);
|
||||
dec_lc : in std_logic;
|
||||
set_la : in std_logic;
|
||||
new_la : in unsigned(BW_ADDRESS-1 downto 0)
|
||||
);
|
||||
end component reg_file;
|
||||
|
||||
signal register_file : register_file_type;
|
||||
signal rf_wr_R_port_A_valid : std_logic;
|
||||
signal rf_wr_R_port_B_valid : std_logic;
|
||||
signal rf_reg_wr_addr : std_logic_vector(5 downto 0);
|
||||
signal rf_reg_wr_addr_valid : std_logic;
|
||||
signal rf_reg_wr_data : std_logic_vector(23 downto 0);
|
||||
signal rf_reg_rd_addr : std_logic_vector(5 downto 0);
|
||||
signal rf_reg_rd_data : std_logic_vector(23 downto 0);
|
||||
signal rf_X_bus_rd_addr : std_logic_vector(1 downto 0);
|
||||
signal rf_X_bus_data_out : std_logic_vector(23 downto 0);
|
||||
signal rf_X_bus_wr_addr : std_logic_vector(1 downto 0);
|
||||
signal rf_X_bus_wr_valid : std_logic;
|
||||
signal rf_X_bus_data_in : std_logic_vector(23 downto 0);
|
||||
signal rf_Y_bus_rd_addr : std_logic_vector(1 downto 0);
|
||||
signal rf_Y_bus_data_out : std_logic_vector(23 downto 0);
|
||||
signal rf_Y_bus_wr_addr : std_logic_vector(1 downto 0);
|
||||
signal rf_Y_bus_wr_valid : std_logic;
|
||||
signal rf_Y_bus_data_in : std_logic_vector(23 downto 0);
|
||||
signal rf_L_bus_rd_addr : std_logic_vector(2 downto 0);
|
||||
signal rf_L_bus_rd_valid : std_logic;
|
||||
signal rf_L_bus_wr_addr : std_logic_vector(2 downto 0);
|
||||
signal rf_L_bus_wr_valid : std_logic;
|
||||
signal push_stack : push_stack_type;
|
||||
signal pop_stack : pop_stack_type;
|
||||
signal rf_set_sr : std_logic;
|
||||
signal rf_new_sr : std_logic_vector(15 downto 0);
|
||||
signal rf_set_omr : std_logic;
|
||||
signal rf_new_omr : std_logic_vector(7 downto 0);
|
||||
signal rf_dec_lc : std_logic;
|
||||
signal rf_set_lc : std_logic;
|
||||
signal rf_new_lc : unsigned(15 downto 0);
|
||||
signal rf_set_la : std_logic;
|
||||
signal rf_new_la : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal rf_alu_wr_valid : std_logic;
|
||||
|
||||
component memory_management is port (
|
||||
clk, rst : in std_logic;
|
||||
stall_flags : in std_logic_vector(PIPELINE_DEPTH-1 downto 0);
|
||||
memory_stall : out std_logic;
|
||||
data_rom_enable: in std_logic;
|
||||
pmem_ctrl_in : in mem_ctrl_type_in;
|
||||
pmem_ctrl_out : out mem_ctrl_type_out;
|
||||
xmem_ctrl_in : in mem_ctrl_type_in;
|
||||
xmem_ctrl_out : out mem_ctrl_type_out;
|
||||
ymem_ctrl_in : in mem_ctrl_type_in;
|
||||
ymem_ctrl_out : out mem_ctrl_type_out
|
||||
);
|
||||
end component memory_management;
|
||||
|
||||
signal memory_stall : std_logic;
|
||||
signal pmem_ctrl_in : mem_ctrl_type_in;
|
||||
signal pmem_ctrl_out : mem_ctrl_type_out;
|
||||
signal xmem_ctrl_in : mem_ctrl_type_in;
|
||||
signal xmem_ctrl_out : mem_ctrl_type_out;
|
||||
signal ymem_ctrl_in : mem_ctrl_type_in;
|
||||
signal ymem_ctrl_out : mem_ctrl_type_out;
|
||||
|
||||
signal pmem_data_out : std_logic_vector(23 downto 0);
|
||||
signal pmem_data_out_valid : std_logic;
|
||||
signal xmem_data_out : std_logic_vector(23 downto 0);
|
||||
signal xmem_data_out_valid : std_logic;
|
||||
signal ymem_data_out : std_logic_vector(23 downto 0);
|
||||
signal ymem_data_out_valid : std_logic;
|
||||
|
||||
begin
|
||||
register_file_out <= register_file;
|
||||
|
||||
-- merge all stall sources
|
||||
stall_flags(ST_FETCH) <= '1' when exec_loop_stall_rep = '1' or
|
||||
memory_stall = '1' or
|
||||
exec_loop_stall_do = '1' else '0';
|
||||
stall_flags(ST_FETCH2) <= '1' when exec_loop_stall_rep = '1' or
|
||||
memory_stall = '1' or
|
||||
exec_loop_stall_do = '1' else '0';
|
||||
stall_flags(ST_DECODE) <= '1' when exec_loop_stall_rep = '1' or
|
||||
memory_stall = '1' or
|
||||
exec_loop_stall_do = '1' else '0';
|
||||
stall_flags(ST_ADGEN) <= exec_loop_stall_do;
|
||||
-- stall_flags(ST_ADGEN) <= '1' when memory_stall = '1' or
|
||||
-- exec_loop_stall_do = '1' else '0';
|
||||
-- stall_flags(ST_EXEC) <= '0';
|
||||
stall_flags(ST_EXEC) <= exec_loop_stall_do;
|
||||
-- stall_flags(ST_EXEC) <= '1' when memory_stall = '1' or
|
||||
-- exec_loop_stall_do = '1' else '0';
|
||||
|
||||
shift_pipeline: process(clk, rst) is
|
||||
procedure flush_pipeline_stage(stage: natural) is
|
||||
begin
|
||||
pipeline_regs(stage).pc <= (others => '1');
|
||||
pipeline_regs(stage).instr_word <= (others => '0');
|
||||
pipeline_regs(stage).act_array <= (others => '0');
|
||||
pipeline_regs(stage).instr_array <= INSTR_NOP;
|
||||
pipeline_regs(stage).dble_word_instr <= '0';
|
||||
pipeline_regs(stage).dec_activate <= '0';
|
||||
pipeline_regs(stage).adgen_mode_a <= NOP;
|
||||
pipeline_regs(stage).adgen_mode_b <= NOP;
|
||||
pipeline_regs(stage).reg_wr_addr <= (others => '0');
|
||||
pipeline_regs(stage).reg_rd_addr <= (others => '0');
|
||||
pipeline_regs(stage).x_bus_rd_addr <= (others => '0');
|
||||
pipeline_regs(stage).x_bus_wr_addr <= (others => '0');
|
||||
pipeline_regs(stage).y_bus_rd_addr <= (others => '0');
|
||||
pipeline_regs(stage).y_bus_wr_addr <= (others => '0');
|
||||
pipeline_regs(stage).l_bus_addr <= (others => '0');
|
||||
pipeline_regs(stage).adgen_address_x <= (others => '0');
|
||||
pipeline_regs(stage).adgen_address_y <= (others => '0');
|
||||
pipeline_regs(stage).RAM_out_x <= (others => '0');
|
||||
pipeline_regs(stage).RAM_out_y <= (others => '0');
|
||||
pipeline_regs(stage).alu_ctrl.store_result <= '0';
|
||||
end procedure flush_pipeline_stage;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
for i in 0 to PIPELINE_DEPTH-1 loop
|
||||
flush_pipeline_stage(i);
|
||||
end loop;
|
||||
else
|
||||
-- shift the pipeline registers when no stall applies
|
||||
for i in 1 to PIPELINE_DEPTH-1 loop
|
||||
if stall_flags(i) = '0' then
|
||||
-- do not copy the pipeline registers from a stalled pipeline stage
|
||||
-- for REP we do not flush
|
||||
-- if stall_flags(i-1) = '1' then
|
||||
if (stall_flags(i-1) = '1' and exec_loop_stall_rep = '0') or
|
||||
(i = ST_ADGEN and memory_stall = '1' and exec_loop_stall_rep = '1') then
|
||||
flush_pipeline_stage(i);
|
||||
else
|
||||
pipeline_regs(i) <= pipeline_regs(i-1);
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
-- FETCH Pipeline Registers
|
||||
if stall_flags(ST_FETCH) = '0' then
|
||||
pipeline_regs(ST_FETCH).pc <= pc_new;
|
||||
pipeline_regs(ST_FETCH).dec_activate <= '1';
|
||||
end if;
|
||||
|
||||
-- FETCH2 Pipeline Registers
|
||||
if stall_flags(ST_FETCH2) = '0' then
|
||||
-- Normal pipeline operation?
|
||||
-- Buffering of RAM output when stalling is performed in the memory management
|
||||
if pmem_data_out_valid = '1' then
|
||||
pipeline_regs(ST_FETCH2).instr_word <= pmem_data_out;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- DECODE Pipeline registers
|
||||
if stall_flags(ST_DECODE) = '0' then
|
||||
pipeline_regs(ST_DECODE).act_array <= dec_act_array;
|
||||
pipeline_regs(ST_DECODE).instr_array <= dec_instr_array;
|
||||
pipeline_regs(ST_DECODE).dble_word_instr <= dec_dble_word_instr;
|
||||
pipeline_regs(ST_DECODE).reg_wr_addr <= dec_reg_wr_addr;
|
||||
pipeline_regs(ST_DECODE).reg_rd_addr <= dec_reg_rd_addr;
|
||||
pipeline_regs(ST_DECODE).x_bus_wr_addr <= dec_x_bus_wr_addr;
|
||||
pipeline_regs(ST_DECODE).x_bus_rd_addr <= dec_x_bus_rd_addr;
|
||||
pipeline_regs(ST_DECODE).y_bus_wr_addr <= dec_y_bus_wr_addr;
|
||||
pipeline_regs(ST_DECODE).y_bus_rd_addr <= dec_y_bus_rd_addr;
|
||||
pipeline_regs(ST_DECODE).l_bus_addr <= dec_l_bus_addr;
|
||||
pipeline_regs(ST_DECODE).adgen_mode_a <= dec_adgen_mode_a;
|
||||
pipeline_regs(ST_DECODE).adgen_mode_b <= dec_adgen_mode_b;
|
||||
pipeline_regs(ST_DECODE).alu_ctrl <= dec_alu_ctrl;
|
||||
end if;
|
||||
|
||||
-- ADGEN Pipeline registers
|
||||
if stall_flags(ST_ADGEN) = '0' then
|
||||
pipeline_regs(ST_ADGEN).adgen_address_x <= adgen_address_out_x;
|
||||
pipeline_regs(ST_ADGEN).adgen_address_y <= adgen_address_out_y;
|
||||
end if;
|
||||
if xmem_data_out_valid = '1' then
|
||||
pipeline_regs(ST_ADGEN).RAM_out_x <= xmem_data_out;
|
||||
end if;
|
||||
if ymem_data_out_valid = '1' then
|
||||
pipeline_regs(ST_ADGEN).RAM_out_y <= ymem_data_out;
|
||||
end if;
|
||||
|
||||
-- EXEC Pipeline stuff
|
||||
if exec_bra_modify_pc = '1' or exec_loop_modify_pc = '1' then
|
||||
-- clear the following pipeline stages,
|
||||
-- since we modified the pc.
|
||||
-- Do not flush ST_FETCH - it will hold the correct pc.
|
||||
flush_pipeline_stage(ST_FETCH2);
|
||||
flush_pipeline_stage(ST_DECODE);
|
||||
flush_pipeline_stage(ST_ADGEN);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process shift_pipeline;
|
||||
|
||||
-------------------------------
|
||||
-- FETCH STAGE INSTANTIATION
|
||||
-------------------------------
|
||||
inst_fetch_stage: fetch_stage port map(
|
||||
pc_old => pc_old,
|
||||
pc_new => pc_new,
|
||||
modify_pc => fetch_modify_pc,
|
||||
modified_pc => fetch_modified_pc,
|
||||
register_file => register_file,
|
||||
decrement_lc => fetch_decrement_lc,
|
||||
perform_enddo => fetch_perform_enddo
|
||||
);
|
||||
|
||||
pc_old <= pipeline_regs(ST_FETCH).pc;
|
||||
|
||||
fetch_modify_pc <= '1' when exec_bra_modify_pc = '1' or exec_loop_modify_pc = '1' else '0';
|
||||
fetch_modified_pc <= exec_bra_modified_pc when exec_bra_modify_pc = '1' else
|
||||
exec_loop_modified_pc;
|
||||
|
||||
-------------------------------
|
||||
-- DECODE STAGE INSTANTIATION
|
||||
-------------------------------
|
||||
inst_decode_stage : decode_stage port map(
|
||||
activate_dec => dec_activate,
|
||||
instr_word => dec_instr_word,
|
||||
dble_word_instr => dec_dble_word_instr,
|
||||
instr_array => dec_instr_array,
|
||||
act_array => dec_act_array,
|
||||
reg_wr_addr => dec_reg_wr_addr,
|
||||
reg_rd_addr => dec_reg_rd_addr,
|
||||
x_bus_wr_addr => dec_x_bus_wr_addr,
|
||||
x_bus_rd_addr => dec_x_bus_rd_addr,
|
||||
y_bus_wr_addr => dec_y_bus_wr_addr,
|
||||
y_bus_rd_addr => dec_y_bus_rd_addr,
|
||||
l_bus_addr => dec_l_bus_addr,
|
||||
adgen_mode_a => dec_adgen_mode_a,
|
||||
adgen_mode_b => dec_adgen_mode_b,
|
||||
alu_ctrl => dec_alu_ctrl
|
||||
);
|
||||
|
||||
dec_instr_word <= pipeline_regs(ST_DECODE-1).instr_word;
|
||||
-- do not decode, when we have no valid instruction. This can happen when
|
||||
-- 1) the pipeline just started its operation
|
||||
-- 2) the pipeline was flushed due to a jump
|
||||
-- 3) we are processing a instruction that consists of two words
|
||||
dec_activate <= '1' when pipeline_regs(ST_DECODE-1).dec_activate = '1' and pipeline_regs(ST_DECODE).dble_word_instr = '0' else '0';
|
||||
|
||||
-------------------------------
|
||||
-- AGU STAGE INSTANTIATION
|
||||
-------------------------------
|
||||
inst_adgen_stage: adgen_stage port map(
|
||||
activate_adgen => adgen_activate,
|
||||
activate_x_mem => adgen_activate_x_mem,
|
||||
activate_y_mem => adgen_activate_y_mem,
|
||||
activate_l_mem => adgen_activate_l_mem,
|
||||
instr_word => adgen_instr_word,
|
||||
instr_array => adgen_instr_array,
|
||||
optional_ea_word => adgen_optional_ea_word,
|
||||
register_file => register_file,
|
||||
adgen_mode_a => adgen_mode_a,
|
||||
adgen_mode_b => adgen_mode_b,
|
||||
address_out_x => adgen_address_out_x,
|
||||
address_out_y => adgen_address_out_y,
|
||||
wr_R_port_A_valid => adgen_wr_R_port_A_valid,
|
||||
wr_R_port_A => adgen_wr_R_port_A,
|
||||
wr_R_port_B_valid => adgen_wr_R_port_B_valid,
|
||||
wr_R_port_B => adgen_wr_R_port_B
|
||||
);
|
||||
|
||||
adgen_activate <= pipeline_regs(ST_ADGEN-1).act_array(ACT_ADGEN);
|
||||
adgen_activate_x_mem <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_X_MEM_RD) = '1' or
|
||||
pipeline_regs(ST_ADGEN-1).act_array(ACT_X_MEM_WR) = '1' else '0';
|
||||
adgen_activate_y_mem <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_Y_MEM_RD) = '1' or
|
||||
pipeline_regs(ST_ADGEN-1).act_array(ACT_Y_MEM_WR) = '1' else '0';
|
||||
adgen_activate_l_mem <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_L_BUS_RD) = '1' or
|
||||
pipeline_regs(ST_ADGEN-1).act_array(ACT_L_BUS_WR) = '1' else '0';
|
||||
adgen_instr_word <= pipeline_regs(ST_ADGEN-1).instr_word;
|
||||
adgen_instr_array <= pipeline_regs(ST_ADGEN-1).instr_array;
|
||||
adgen_optional_ea_word <= pipeline_regs(ST_ADGEN-2).instr_word;
|
||||
adgen_mode_a <= pipeline_regs(ST_ADGEN-1).adgen_mode_a;
|
||||
adgen_mode_b <= pipeline_regs(ST_ADGEN-1).adgen_mode_b;
|
||||
|
||||
-------------------------------
|
||||
-- EXECUTE STAGE INSTANTIATIONS
|
||||
-------------------------------
|
||||
inst_exec_stage_alu: exec_stage_alu port map(
|
||||
alu_activate => exec_alu_activate,
|
||||
instr_word => exec_alu_instr_word,
|
||||
alu_ctrl => exec_alu_ctrl,
|
||||
register_file => register_file,
|
||||
addr_r_in => exec_alu_addr_r_in,
|
||||
addr_r_out => exec_alu_addr_r_out,
|
||||
modify_accu => exec_alu_modify_accu,
|
||||
dst_accu => exec_alu_dst_accu,
|
||||
modified_accu => exec_alu_modified_accu,
|
||||
modify_sr => exec_alu_modify_sr,
|
||||
modified_sr => exec_alu_modified_sr
|
||||
);
|
||||
|
||||
exec_alu_activate <= pipeline_regs(ST_EXEC-1).act_array(ACT_ALU);
|
||||
exec_alu_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
|
||||
exec_alu_ctrl <= pipeline_regs(ST_EXEC-1).alu_ctrl;
|
||||
|
||||
exec_alu_addr_r_in <= unsigned(rf_reg_rd_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
inst_exec_stage_bit_modify: exec_stage_bit_modify port map(
|
||||
instr_word => exec_bit_modify_instr_word,
|
||||
instr_array => exec_bit_modify_instr_array,
|
||||
src_operand => exec_bit_modify_src_operand,
|
||||
register_file => register_file,
|
||||
dst_operand => exec_bit_modify_dst_operand,
|
||||
bit_cond_met => exec_bit_modify_bit_cond_met,
|
||||
modify_sr => exec_bit_modify_modify_sr,
|
||||
modified_sr => exec_bit_modify_modified_sr
|
||||
);
|
||||
|
||||
exec_bit_modify_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
|
||||
exec_bit_modify_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
|
||||
exec_bit_modify_src_operand <= exec_src_operand;
|
||||
|
||||
-- Writing to the register file using the 6 bit addressing scheme
|
||||
-- sources are:
|
||||
-- 1) X-RAM output
|
||||
-- 2) Y-RAM output
|
||||
-- 3) register file itself
|
||||
-- 4) short immediate value (8 bit stored in instruction word)
|
||||
-- 5) long immediate value (from optional effective address extension)
|
||||
-- 5) address generated by the address generation unit (LUA instr)
|
||||
exec_src_operand <= pipeline_regs(ST_EXEC-1).RAM_out_x when pipeline_regs(ST_EXEC-1).act_array(ACT_X_MEM_RD) = '1' else
|
||||
pipeline_regs(ST_EXEC-1).RAM_out_y when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_MEM_RD) = '1' else
|
||||
rf_reg_rd_data when pipeline_regs(ST_EXEC-1).act_array(ACT_REG_RD) = '1' else
|
||||
exec_imm_8bit when pipeline_regs(ST_EXEC-1).act_array(ACT_IMM_8BIT) = '1' else
|
||||
exec_imm_12bit when pipeline_regs(ST_EXEC-1).act_array(ACT_IMM_12BIT) = '1' else
|
||||
pipeline_regs(ST_EXEC-2).instr_word when pipeline_regs(ST_EXEC-1).act_array(ACT_IMM_LONG) = '1' else
|
||||
std_logic_vector(resize(pipeline_regs(ST_EXEC-1).adgen_address_x, 24)); -- for LUA instr.
|
||||
|
||||
-- Destination for the register file using the 6 bit addressing scheme.
|
||||
-- Either read the bit modified version of the read value
|
||||
-- or use the modified Rn in case of a NORM instruction
|
||||
-- exec_dst_operand <= exec_bit_modify_dst_operand;
|
||||
exec_dst_operand <= exec_bit_modify_dst_operand when pipeline_regs(ST_EXEC-1).act_array(ACT_NORM) = '0' else
|
||||
std_logic_vector(resize(exec_alu_addr_r_out,24));
|
||||
|
||||
-- Unit to check whether cc (in Jcc, JScc, Tcc, ...) is true
|
||||
inst_exec_stage_cc_flag_calc: exec_stage_cc_flag_calc port map(
|
||||
instr_word => exec_cc_flag_calc_instr_word,
|
||||
instr_array => exec_cc_flag_calc_instr_array,
|
||||
register_file => register_file,
|
||||
cc_flag_set => exec_cc_flag_set
|
||||
);
|
||||
|
||||
exec_cc_flag_calc_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
|
||||
exec_cc_flag_calc_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
|
||||
|
||||
|
||||
inst_exec_stage_branch : exec_stage_branch port map(
|
||||
activate_exec_bra => exec_bra_activate,
|
||||
instr_word => exec_bra_instr_word,
|
||||
instr_array => exec_bra_instr_array,
|
||||
register_file => register_file,
|
||||
jump_address => exec_bra_jump_address,
|
||||
bit_cond_met => exec_bra_bit_cond_met,
|
||||
cc_flag_set => exec_cc_flag_set,
|
||||
push_stack => exec_bra_push_stack,
|
||||
pop_stack => exec_bra_pop_stack,
|
||||
modify_pc => exec_bra_modify_pc,
|
||||
modified_pc => exec_bra_modified_pc,
|
||||
modify_sr => exec_bra_modify_sr,
|
||||
modified_sr => exec_bra_modified_sr
|
||||
);
|
||||
|
||||
exec_bra_activate <= pipeline_regs(ST_EXEC-1).act_array(ACT_EXEC_BRA);
|
||||
exec_bra_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
|
||||
exec_bra_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
|
||||
exec_bra_jump_address <= pipeline_regs(ST_EXEC-1).adgen_address_x when pipeline_regs(ST_EXEC-1).dble_word_instr = '0' else
|
||||
unsigned(pipeline_regs(ST_EXEC-2).instr_word(BW_ADDRESS-1 downto 0));
|
||||
exec_bra_bit_cond_met <= exec_bit_modify_bit_cond_met;
|
||||
|
||||
inst_exec_stage_cr_mod : exec_stage_cr_mod port map(
|
||||
activate_exec_cr_mod => exec_cr_mod_activate,
|
||||
instr_word => exec_cr_mod_instr_word,
|
||||
instr_array => exec_cr_mod_instr_array,
|
||||
register_file => register_file,
|
||||
modify_sr => exec_cr_mod_modify_sr,
|
||||
modified_sr => exec_cr_mod_modified_sr,
|
||||
modify_omr => exec_cr_mod_modify_omr,
|
||||
modified_omr => exec_cr_mod_modified_omr
|
||||
);
|
||||
|
||||
exec_cr_mod_activate <= pipeline_regs(ST_EXEC-1).act_array(ACT_EXEC_CR_MOD);
|
||||
exec_cr_mod_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
|
||||
exec_cr_mod_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
|
||||
|
||||
inst_exec_stage_loop: exec_stage_loop port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
activate_exec_loop => exec_loop_activate,
|
||||
instr_word => exec_loop_instr_word,
|
||||
instr_array => exec_loop_instr_array,
|
||||
loop_iterations => exec_loop_iterations,
|
||||
loop_address => exec_loop_address,
|
||||
loop_start_address => exec_loop_start_address,
|
||||
register_file => register_file,
|
||||
fetch_perform_enddo=> fetch_perform_enddo,
|
||||
memory_stall => memory_stall,
|
||||
push_stack => exec_loop_push_stack,
|
||||
pop_stack => exec_loop_pop_stack,
|
||||
stall_rep => exec_loop_stall_rep,
|
||||
stall_do => exec_loop_stall_do,
|
||||
modify_lc => exec_loop_modify_lc,
|
||||
decrement_lc => exec_loop_decrement_lc,
|
||||
modified_lc => exec_loop_modified_lc,
|
||||
modify_la => exec_loop_modify_la,
|
||||
modified_la => exec_loop_modified_la,
|
||||
modify_pc => exec_loop_modify_pc,
|
||||
modified_pc => exec_loop_modified_pc,
|
||||
modify_sr => exec_loop_modify_sr,
|
||||
modified_sr => exec_loop_modified_sr
|
||||
);
|
||||
|
||||
exec_loop_activate <= pipeline_regs(ST_EXEC-1).act_array(ACT_EXEC_LOOP);
|
||||
exec_loop_instr_word <= pipeline_regs(ST_EXEC-1).instr_word;
|
||||
exec_loop_instr_array <= pipeline_regs(ST_EXEC-1).instr_array;
|
||||
exec_loop_iterations <= unsigned(exec_src_operand(15 downto 0));
|
||||
-- from which source is our operand?
|
||||
-- - XMEM
|
||||
-- - YMEM
|
||||
-- - Any register
|
||||
-- - Immediate (from instruction word)
|
||||
-- exec_src_operand <= unsigned(pipeline_regs(ST_EXEC-1).RAM_out_x(BW_ADDRESS-1 downto 0)) when
|
||||
-- pipeline_regs(ST_EXEC-1).act_array(ACT_X_MEM_RD) = '1' else
|
||||
-- unsigned(pipeline_regs(ST_EXEC-1).RAM_out_y(BW_ADDRESS-1 downto 0)) when
|
||||
-- pipeline_regs(ST_EXEC-1).act_array(ACT_Y_MEM_RD) = '1' else
|
||||
-- unsigned(rf_reg_rd_data(15 downto 0)) when
|
||||
-- pipeline_regs(ST_EXEC-1).act_array(ACT_REG_RD) = '1' else
|
||||
-- "00000000" & unsigned(pipeline_regs(ST_EXEC-1).instr_word(15 downto 8));
|
||||
|
||||
-- Loop address is given by the second instruction word of the DO instruction.
|
||||
-- This address is available one previous stage within the pipeline
|
||||
exec_loop_address <= unsigned(pipeline_regs(ST_EXEC-2).instr_word(BW_ADDRESS-1 downto 0)) - 1;
|
||||
-- one more stage before we find the programm counter of the first instruction to be executed in a DO loop
|
||||
exec_loop_start_address <= unsigned(pipeline_regs(ST_EXEC-3).pc);
|
||||
|
||||
-- For the 8 bit immediate is can be either a fractional (registers x0,x1,y0,y1,a,b) or an unsigned (the rest)
|
||||
exec_imm_8bit(23 downto 16) <= (others => '0') when rf_reg_wr_addr(5 downto 2) /= "0001" and rf_reg_wr_addr(5 downto 1) /= "00111" else
|
||||
pipeline_regs(ST_EXEC-1).instr_word(15 downto 8);
|
||||
exec_imm_8bit(15 downto 8) <= (others => '0');
|
||||
exec_imm_8bit( 7 downto 0) <= (others => '0') when rf_reg_wr_addr(5 downto 2) = "0001" or rf_reg_wr_addr(5 downto 1) = "00111" else
|
||||
pipeline_regs(ST_EXEC-1).instr_word(15 downto 8);
|
||||
-- The 12 bit immediate stems from the instruction word
|
||||
exec_imm_12bit(23 downto 12) <= (others => '0');
|
||||
exec_imm_12bit(11 downto 0) <= pipeline_regs(ST_EXEC-1).instr_word(3 downto 0) & pipeline_regs(ST_EXEC-1).instr_word(15 downto 8);
|
||||
-----------------
|
||||
-- REGISTER FILE
|
||||
-----------------
|
||||
inst_reg_file: reg_file port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
register_file => register_file,
|
||||
wr_R_port_A_valid => rf_wr_R_port_A_valid,
|
||||
wr_R_port_A => adgen_wr_R_port_A,
|
||||
wr_R_port_B_valid => rf_wr_R_port_B_valid,
|
||||
wr_R_port_B => adgen_wr_R_port_B,
|
||||
reg_wr_addr => rf_reg_wr_addr,
|
||||
reg_wr_addr_valid => rf_reg_wr_addr_valid,
|
||||
reg_wr_data => rf_reg_wr_data,
|
||||
reg_rd_addr => rf_reg_rd_addr,
|
||||
reg_rd_data => rf_reg_rd_data,
|
||||
alu_wr_valid => rf_alu_wr_valid,
|
||||
alu_wr_addr => exec_alu_dst_accu,
|
||||
alu_wr_data => exec_alu_modified_accu,
|
||||
X_bus_rd_addr => rf_X_bus_rd_addr,
|
||||
X_bus_data_out => rf_X_bus_data_out,
|
||||
X_bus_wr_addr => rf_X_bus_wr_addr ,
|
||||
X_bus_wr_valid => rf_X_bus_wr_valid,
|
||||
X_bus_data_in => rf_X_bus_data_in ,
|
||||
Y_bus_rd_addr => rf_Y_bus_rd_addr ,
|
||||
Y_bus_data_out => rf_Y_bus_data_out,
|
||||
Y_bus_wr_addr => rf_Y_bus_wr_addr ,
|
||||
Y_bus_wr_valid => rf_Y_bus_wr_valid,
|
||||
Y_bus_data_in => rf_Y_bus_data_in ,
|
||||
L_bus_rd_addr => rf_L_bus_rd_addr ,
|
||||
L_bus_rd_valid => rf_L_bus_rd_valid,
|
||||
L_bus_wr_addr => rf_L_bus_wr_addr ,
|
||||
L_bus_wr_valid => rf_L_bus_wr_valid,
|
||||
push_stack => push_stack,
|
||||
pop_stack => pop_stack,
|
||||
set_sr => rf_set_sr,
|
||||
new_sr => rf_new_sr,
|
||||
set_omr => rf_set_omr,
|
||||
new_omr => rf_new_omr,
|
||||
set_la => rf_set_la,
|
||||
new_la => rf_new_la,
|
||||
dec_lc => rf_dec_lc,
|
||||
set_lc => rf_set_lc,
|
||||
new_lc => rf_new_lc
|
||||
);
|
||||
|
||||
-----------------
|
||||
-- BUSES (X,Y,L)
|
||||
-----------------
|
||||
rf_X_bus_wr_valid <= pipeline_regs(ST_EXEC-1).act_array(ACT_X_BUS_WR);
|
||||
rf_X_bus_wr_addr <= pipeline_regs(ST_EXEC-1).x_bus_wr_addr;
|
||||
rf_X_bus_rd_addr <= pipeline_regs(ST_EXEC-1).x_bus_rd_addr;
|
||||
rf_X_bus_data_in <= rf_X_bus_data_out when pipeline_regs(ST_EXEC-1).act_array(ACT_X_BUS_RD) = '1' else
|
||||
pipeline_regs(ST_EXEC-1).RAM_out_x; -- when pipeline_regs(ST_EXEC-1).act_array(ACT_X_MEM_RD) = '1' else
|
||||
|
||||
rf_Y_bus_wr_valid <= pipeline_regs(ST_EXEC-1).act_array(ACT_Y_BUS_WR);
|
||||
rf_Y_bus_wr_addr <= pipeline_regs(ST_EXEC-1).y_bus_wr_addr;
|
||||
rf_Y_bus_rd_addr <= pipeline_regs(ST_EXEC-1).y_bus_rd_addr;
|
||||
rf_Y_bus_data_in <= rf_Y_bus_data_out when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_BUS_RD) = '1' else
|
||||
pipeline_regs(ST_EXEC-1).RAM_out_y; -- when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_MEM_RD) = '1' else
|
||||
|
||||
rf_L_bus_wr_valid <= pipeline_regs(ST_EXEC-1).act_array(ACT_L_BUS_WR);
|
||||
rf_L_bus_rd_valid <= pipeline_regs(ST_EXEC-1).act_array(ACT_L_BUS_RD);
|
||||
rf_L_bus_wr_addr <= pipeline_regs(ST_EXEC-1).l_bus_addr; -- equal to bits in instruction word
|
||||
rf_L_bus_rd_addr <= pipeline_regs(ST_EXEC-1).l_bus_addr; -- could be simplified by taking these bits..
|
||||
|
||||
-- writing to the R registers within the ADGEN stage has to be prevented when
|
||||
-- 1) a jump is currently being executed (which is detected in the exec stage)
|
||||
-- 2) stall cycles occur. In this case the write will happen in the last cycle, when we stop stalling.
|
||||
-- 3) a memory access results in a stall (e.g. caused by the instruction to REP)
|
||||
rf_wr_R_port_A_valid <= '0' when stall_flags(ST_ADGEN) = '1' or
|
||||
exec_bra_modify_pc = '1' or
|
||||
memory_stall = '1' else
|
||||
adgen_wr_R_port_A_valid;
|
||||
rf_wr_R_port_B_valid <= '0' when stall_flags(ST_ADGEN) = '1' or
|
||||
exec_bra_modify_pc = '1' or
|
||||
memory_stall = '1' else
|
||||
adgen_wr_R_port_B_valid;
|
||||
|
||||
|
||||
rf_reg_wr_addr <= pipeline_regs(ST_EXEC-1).reg_wr_addr;
|
||||
-- can be set due to
|
||||
-- 1) normal write operation (e.g., move)
|
||||
-- 2) conditional move (Tcc)
|
||||
rf_reg_wr_addr_valid <= '1' when pipeline_regs(ST_EXEC-1).act_array(ACT_REG_WR) = '1' else
|
||||
exec_cc_flag_set when pipeline_regs(ST_EXEC-1).act_array(ACT_REG_WR_CC) = '1' else '0';
|
||||
rf_reg_wr_data <= exec_dst_operand;
|
||||
|
||||
rf_reg_rd_addr <= pipeline_regs(ST_EXEC-1).reg_rd_addr;
|
||||
|
||||
-- Writing from the ALU can depend on the condition code (Tcc) instruction
|
||||
rf_alu_wr_valid <= exec_cc_flag_set when pipeline_regs(ST_EXEC-1).act_array(ACT_ALU_WR_CC) = '1' else
|
||||
exec_alu_modify_accu;
|
||||
|
||||
push_stack.valid <= '1' when exec_bra_push_stack.valid = '1' or exec_loop_push_stack.valid = '1' else '0';
|
||||
push_stack.content <= exec_bra_push_stack.content when exec_bra_push_stack.valid = '1' else
|
||||
exec_loop_push_stack.content;
|
||||
-- for jump to subroutine store the pc of the subsequent instruction
|
||||
push_stack.pc <= pipeline_regs(ST_EXEC-2).pc when exec_bra_push_stack.valid = '1' and pipeline_regs(ST_EXEC-1).dble_word_instr = '0' else
|
||||
pipeline_regs(ST_EXEC-3).pc when exec_bra_push_stack.valid = '1' and pipeline_regs(ST_EXEC-1).dble_word_instr = '1' else
|
||||
exec_loop_push_stack.pc when exec_loop_push_stack.valid = '1' else
|
||||
(others => '0');
|
||||
|
||||
pop_stack.valid <= '1' when exec_bra_pop_stack.valid = '1' or exec_loop_pop_stack.valid = '1' else '0';
|
||||
|
||||
rf_set_sr <= '1' when exec_bra_modify_sr = '1' or
|
||||
exec_cr_mod_modify_sr = '1' or
|
||||
exec_loop_modify_sr = '1' or
|
||||
exec_alu_modify_sr = '1' or
|
||||
exec_bit_modify_modify_sr = '1' else '0';
|
||||
rf_new_sr <= exec_bra_modified_sr when exec_bra_modify_sr = '1' else
|
||||
exec_cr_mod_modified_sr when exec_cr_mod_modify_sr = '1' else
|
||||
exec_loop_modified_sr when exec_loop_modify_sr = '1' else
|
||||
exec_alu_modified_sr when exec_alu_modify_sr = '1' else
|
||||
exec_bit_modify_modified_sr; -- when exec_bit_modify_modify_sr = '1' else
|
||||
|
||||
rf_set_omr <= exec_cr_mod_modify_omr;
|
||||
rf_new_omr <= exec_cr_mod_modified_omr;
|
||||
rf_set_lc <= exec_loop_modify_lc;
|
||||
rf_new_lc <= exec_loop_modified_lc;
|
||||
rf_set_la <= exec_loop_modify_la;
|
||||
rf_new_la <= exec_loop_modified_la;
|
||||
|
||||
rf_dec_lc <= '1' when exec_loop_decrement_lc = '1' or fetch_decrement_lc = '1' else '0';
|
||||
|
||||
---------------------
|
||||
-- MEMORY MANAGEMENT
|
||||
---------------------
|
||||
MMU_inst: memory_management port map (
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
stall_flags => stall_flags,
|
||||
memory_stall => memory_stall,
|
||||
data_rom_enable => register_file.omr(2),
|
||||
pmem_ctrl_in => pmem_ctrl_in,
|
||||
pmem_ctrl_out => pmem_ctrl_out,
|
||||
xmem_ctrl_in => xmem_ctrl_in,
|
||||
xmem_ctrl_out => xmem_ctrl_out,
|
||||
ymem_ctrl_in => ymem_ctrl_in,
|
||||
ymem_ctrl_out => ymem_ctrl_out
|
||||
);
|
||||
|
||||
------------------
|
||||
-- Program Memory
|
||||
------------------
|
||||
pmem_ctrl_in.rd_addr <= pc_new;
|
||||
pmem_ctrl_in.rd_en <= '1' when stall_flags(ST_FETCH) = '0' else '0';
|
||||
-- TODO: Writing to PMEM!
|
||||
pmem_ctrl_in.wr_addr <= (others => '0');
|
||||
pmem_ctrl_in.wr_en <= '0';
|
||||
pmem_ctrl_in.data_in <= (others => '0');
|
||||
|
||||
pmem_data_out <= pmem_ctrl_out.data_out;
|
||||
pmem_data_out_valid <= pmem_ctrl_out.data_out_valid;
|
||||
|
||||
|
||||
------------------
|
||||
-- X Memory
|
||||
------------------
|
||||
-- Either take the result of the AGU or use the short absolute value stored in the instruction word
|
||||
xmem_ctrl_in.rd_addr <= adgen_address_out_x when pipeline_regs(ST_ADGEN-1).act_array(ACT_ADGEN) = '1' else
|
||||
"0000000000" & unsigned(pipeline_regs(ST_ADGEN-1).instr_word(13 downto 8));
|
||||
xmem_ctrl_in.rd_en <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_X_MEM_RD) = '1' else '0';
|
||||
-- Either take the result of the AGU or use the absolute value stored in the instruction word
|
||||
xmem_ctrl_in.wr_addr <= pipeline_regs(ST_EXEC-1).adgen_address_x when pipeline_regs(ST_EXEC-1).act_array(ACT_ADGEN) = '1' else
|
||||
"0000000000" & unsigned(pipeline_regs(ST_EXEC-1).instr_word(13 downto 8));
|
||||
xmem_ctrl_in.wr_en <= '1' when pipeline_regs(ST_EXEC-1).act_array(ACT_X_MEM_WR) = '1' else '0';
|
||||
xmem_ctrl_in.data_in <= rf_X_bus_data_out when pipeline_regs(ST_EXEC-1).act_array(ACT_X_BUS_RD) = '1' or
|
||||
pipeline_regs(ST_EXEC-1).act_array(ACT_L_BUS_RD) = '1' else
|
||||
exec_dst_operand;
|
||||
|
||||
xmem_data_out <= xmem_ctrl_out.data_out;
|
||||
xmem_data_out_valid <= xmem_ctrl_out.data_out_valid;
|
||||
|
||||
------------------
|
||||
-- Y Memory
|
||||
------------------
|
||||
-- Either take the result of the AGU or use the absolute value stored in the instruction word
|
||||
ymem_ctrl_in.rd_addr <= adgen_address_out_y when pipeline_regs(ST_ADGEN-1).act_array(ACT_ADGEN) = '1' else
|
||||
"0000000000" & unsigned(pipeline_regs(ST_ADGEN-1).instr_word(13 downto 8));
|
||||
ymem_ctrl_in.rd_en <= '1' when pipeline_regs(ST_ADGEN-1).act_array(ACT_Y_MEM_RD) = '1' else '0';
|
||||
-- Either take the result of the AGU or use the absolute value stored in the instruction word
|
||||
ymem_ctrl_in.wr_addr <= pipeline_regs(ST_EXEC-1).adgen_address_y when pipeline_regs(ST_EXEC-1).act_array(ACT_ADGEN) = '1' else
|
||||
"0000000000" & unsigned(pipeline_regs(ST_EXEC-1).instr_word(13 downto 8));
|
||||
ymem_ctrl_in.wr_en <= '1' when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_MEM_WR) = '1' else '0';
|
||||
ymem_ctrl_in.data_in <= rf_Y_bus_data_out when pipeline_regs(ST_EXEC-1).act_array(ACT_Y_BUS_RD) = '1' or
|
||||
pipeline_regs(ST_EXEC-1).act_array(ACT_L_BUS_RD) = '1' else
|
||||
exec_dst_operand;
|
||||
|
||||
ymem_data_out <= ymem_ctrl_out.data_out;
|
||||
ymem_data_out_valid <= ymem_ctrl_out.data_out_valid;
|
||||
|
||||
|
||||
end architecture rtl;
|
||||
679
FPGA_Quartus_13.1/DSP/src/reg_file.vhd
Normal file
679
FPGA_Quartus_13.1/DSP/src/reg_file.vhd
Normal file
@@ -0,0 +1,679 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
use work.types_pkg.all;
|
||||
use work.constants_pkg.all;
|
||||
|
||||
entity reg_file is port(
|
||||
clk, rst : in std_logic;
|
||||
register_file : out register_file_type;
|
||||
wr_R_port_A_valid : in std_logic;
|
||||
wr_R_port_A : in addr_wr_port_type;
|
||||
wr_R_port_B_valid : in std_logic;
|
||||
wr_R_port_B : in addr_wr_port_type;
|
||||
alu_wr_valid : in std_logic;
|
||||
alu_wr_addr : in std_logic;
|
||||
alu_wr_data : in signed(55 downto 0);
|
||||
reg_wr_addr : in std_logic_vector(5 downto 0);
|
||||
reg_wr_addr_valid : in std_logic;
|
||||
reg_wr_data : in std_Logic_vector(23 downto 0);
|
||||
reg_rd_addr : in std_logic_vector(5 downto 0);
|
||||
reg_rd_data : out std_Logic_vector(23 downto 0);
|
||||
X_bus_rd_addr : in std_logic_vector(1 downto 0);
|
||||
X_bus_data_out : out std_logic_vector(23 downto 0);
|
||||
X_bus_wr_addr : in std_logic_vector(1 downto 0);
|
||||
X_bus_wr_valid : in std_logic;
|
||||
X_bus_data_in : in std_logic_vector(23 downto 0);
|
||||
Y_bus_rd_addr : in std_logic_vector(1 downto 0);
|
||||
Y_bus_data_out : out std_logic_vector(23 downto 0);
|
||||
Y_bus_wr_addr : in std_logic_vector(1 downto 0);
|
||||
Y_bus_wr_valid : in std_logic;
|
||||
Y_bus_data_in : in std_logic_vector(23 downto 0);
|
||||
L_bus_rd_addr : in std_logic_vector(2 downto 0);
|
||||
L_bus_rd_valid : in std_logic;
|
||||
L_bus_wr_addr : in std_logic_vector(2 downto 0);
|
||||
L_bus_wr_valid : in std_logic;
|
||||
push_stack : in push_stack_type;
|
||||
pop_stack : in pop_stack_type;
|
||||
set_sr : in std_logic;
|
||||
new_sr : in std_logic_vector(15 downto 0);
|
||||
set_omr : in std_logic;
|
||||
new_omr : in std_logic_vector(7 downto 0);
|
||||
dec_lc : in std_logic;
|
||||
set_lc : in std_logic;
|
||||
new_lc : in unsigned(15 downto 0);
|
||||
set_la : in std_logic;
|
||||
new_la : in unsigned(BW_ADDRESS-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
architecture rtl of reg_file is
|
||||
|
||||
signal addr_r : addr_array;
|
||||
signal addr_m : addr_array;
|
||||
signal addr_n : addr_array;
|
||||
|
||||
signal loop_address : unsigned(BW_ADDRESS-1 downto 0);
|
||||
signal loop_counter : unsigned(15 downto 0);
|
||||
|
||||
-- condition code register
|
||||
signal ccr : std_logic_vector(7 downto 0);
|
||||
-- mode register
|
||||
signal mr : std_logic_vector(7 downto 0);
|
||||
-- status register = mode register + condition code register
|
||||
signal sr : std_logic_vector(15 downto 0);
|
||||
-- operation mode register
|
||||
signal omr : std_logic_vector(7 downto 0);
|
||||
|
||||
signal stack_pointer : unsigned(5 downto 0);
|
||||
signal system_stack_ssh : stack_array_type;
|
||||
signal system_stack_ssl : stack_array_type;
|
||||
|
||||
signal x0 : signed(23 downto 0);
|
||||
signal x1 : signed(23 downto 0);
|
||||
signal y0 : signed(23 downto 0);
|
||||
signal y1 : signed(23 downto 0);
|
||||
|
||||
signal a0 : signed(23 downto 0);
|
||||
signal a1 : signed(23 downto 0);
|
||||
signal a2 : signed(7 downto 0);
|
||||
|
||||
signal b0 : signed(23 downto 0);
|
||||
signal b1 : signed(23 downto 0);
|
||||
signal b2 : signed(7 downto 0);
|
||||
|
||||
signal limited_a1 : signed(23 downto 0);
|
||||
signal limited_b1 : signed(23 downto 0);
|
||||
signal limited_a0 : signed(23 downto 0);
|
||||
signal limited_b0 : signed(23 downto 0);
|
||||
signal set_limiting_flag : std_logic;
|
||||
signal X_bus_rd_limited_a : std_logic;
|
||||
signal X_bus_rd_limited_b : std_logic;
|
||||
signal Y_bus_rd_limited_a : std_logic;
|
||||
signal Y_bus_rd_limited_b : std_logic;
|
||||
signal reg_rd_limited_a : std_logic;
|
||||
signal reg_rd_limited_b : std_logic;
|
||||
signal rd_limited_a : std_logic;
|
||||
signal rd_limited_b : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
|
||||
|
||||
sr <= mr & ccr;
|
||||
|
||||
register_file.addr_r <= addr_r;
|
||||
register_file.addr_n <= addr_n;
|
||||
register_file.addr_m <= addr_m;
|
||||
register_file.lc <= loop_counter;
|
||||
register_file.la <= loop_address;
|
||||
register_file.ccr <= ccr;
|
||||
register_file.mr <= mr;
|
||||
register_file.sr <= sr;
|
||||
register_file.omr <= omr;
|
||||
register_file.stack_pointer <= stack_pointer;
|
||||
register_file.current_ssh <= system_stack_ssh(to_integer(stack_pointer(3 downto 0)));
|
||||
register_file.current_ssl <= system_stack_ssl(to_integer(stack_pointer(3 downto 0)));
|
||||
register_file.a <= a2 & a1 & a0;
|
||||
register_file.b <= b2 & b1 & b0;
|
||||
register_file.x0 <= x0;
|
||||
register_file.x1 <= x1;
|
||||
register_file.y0 <= y0;
|
||||
register_file.y1 <= y1;
|
||||
|
||||
|
||||
global_register_file: process(clk) is
|
||||
variable stack_pointer_plus_1 : unsigned(3 downto 0);
|
||||
variable reg_addr : integer range 0 to 7;
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst = '1' then
|
||||
addr_r <= (others => (others => '0'));
|
||||
addr_n <= (others => (others => '0'));
|
||||
addr_m <= (others => (others => '1'));
|
||||
ccr <= (others => '0');
|
||||
mr <= (others => '0');
|
||||
omr <= (others => '0');
|
||||
system_stack_ssl <= (others => (others => '0'));
|
||||
system_stack_ssh <= (others => (others => '0'));
|
||||
stack_pointer <= (others => '0');
|
||||
loop_counter <= (others => '0');
|
||||
loop_address <= (others => '0');
|
||||
x0 <= (others => '0');
|
||||
x1 <= (others => '0');
|
||||
y0 <= (others => '0');
|
||||
y1 <= (others => '0');
|
||||
a0 <= (others => '0');
|
||||
a1 <= (others => '0');
|
||||
a2 <= (others => '0');
|
||||
b0 <= (others => '0');
|
||||
b1 <= (others => '0');
|
||||
b2 <= (others => '0');
|
||||
else
|
||||
reg_addr := to_integer(unsigned(reg_wr_addr(2 downto 0)));
|
||||
-----------------------------------------------------------------------
|
||||
-- General write port to register file using 6 bit addressing scheme
|
||||
-----------------------------------------------------------------------
|
||||
if reg_wr_addr_valid = '1' then
|
||||
case reg_wr_addr(5 downto 3) is
|
||||
-- X0, X1, Y0, Y1
|
||||
when "000" =>
|
||||
case reg_wr_addr(2 downto 0) is
|
||||
when "100" =>
|
||||
x0 <= signed(reg_wr_data);
|
||||
when "101" =>
|
||||
x1 <= signed(reg_wr_data);
|
||||
when "110" =>
|
||||
y0 <= signed(reg_wr_data);
|
||||
when "111" =>
|
||||
y1 <= signed(reg_wr_data);
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
-- A0, B0, A2, B2, A1, B1, A, B
|
||||
when "001" =>
|
||||
case reg_wr_addr(2 downto 0) is
|
||||
when "000" =>
|
||||
a0 <= signed(reg_wr_data);
|
||||
when "001" =>
|
||||
b0 <= signed(reg_wr_data);
|
||||
when "010" =>
|
||||
a2 <= signed(reg_wr_data(7 downto 0));
|
||||
when "011" =>
|
||||
b2 <= signed(reg_wr_data(7 downto 0));
|
||||
when "100" =>
|
||||
a1 <= signed(reg_wr_data);
|
||||
when "101" =>
|
||||
b1 <= signed(reg_wr_data);
|
||||
when "110" =>
|
||||
a2 <= (others => reg_wr_data(23));
|
||||
a1 <= signed(reg_wr_data);
|
||||
a0 <= (others => '0');
|
||||
when "111" =>
|
||||
b2 <= (others => reg_wr_data(23));
|
||||
b1 <= signed(reg_wr_data);
|
||||
b0 <= (others => '0');
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
-- R0-R7
|
||||
when "010" =>
|
||||
addr_r(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
-- N0-N7
|
||||
when "011" =>
|
||||
addr_n(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
-- M0-M7
|
||||
when "100" =>
|
||||
addr_m(reg_addr) <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
-- SR, OMR, SP, SSH, SSL, LA, LC
|
||||
when "111" =>
|
||||
case reg_wr_addr(2 downto 0) is
|
||||
-- SR
|
||||
when "001" =>
|
||||
mr <= reg_wr_data(15 downto 8);
|
||||
ccr <= reg_wr_data( 7 downto 0);
|
||||
|
||||
-- OMR
|
||||
when "010" =>
|
||||
omr <= reg_wr_data(7 downto 0);
|
||||
|
||||
-- SP
|
||||
when "011" =>
|
||||
stack_pointer <= unsigned(reg_wr_data(5 downto 0));
|
||||
|
||||
-- SSH
|
||||
when "100" =>
|
||||
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
|
||||
-- increase stack after writing
|
||||
stack_pointer(3 downto 0) <= stack_pointer_plus_1;
|
||||
-- test whether stack is full, if so set the stack error flag (SE)
|
||||
if stack_pointer(3 downto 0) = "1111" then
|
||||
stack_pointer(4) <= '1';
|
||||
end if;
|
||||
|
||||
-- SSL
|
||||
when "101" =>
|
||||
system_stack_ssl(to_integer(stack_pointer)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
|
||||
|
||||
-- LA
|
||||
when "110" =>
|
||||
loop_address <= unsigned(reg_wr_data(BW_ADDRESS-1 downto 0));
|
||||
|
||||
-- LC
|
||||
when "111" =>
|
||||
loop_counter <= unsigned(reg_wr_data(15 downto 0));
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
when others =>
|
||||
end case;
|
||||
end if;
|
||||
|
||||
----------------
|
||||
-- X BUS Write
|
||||
----------------
|
||||
if X_bus_wr_valid = '1' then
|
||||
case X_bus_wr_addr is
|
||||
when "00" =>
|
||||
x0 <= signed(X_bus_data_in);
|
||||
when "01" =>
|
||||
x1 <= signed(X_bus_data_in);
|
||||
when "10" =>
|
||||
a2 <= (others => X_bus_data_in(23));
|
||||
a1 <= signed(X_bus_data_in);
|
||||
a0 <= (others => '0');
|
||||
when others =>
|
||||
b2 <= (others => X_bus_data_in(23));
|
||||
b1 <= signed(X_bus_data_in);
|
||||
b0 <= (others => '0');
|
||||
end case;
|
||||
end if;
|
||||
----------------
|
||||
-- Y BUS Write
|
||||
----------------
|
||||
if Y_bus_wr_valid = '1' then
|
||||
case Y_bus_wr_addr is
|
||||
when "00" =>
|
||||
y0 <= signed(Y_bus_data_in);
|
||||
when "01" =>
|
||||
y1 <= signed(Y_bus_data_in);
|
||||
when "10" =>
|
||||
a2 <= (others => Y_bus_data_in(23));
|
||||
a1 <= signed(Y_bus_data_in);
|
||||
a0 <= (others => '0');
|
||||
when others =>
|
||||
b2 <= (others => Y_bus_data_in(23));
|
||||
b1 <= signed(Y_bus_data_in);
|
||||
b0 <= (others => '0');
|
||||
end case;
|
||||
end if;
|
||||
------------------
|
||||
-- L BUS Write
|
||||
------------------
|
||||
if L_bus_wr_valid = '1' then
|
||||
case L_bus_wr_addr is
|
||||
-- A10
|
||||
when "000" =>
|
||||
a1 <= signed(X_bus_data_in);
|
||||
a0 <= signed(Y_bus_data_in);
|
||||
-- B10
|
||||
when "001" =>
|
||||
b1 <= signed(X_bus_data_in);
|
||||
b0 <= signed(Y_bus_data_in);
|
||||
-- X
|
||||
when "010" =>
|
||||
x1 <= signed(X_bus_data_in);
|
||||
x0 <= signed(Y_bus_data_in);
|
||||
-- Y
|
||||
when "011" =>
|
||||
y1 <= signed(X_bus_data_in);
|
||||
y0 <= signed(Y_bus_data_in);
|
||||
-- A
|
||||
when "100" =>
|
||||
a2 <= (others => X_bus_data_in(23));
|
||||
a1 <= signed(X_bus_data_in);
|
||||
a0 <= signed(Y_bus_data_in);
|
||||
-- B
|
||||
when "101" =>
|
||||
b2 <= (others => X_bus_data_in(23));
|
||||
b1 <= signed(X_bus_data_in);
|
||||
b0 <= signed(Y_bus_data_in);
|
||||
-- AB
|
||||
when "110" =>
|
||||
a2 <= (others => X_bus_data_in(23));
|
||||
a1 <= signed(X_bus_data_in);
|
||||
a0 <= (others => '0');
|
||||
b2 <= (others => Y_bus_data_in(23));
|
||||
b1 <= signed(Y_bus_data_in);
|
||||
b0 <= (others => '0');
|
||||
-- BA
|
||||
when others =>
|
||||
a2 <= (others => Y_bus_data_in(23));
|
||||
a1 <= signed(Y_bus_data_in);
|
||||
a0 <= (others => '0');
|
||||
b2 <= (others => X_bus_data_in(23));
|
||||
b1 <= signed(X_bus_data_in);
|
||||
b0 <= (others => '0');
|
||||
end case;
|
||||
end if;
|
||||
|
||||
---------------------
|
||||
-- STATUS REGISTERS
|
||||
---------------------
|
||||
if set_sr = '1' then
|
||||
ccr <= new_sr( 7 downto 0);
|
||||
mr <= new_sr(15 downto 8);
|
||||
end if;
|
||||
if set_omr = '1' then
|
||||
omr <= new_omr;
|
||||
end if;
|
||||
-- data limiter active?
|
||||
-- listing this statement after the set_sr test results
|
||||
-- in the correct behaviour for ALU operations with parallel move
|
||||
if set_limiting_flag = '1' then
|
||||
ccr(6) <= '1';
|
||||
end if;
|
||||
|
||||
--------------------
|
||||
-- LOOP REGISTERS
|
||||
--------------------
|
||||
if set_la = '1' then
|
||||
loop_address <= new_la;
|
||||
end if;
|
||||
if set_lc = '1' then
|
||||
loop_counter <= new_lc;
|
||||
end if;
|
||||
if dec_lc = '1' then
|
||||
loop_counter <= loop_counter - 1;
|
||||
end if;
|
||||
|
||||
---------------------
|
||||
-- ADDRESS REGISTER
|
||||
---------------------
|
||||
if wr_R_port_A_valid = '1' then
|
||||
addr_r(to_integer(wr_R_port_A.reg_number)) <= wr_R_port_A.reg_value;
|
||||
end if;
|
||||
if wr_R_port_B_valid = '1' then
|
||||
addr_r(to_integer(wr_R_port_B.reg_number)) <= wr_R_port_B.reg_value;
|
||||
end if;
|
||||
|
||||
-------------------------
|
||||
-- ALU ACCUMULATOR WRITE
|
||||
-------------------------
|
||||
if alu_wr_valid = '1' then
|
||||
if alu_wr_addr = '0' then
|
||||
a2 <= alu_wr_data(55 downto 48);
|
||||
a1 <= alu_wr_data(47 downto 24);
|
||||
a0 <= alu_wr_data(23 downto 0);
|
||||
else
|
||||
b2 <= alu_wr_data(55 downto 48);
|
||||
b1 <= alu_wr_data(47 downto 24);
|
||||
b0 <= alu_wr_data(23 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
---------------------
|
||||
-- STACK CONTROLLER
|
||||
---------------------
|
||||
stack_pointer_plus_1 := stack_pointer(3 downto 0) + 1;
|
||||
if push_stack.valid = '1' then
|
||||
-- increase stack after writing
|
||||
stack_pointer(3 downto 0) <= stack_pointer_plus_1;
|
||||
-- test whether stack is full, if so set the stack error flag (SE)
|
||||
if stack_pointer(3 downto 0) = "1111" then
|
||||
stack_pointer(4) <= '1';
|
||||
end if;
|
||||
case push_stack.content is
|
||||
when PC =>
|
||||
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(push_stack.pc);
|
||||
|
||||
when PC_AND_SR =>
|
||||
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(push_stack.pc);
|
||||
system_stack_ssl(to_integer(stack_pointer_plus_1)) <= SR;
|
||||
|
||||
when LA_AND_LC =>
|
||||
system_stack_ssh(to_integer(stack_pointer_plus_1)) <= std_logic_vector(loop_address);
|
||||
system_stack_ssl(to_integer(stack_pointer_plus_1)) <= std_logic_vector(loop_counter);
|
||||
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-- decrease stack pointer
|
||||
if pop_stack.valid = '1' then
|
||||
stack_pointer(3 downto 0) <= stack_pointer(3 downto 0) - 1;
|
||||
-- if stack is empty set the underflow flag (bit 5, UF) and the stack error flag (bit 4, SE)
|
||||
if stack_pointer(3 downto 0) = "0000" then
|
||||
stack_pointer(5) <= '1';
|
||||
stack_pointer(4) <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
x_bus_rd_port: process(X_bus_rd_addr,x0,x1,a1,b1,limited_a1,limited_b1,
|
||||
L_bus_rd_addr,L_bus_rd_valid,y1) is
|
||||
begin
|
||||
X_bus_rd_limited_a <= '0';
|
||||
X_bus_rd_limited_b <= '0';
|
||||
case X_bus_rd_addr is
|
||||
when "00" => X_bus_data_out <= std_logic_vector(x0);
|
||||
when "01" => X_bus_data_out <= std_logic_vector(x1);
|
||||
when "10" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
|
||||
when others => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
|
||||
end case;
|
||||
if L_bus_rd_valid = '1' then
|
||||
case L_bus_rd_addr is
|
||||
when "000" => X_bus_data_out <= std_logic_vector(a1);
|
||||
when "001" => X_bus_data_out <= std_logic_vector(b1);
|
||||
when "010" => X_bus_data_out <= std_logic_vector(x1);
|
||||
when "011" => X_bus_data_out <= std_logic_vector(y1);
|
||||
when "100" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
|
||||
when "101" => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
|
||||
when "110" => X_bus_data_out <= std_logic_vector(limited_a1); X_bus_rd_limited_a <= '1';
|
||||
when others => X_bus_data_out <= std_logic_vector(limited_b1); X_bus_rd_limited_b <= '1';
|
||||
end case;
|
||||
end if;
|
||||
end process x_bus_rd_port;
|
||||
|
||||
y_bus_rd_port: process(Y_bus_rd_addr,y0,y1,a1,b1,limited_a1,limited_b1,
|
||||
L_bus_rd_addr,L_bus_rd_valid,a0,b0,x0,limited_a0,limited_b0) is
|
||||
begin
|
||||
Y_bus_rd_limited_a <= '0';
|
||||
Y_bus_rd_limited_b <= '0';
|
||||
case Y_bus_rd_addr is
|
||||
when "00" => Y_bus_data_out <= std_logic_vector(y0);
|
||||
when "01" => Y_bus_data_out <= std_logic_vector(y1);
|
||||
when "10" => Y_bus_data_out <= std_logic_vector(limited_a1); Y_bus_rd_limited_a <= '1';
|
||||
when others => Y_bus_data_out <= std_logic_vector(limited_b1); Y_bus_rd_limited_b <= '1';
|
||||
end case;
|
||||
if L_bus_rd_valid = '1' then
|
||||
case L_bus_rd_addr is
|
||||
when "000" => Y_bus_data_out <= std_logic_vector(a0);
|
||||
when "001" => Y_bus_data_out <= std_logic_vector(b0);
|
||||
when "010" => Y_bus_data_out <= std_logic_vector(x0);
|
||||
when "011" => Y_bus_data_out <= std_logic_vector(y0);
|
||||
when "100" => Y_bus_data_out <= std_logic_vector(limited_a0); Y_bus_rd_limited_a <= '1';
|
||||
when "101" => Y_bus_data_out <= std_logic_vector(limited_b0); Y_bus_rd_limited_b <= '1';
|
||||
when "110" => Y_bus_data_out <= std_logic_vector(limited_b1); Y_bus_rd_limited_b <= '1';
|
||||
when others => Y_bus_data_out <= std_logic_vector(limited_a1); Y_bus_rd_limited_a <= '1';
|
||||
end case;
|
||||
end if;
|
||||
end process y_bus_rd_port;
|
||||
|
||||
|
||||
reg_rd_port: process(reg_rd_addr, x0,x1,y0,y1,a0,a1,a2,b0,b1,b2,
|
||||
omr,ccr,mr,addr_r,addr_n,addr_m,stack_pointer,
|
||||
loop_address,loop_counter,system_stack_ssl,system_stack_ssh) is
|
||||
variable reg_addr : integer range 0 to 7;
|
||||
begin
|
||||
reg_addr := to_integer(unsigned(reg_rd_addr(2 downto 0)));
|
||||
reg_rd_data <= (others => '0');
|
||||
reg_rd_limited_a <= '0';
|
||||
reg_rd_limited_b <= '0';
|
||||
|
||||
case reg_rd_addr(5 downto 3) is
|
||||
-- X0, X1, Y0, Y1
|
||||
when "000" =>
|
||||
case reg_rd_addr(2 downto 0) is
|
||||
when "100" =>
|
||||
reg_rd_data <= std_logic_vector(x0);
|
||||
when "101" =>
|
||||
reg_rd_data <= std_logic_vector(x1);
|
||||
when "110" =>
|
||||
reg_rd_data <= std_logic_vector(y0);
|
||||
when "111" =>
|
||||
reg_rd_data <= std_logic_vector(y1);
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
-- A0, B0, A2, B2, A1, B1, A, B
|
||||
when "001" =>
|
||||
case reg_rd_addr(2 downto 0) is
|
||||
when "000" =>
|
||||
reg_rd_data <= std_logic_vector(a0);
|
||||
when "001" =>
|
||||
reg_rd_data <= std_logic_vector(b0);
|
||||
when "010" =>
|
||||
-- MSBs are read as zero!
|
||||
reg_rd_data(23 downto 8) <= (others => '0');
|
||||
reg_rd_data(7 downto 0) <= std_logic_vector(a2);
|
||||
when "011" =>
|
||||
-- MSBs are read as zero!
|
||||
reg_rd_data(23 downto 8) <= (others => '0');
|
||||
reg_rd_data(7 downto 0) <= std_logic_vector(b2);
|
||||
when "100" =>
|
||||
reg_rd_data <= std_logic_vector(a1);
|
||||
when "101" =>
|
||||
reg_rd_data <= std_logic_vector(b1);
|
||||
when "110" =>
|
||||
reg_rd_data <= std_logic_vector(limited_a1);
|
||||
reg_rd_limited_a <= '1';
|
||||
when "111" =>
|
||||
reg_rd_data <= std_logic_vector(limited_b1);
|
||||
reg_rd_limited_b <= '1';
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
-- R0-R7
|
||||
when "010" =>
|
||||
reg_rd_data <= std_logic_vector(resize(addr_r(reg_addr), 24));
|
||||
|
||||
-- N0-N7
|
||||
when "011" =>
|
||||
reg_rd_data <= std_logic_vector(resize(addr_n(reg_addr), 24));
|
||||
|
||||
-- M0-M7
|
||||
when "100" =>
|
||||
reg_rd_data <= std_logic_vector(resize(addr_m(reg_addr), 24));
|
||||
|
||||
-- SR, OMR, SP, SSH, SSL, LA, LC
|
||||
when "111" =>
|
||||
case reg_wr_addr(2 downto 0) is
|
||||
-- SR
|
||||
when "001" =>
|
||||
reg_rd_data(23 downto 16) <= (others => '0');
|
||||
reg_rd_data(15 downto 0) <= mr & ccr;
|
||||
|
||||
-- OMR
|
||||
when "010" =>
|
||||
reg_rd_data(23 downto 8) <= (others => '0');
|
||||
reg_rd_data( 7 downto 0) <= omr;
|
||||
|
||||
-- SP
|
||||
when "011" =>
|
||||
reg_rd_data(23 downto 6) <= (others => '0');
|
||||
reg_rd_data(5 downto 0) <= std_logic_vector(stack_pointer);
|
||||
|
||||
-- SSH
|
||||
when "100" =>
|
||||
-- TODO!
|
||||
-- system_stack_ssh(to_integer(stack_pointer_plus_1)) <= reg_wr_data(BW_ADDRESS-1 downto 0);
|
||||
-- -- increase stack after writing
|
||||
-- stack_pointer(3 downto 0) <= stack_pointer_plus_1;
|
||||
-- -- test whether stack is full, if so set the stack error flag (SE)
|
||||
-- if stack_pointer(3 downto 0) = "1111" then
|
||||
-- stack_pointer(4) <= '1';
|
||||
-- end if;
|
||||
|
||||
-- SSL
|
||||
when "101" =>
|
||||
reg_rd_data <= (others => '0');
|
||||
reg_rd_data(BW_ADDRESS-1 downto 0) <= std_logic_vector(system_stack_ssl(to_integer(stack_pointer)));
|
||||
|
||||
-- LA
|
||||
when "110" =>
|
||||
reg_rd_data <= (others => '0');
|
||||
reg_rd_data(BW_ADDRESS-1 downto 0) <= std_logic_vector(loop_address);
|
||||
|
||||
-- LC
|
||||
when "111" =>
|
||||
reg_rd_data <= (others => '0');
|
||||
reg_rd_data(15 downto 0) <= std_logic_vector(loop_counter);
|
||||
|
||||
when others =>
|
||||
end case;
|
||||
when others =>
|
||||
end case;
|
||||
end process;
|
||||
|
||||
rd_limited_a <= '1' when reg_rd_limited_a = '1' or X_bus_rd_limited_a = '1' or Y_bus_rd_limited_a = '1' else '0';
|
||||
rd_limited_b <= '1' when reg_rd_limited_b = '1' or X_bus_rd_limited_b = '1' or Y_bus_rd_limited_b = '1' else '0';
|
||||
|
||||
data_shifter_limiter: process(a2,a1,a0,b2,b1,b0,sr,rd_limited_a,rd_limited_b) is
|
||||
variable scaled_a : signed(55 downto 0);
|
||||
variable scaled_b : signed(55 downto 0);
|
||||
begin
|
||||
|
||||
set_limiting_flag <= '0';
|
||||
-----------------
|
||||
-- DATA SCALING
|
||||
-----------------
|
||||
-- test against scaling bits S1, S0
|
||||
case sr(11 downto 10) is
|
||||
-- scale down (right shift)
|
||||
when "01" =>
|
||||
scaled_a := a2(7) & a2 & a1 & a0(23 downto 1);
|
||||
scaled_b := b2(7) & b2 & b1 & b0(23 downto 1);
|
||||
-- scale up (arithmetic left shift)
|
||||
when "10" =>
|
||||
scaled_a := a2(6 downto 0) & a1 & a0 & '0';
|
||||
scaled_b := b2(6 downto 0) & b1 & b0 & '0';
|
||||
-- "00" do not scale!
|
||||
when others =>
|
||||
scaled_a := a2 & a1 & a0;
|
||||
scaled_b := b2 & b1 & b0;
|
||||
end case;
|
||||
|
||||
-- only sign extension stored in a2?
|
||||
-- Yes: No limiting needed!
|
||||
if scaled_a(55 downto 47) = "111111111" or scaled_a(55 downto 47) = "000000000" then
|
||||
limited_a1 <= scaled_a(47 downto 24);
|
||||
limited_a0 <= scaled_a(23 downto 0);
|
||||
else
|
||||
-- positive value in a?
|
||||
if scaled_a(55) = '0' then
|
||||
limited_a1 <= X"7FFFFF";
|
||||
limited_a0 <= X"FFFFFF";
|
||||
-- negative value in a?
|
||||
else
|
||||
limited_a1 <= X"800000";
|
||||
limited_a0 <= X"000000";
|
||||
end if;
|
||||
-- set the limit flag in the status register
|
||||
if rd_limited_a = '1' then
|
||||
set_limiting_flag <= '1';
|
||||
end if;
|
||||
end if;
|
||||
-- only sign extension stored in b2?
|
||||
-- Yes: No limiting needed!
|
||||
if scaled_b(55 downto 47) = "111111111" or scaled_b(55 downto 47) = "000000000" then
|
||||
limited_b1 <= scaled_b(47 downto 24);
|
||||
limited_b0 <= scaled_b(23 downto 0);
|
||||
else
|
||||
-- positive value in b?
|
||||
if scaled_b(55) = '0' then
|
||||
limited_b1 <= X"7FFFFF";
|
||||
limited_b0 <= X"FFFFFF";
|
||||
-- negative value in b?
|
||||
else
|
||||
limited_b1 <= X"800000";
|
||||
limited_b0 <= X"000000";
|
||||
end if;
|
||||
-- set the limit flag in the status register
|
||||
if rd_limited_b = '1' then
|
||||
set_limiting_flag <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
end architecture rtl;
|
||||
167
FPGA_Quartus_13.1/DSP/src/types_pkg.vhd
Normal file
167
FPGA_Quartus_13.1/DSP/src/types_pkg.vhd
Normal file
@@ -0,0 +1,167 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
library work;
|
||||
use work.parameter_pkg.all;
|
||||
|
||||
|
||||
|
||||
package types_pkg is
|
||||
|
||||
-- the different addressing modes
|
||||
type adgen_mode_type is (NOP, POST_MIN_N, POST_PLUS_N, POST_MIN_1, POST_PLUS_1, INDEXED_N, PRE_MIN_1, ABSOLUTE, IMMEDIATE);
|
||||
------------------------
|
||||
-- Decoded instructions
|
||||
------------------------
|
||||
type instructions_type is (
|
||||
INSTR_NOP ,
|
||||
INSTR_RTI ,
|
||||
INSTR_ILLEGAL ,
|
||||
INSTR_SWI ,
|
||||
INSTR_RTS ,
|
||||
INSTR_RESET ,
|
||||
INSTR_WAIT ,
|
||||
INSTR_STOP ,
|
||||
INSTR_ENDDO ,
|
||||
INSTR_ANDI ,
|
||||
INSTR_ORI ,
|
||||
INSTR_DIV ,
|
||||
INSTR_NORM ,
|
||||
INSTR_LUA ,
|
||||
INSTR_MOVEC ,
|
||||
INSTR_REP ,
|
||||
INSTR_DO ,
|
||||
INSTR_MOVEM ,
|
||||
INSTR_MOVEP ,
|
||||
INSTR_PM_MOVEM,
|
||||
INSTR_BCLR ,
|
||||
INSTR_BSET ,
|
||||
INSTR_JCLR ,
|
||||
INSTR_JSET ,
|
||||
INSTR_JMP ,
|
||||
INSTR_JCC ,
|
||||
INSTR_BCHG ,
|
||||
INSTR_BTST ,
|
||||
INSTR_JSCLR ,
|
||||
INSTR_JSSET ,
|
||||
INSTR_JSR ,
|
||||
INSTR_JSCC );
|
||||
|
||||
type addr_array is array(0 to 7) of unsigned(BW_ADDRESS-1 downto 0);
|
||||
|
||||
type alu_shift_mode is (NO_SHIFT, SHIFT_LEFT, SHIFT_RIGHT, ZEROS);
|
||||
type alu_ccr_flag is (DONT_TOUCH, CLEAR, MODIFY, SET);
|
||||
type alu_ccr_flag_array is array(7 downto 0) of alu_ccr_flag;
|
||||
|
||||
type alu_ctrl_type is record
|
||||
mul_op1 : std_logic_vector(1 downto 0); -- x0,x1,y0,y1
|
||||
mul_op2 : std_logic_vector(1 downto 0); -- x0,x1,y0,y1
|
||||
shift_src : std_logic; -- a,b
|
||||
shift_src_sign : std_logic_vector(1 downto 0); -- 00: pos, 01: neg, 10: sign dependant, 11: reserved
|
||||
shift_mode : alu_shift_mode;
|
||||
rotate : std_logic; -- 0: logical shift, 1: rotate shift
|
||||
add_src_stage_1 : std_logic_vector(2 downto 0); -- x0,x1,y0,y1,x,y,a,b
|
||||
add_src_stage_2 : std_logic_vector(1 downto 0); -- 00: 0 , 01: add_src_1, 10: mul_result, 11: reserved
|
||||
add_src_sign : std_logic_vector(1 downto 0); -- 00: pos, 01: neg, 10: sign dependant, 11: reserved
|
||||
logic_function : std_logic_vector(2 downto 0); -- 000: none, 001: and, 010: or, 011: eor, 100: not
|
||||
word_24_update : std_logic; -- only accumulator bits 47 downto 24 affected?
|
||||
rounding_used : std_logic_vector(1 downto 0); -- 00: no rounding, 01: rounding, 10: add carry, 11: subtract carry
|
||||
store_result : std_logic; -- 0: do not update accumulator, 1: update accumulator
|
||||
dst_accu : std_logic; -- 0: a, 1: b
|
||||
div_instr : std_logic; -- DIV instruction? Special ALU operations needed!
|
||||
norm_instr : std_logic; -- NORM instruction? Special ALU operations needed!
|
||||
ccr_flags_ctrl : alu_ccr_flag_array;
|
||||
end record;
|
||||
|
||||
type pipeline_signals is record
|
||||
instr_word: std_logic_vector(23 downto 0);
|
||||
pc : unsigned(BW_ADDRESS-1 downto 0);
|
||||
dble_word_instr : std_logic;
|
||||
instr_array : instructions_type;
|
||||
act_array : std_logic_vector(NUM_ACT_SIGNALS-1 downto 0);
|
||||
dec_activate : std_logic;
|
||||
adgen_mode_a : adgen_mode_type;
|
||||
adgen_mode_b : adgen_mode_type;
|
||||
reg_wr_addr : std_logic_vector(5 downto 0);
|
||||
reg_rd_addr : std_logic_vector(5 downto 0);
|
||||
x_bus_rd_addr : std_logic_vector(1 downto 0);
|
||||
x_bus_wr_addr : std_logic_vector(1 downto 0);
|
||||
y_bus_rd_addr : std_logic_vector(1 downto 0);
|
||||
y_bus_wr_addr : std_logic_vector(1 downto 0);
|
||||
l_bus_addr : std_logic_vector(2 downto 0);
|
||||
adgen_address_x : unsigned(BW_ADDRESS-1 downto 0);
|
||||
adgen_address_y : unsigned(BW_ADDRESS-1 downto 0);
|
||||
RAM_out_x : std_logic_vector(23 downto 0);
|
||||
RAM_out_y : std_logic_vector(23 downto 0);
|
||||
alu_ctrl : alu_ctrl_type;
|
||||
end record;
|
||||
|
||||
type pipeline_type is array(0 to PIPELINE_DEPTH-1) of pipeline_signals;
|
||||
|
||||
|
||||
type register_file_type is record
|
||||
a : signed(55 downto 0);
|
||||
b : signed(55 downto 0);
|
||||
x0 : signed(23 downto 0);
|
||||
x1 : signed(23 downto 0);
|
||||
y0 : signed(23 downto 0);
|
||||
y1 : signed(23 downto 0);
|
||||
la : unsigned(BW_ADDRESS-1 downto 0);
|
||||
lc : unsigned(15 downto 0);
|
||||
addr_r : addr_array;
|
||||
addr_n : addr_array;
|
||||
addr_m : addr_array;
|
||||
ccr : std_logic_vector(7 downto 0);
|
||||
mr : std_logic_vector(7 downto 0);
|
||||
sr : std_logic_vector(15 downto 0);
|
||||
omr : std_logic_vector(7 downto 0);
|
||||
stack_pointer : unsigned(5 downto 0);
|
||||
-- system_stack_ssh : stack_array_type;
|
||||
-- system_stack_ssl : stack_array_type;
|
||||
current_ssh : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
current_ssl : std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
|
||||
end record;
|
||||
|
||||
type addr_wr_port_type is record
|
||||
-- write_valid : std_logic;
|
||||
reg_number : unsigned(2 downto 0);
|
||||
reg_value : unsigned(15 downto 0);
|
||||
end record;
|
||||
|
||||
type mem_ctrl_type_in is record
|
||||
rd_addr : unsigned(BW_ADDRESS-1 downto 0);
|
||||
rd_en : std_logic;
|
||||
wr_addr : unsigned(BW_ADDRESS-1 downto 0);
|
||||
wr_en : std_logic;
|
||||
data_in : std_logic_vector(23 downto 0);
|
||||
end record;
|
||||
|
||||
type mem_ctrl_type_out is record
|
||||
data_out : std_logic_vector(23 downto 0);
|
||||
data_out_valid : std_logic;
|
||||
end record;
|
||||
|
||||
type memory_type is (X_MEM, Y_MEM, P_MEM);
|
||||
---------------
|
||||
-- STACK TYPES
|
||||
---------------
|
||||
type stack_array_type is array(0 to 15) of std_logic_vector(BW_ADDRESS-1 downto 0);
|
||||
|
||||
type push_stack_content_type is (PC, PC_AND_SR, LA_AND_LC);
|
||||
|
||||
type push_stack_type is record
|
||||
valid : std_logic;
|
||||
pc : unsigned(BW_ADDRESS-1 downto 0);
|
||||
content : push_stack_content_type;
|
||||
end record;
|
||||
|
||||
-- type pop_stack_content_type is (PC, PC_AND_SR, SR, LA_AND_LC);
|
||||
|
||||
-- type pop_stack_type is std_logic;
|
||||
type pop_stack_type is record
|
||||
valid : std_logic;
|
||||
-- content : pop_stack_content_type;
|
||||
end record;
|
||||
|
||||
end package types_pkg;
|
||||
Reference in New Issue
Block a user