/
mcc_control_unit.vhd
111 lines (100 loc) · 3.36 KB
/
mcc_control_unit.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
----------------------------------------------------------------------------------
-- Company: @Home
-- Engineer: zpekic@hotmail.com
--
-- Create Date: 12:25:11 04/21/2020
-- Design Name: Microcode controller unit
-- Module Name:
-- Project Name:
-- Target Devices: Digilent Anvyl
-- Tool versions: Xilinx ISE 14.7
-- Description: This is proof of concept for mcc microcode compiler https://github.com/zpekic/MicroCodeCompiler
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity mcc_control_unit is
Generic (
CODE_DEPTH : positive;
IF_WIDTH : positive
);
Port (
-- standard inputs
reset : in STD_LOGIC;
clk : in STD_LOGIC;
-- design specific inputs
seq_cond : in STD_LOGIC_VECTOR (IF_WIDTH - 1 downto 0);
seq_then : in STD_LOGIC_VECTOR (CODE_DEPTH - 1 downto 0);
seq_else : in STD_LOGIC_VECTOR (CODE_DEPTH - 1 downto 0);
seq_fork : in STD_LOGIC_VECTOR (CODE_DEPTH - 1 downto 0);
cond : in STD_LOGIC_VECTOR (2 ** IF_WIDTH - 1 downto 0);
-- outputs
ui_nextinstr : buffer STD_LOGIC_VECTOR (CODE_DEPTH - 1 downto 0);
ui_address : out STD_LOGIC_VECTOR (CODE_DEPTH - 1 downto 0));
end mcc_control_unit;
architecture Behavioral of mcc_control_unit is
constant zero: std_logic_vector(31 downto 0) := X"00000000";
signal uPC0, uPC1, uPC2, uPC3, uPC4, uPC5, uPC6, uPC7: std_logic_vector(CODE_DEPTH - 1 downto 0);
signal condition, push_then_jump: std_logic;
begin
-- uPC holds the address of current microinstruction
ui_address <= uPC0;
-- evaluate if true/false
condition <= cond(to_integer(unsigned(seq_cond)));
-- select next instruction based on condition
ui_nextinstr <= seq_then when (condition = '1') else seq_else;
-- check if jump or one of 4 "special" instructions
push_then_jump <= '0' when (ui_nextinstr(CODE_DEPTH - 1 downto 2) = zero(CODE_DEPTH - 3 downto 0)) else '1';
sequence: process(reset, clk, push_then_jump, ui_nextinstr)
begin
if (reset = '1') then
uPC0 <= (others => '0'); -- reset clears top microcode program counter
else
if (rising_edge(clk)) then
if (push_then_jump = '1') then
uPC0 <= ui_nextinstr;
uPC1 <= std_logic_vector(unsigned(uPC0) + 1);
uPC2 <= uPC1;
uPC3 <= uPC2;
uPC4 <= uPC3;
uPC5 <= uPC4;
uPC6 <= uPC5;
uPC7 <= uPC6;
else
case (ui_nextinstr(1 downto 0)) is
when "00" => -- next
uPC0 <= std_logic_vector(unsigned(uPC0) + 1);
when "01" => -- repeat
uPC0 <= uPC0;
when "10" => -- return
uPC0 <= uPC1;
uPC1 <= uPC2;
uPC2 <= uPC3;
uPC3 <= uPC4;
uPC4 <= uPC5;
uPC5 <= uPC6;
uPC6 <= uPC7;
uPC7 <= (others => '0');
when "11" => -- fork
uPC0 <= seq_fork;
when others =>
null;
end case;
end if;
end if;
end if;
end process;
end;