1 |
4 |
atypic |
library ieee;
|
2 |
|
|
use ieee.std_logic_1164.all;
|
3 |
|
|
use work.whisk_constants.all;
|
4 |
|
|
|
5 |
|
|
entity instr_decode is
|
6 |
|
|
port (
|
7 |
|
|
clk : in std_logic;
|
8 |
|
|
-- data lines
|
9 |
|
|
reg1 : out std_logic_vector(WORD_BITS - 1 downto 0);
|
10 |
|
|
reg2 : out std_logic_vector(WORD_BITS - 1 downto 0);
|
11 |
|
|
immediate : out std_logic_vector(IMM_SIZE - 1 downto 0);
|
12 |
|
|
regs_data_in : in std_logic_vector(WORD_BITS - 1 downto 0);
|
13 |
|
|
--branch_target : out std_logic_vector(MC_ADDR_BITS - 1 downto 0);
|
14 |
|
|
|
15 |
|
|
instr : in std_logic_vector(MC_INSTR_BITS - 1 downto 0);
|
16 |
|
|
|
17 |
|
|
-- Let the control unit know if we're using indirect addressing
|
18 |
|
|
indir_reg1_sel : out std_logic;
|
19 |
|
|
indir_reg2_sel : out std_logic;
|
20 |
|
|
alu_funct : out std_logic_vector(ALU_FUNCT_SIZE - 1 downto 0);
|
21 |
|
|
reg_write : out std_logic; -- feed forward to next stage
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
wb_reg_write : in std_logic; -- from write-back stage.
|
25 |
|
|
ctrl_regs_we : in std_logic; -- from control unit
|
26 |
|
|
ctrl_alu_funct : in std_logic_vector(ALU_FUNCT_SIZE - 1 downto 0);
|
27 |
|
|
|
28 |
|
|
-- Select source of register address. Either direct or indirect register.
|
29 |
|
|
regs_addr_src_1 : in std_logic;
|
30 |
|
|
regs_addr_src_2 : in std_logic
|
31 |
|
|
);
|
32 |
|
|
end entity;
|
33 |
|
|
|
34 |
|
|
|
35 |
|
|
architecture mixed of instr_decode is
|
36 |
|
|
signal regs_addr_1 : std_logic_vector(REGS_ADDR_BITS - 1 downto 0);
|
37 |
|
|
signal regs_addr_2 : std_logic_vector(REGS_ADDR_BITS - 1 downto 0);
|
38 |
|
|
signal regs_data_1 : std_logic_vector(WORD_BITS - 1 downto 0);
|
39 |
|
|
signal regs_data_2 : std_logic_vector(WORD_BITS - 1 downto 0);
|
40 |
|
|
-- signal regs_data_in : std_logic_vector(WORD_BITS - 1 downto 0);
|
41 |
|
|
|
42 |
|
|
--storage for the indirect registers
|
43 |
|
|
signal indir_reg_1 : std_logic_vector(REGS_ADDR_BITS - 1 downto 0);
|
44 |
|
|
signal indir_reg_2 : std_logic_vector(REGS_ADDR_BITS - 1 downto 0);
|
45 |
|
|
begin
|
46 |
|
|
regfile : entity dualport_mem
|
47 |
|
|
generic map (
|
48 |
|
|
memsize => REGS_SIZE,
|
49 |
|
|
addr_width => REGS_ADDR_BITS,
|
50 |
|
|
data_width => WORD_BITS,
|
51 |
|
|
initfile => SCRATCH_MEM_INIT)
|
52 |
|
|
port map (
|
53 |
|
|
clk => clk,
|
54 |
|
|
a => regs_addr_1,
|
55 |
|
|
b => regs_addr_2,
|
56 |
|
|
doa => regs_data_1,
|
57 |
|
|
dob => regs_data_2,
|
58 |
|
|
dia => regs_data_in,
|
59 |
|
|
we => wb_reg_write);
|
60 |
|
|
|
61 |
|
|
-- Indirect register addressing
|
62 |
|
|
regs_addr_1 <= indir_reg_1 when regs_addr_src_1 = '1'
|
63 |
|
|
else instr(INSTR_REG1_START - 1 downto INSTR_REG1_END);
|
64 |
|
|
regs_addr_2 <= indir_reg_2 when regs_addr_src_2 = '1'
|
65 |
|
|
else instr(INSTR_REG2_START - 1 downto INSTR_REG2_END);
|
66 |
|
|
|
67 |
|
|
-- Update pipeline registers.
|
68 |
|
|
update_id_regs : process (clk)
|
69 |
|
|
begin
|
70 |
|
|
if rising_edge(clk) then
|
71 |
|
|
immediate <= instr(INSTR_IMM_START downto 0);
|
72 |
|
|
-- Control signals that are fed forward.
|
73 |
|
|
reg_write <= ctrl_regs_we;
|
74 |
|
|
-- Lets us know if the next cycle is an indirect addressing
|
75 |
|
|
indir_reg1_sel <= instr(INSTR_REG1_INDIR);
|
76 |
|
|
indir_reg2_sel <= instr(INSTR_REG2_INDIR);
|
77 |
|
|
indir_reg_1 <= regs_data_1(REGS_ADDR_BITS - 1 downto 0);
|
78 |
|
|
indir_reg_2 <= regs_data_2(REGS_ADDR_BITS - 1 downto 0);
|
79 |
|
|
alu_funct <= ctrl_alu_funct;
|
80 |
|
|
end if;
|
81 |
|
|
-- output ports are registered, no need to be under flank.
|
82 |
|
|
reg1 <= regs_data_1;
|
83 |
|
|
reg2 <= regs_data_2;
|
84 |
|
|
|
85 |
|
|
end process;
|
86 |
|
|
end architecture;
|