1 |
2 |
atypic |
library ieee;
|
2 |
|
|
use ieee.std_logic_1164.all;
|
3 |
|
|
use work.leval_package.all;
|
4 |
|
|
|
5 |
|
|
entity leval is
|
6 |
|
|
port(
|
7 |
|
|
rst : in std_logic; -- convert to synchronous
|
8 |
|
|
clk : in std_logic;
|
9 |
|
|
data_in : in std_logic_vector(BUS_SIZE - 1 downto 0);
|
10 |
|
|
data_out : out std_logic_vector(BUS_SIZE - 1 downto 0);
|
11 |
|
|
addr_bus : out std_logic_vector(ADDR_SIZE-1 downto 0);
|
12 |
|
|
wait_s : in std_logic;
|
13 |
|
|
sync : in std_logic;
|
14 |
|
|
read : out std_logic;
|
15 |
|
|
write : out std_logic;
|
16 |
|
|
led : out std_logic_vector(7 downto 0));
|
17 |
|
|
-- pc_out : out std_logic_vector(MC_ADDR_SIZE-1 downto 0);
|
18 |
|
|
-- state_out : out std_logic_vector(3 downto 0);
|
19 |
|
|
-- status_out : out std_logic_vector(STATUS_REG_SIZE-1 downto 0);
|
20 |
|
|
-- pc_write_out : out std_logic);
|
21 |
|
|
end entity;
|
22 |
|
|
|
23 |
|
|
architecture rtl of leval is
|
24 |
|
|
component pc_incer is
|
25 |
|
|
port(
|
26 |
|
|
clk : in std_logic;
|
27 |
|
|
rst : in std_logic;
|
28 |
|
|
pause : in std_logic;
|
29 |
|
|
offset : in std_logic_vector(MC_ADDR_SIZE - 1 downto 0);
|
30 |
|
|
branch : in std_logic;
|
31 |
|
|
pc_next : out std_logic_vector(MC_ADDR_SIZE - 1 downto 0) );
|
32 |
|
|
end component pc_incer;
|
33 |
|
|
|
34 |
|
|
component inst_mem is
|
35 |
|
|
port (
|
36 |
|
|
clk : in std_logic;
|
37 |
|
|
addr : in std_logic_vector(MC_ADDR_SIZE - 1 downto 0);
|
38 |
|
|
dout : out std_logic_vector(MC_INSTR_SIZE - 1 downto 0);
|
39 |
|
|
din : in std_logic_vector(MC_INSTR_SIZE - 1 downto 0);
|
40 |
|
|
we : in std_logic);
|
41 |
|
|
end component inst_mem;
|
42 |
|
|
|
43 |
|
|
component alu is
|
44 |
|
|
port (
|
45 |
|
|
in_a : in std_logic_vector(OBJECT_SIZE-1 downto 0);
|
46 |
|
|
in_b : in std_logic_vector(OBJECT_SIZE-1 downto 0);
|
47 |
|
|
funct : in std_logic_vector(FUNCT_SIZE-1 downto 0);
|
48 |
|
|
status : out std_logic_vector(STATUS_REG_SIZE-1 downto 0);
|
49 |
|
|
output : out std_logic_vector(OBJECT_SIZE-1 downto 0));
|
50 |
|
|
end component alu;
|
51 |
|
|
|
52 |
|
|
component reg_mem is
|
53 |
|
|
port (
|
54 |
|
|
clk : in std_logic;
|
55 |
|
|
we : in std_logic;
|
56 |
|
|
a : in std_logic_vector(SCRATCH_ADDR_SIZE - 1 downto 0);
|
57 |
|
|
b : in std_logic_vector(SCRATCH_ADDR_SIZE - 1 downto 0);
|
58 |
|
|
dia : in std_logic_vector(WORD_SIZE - 1 downto 0);
|
59 |
|
|
doa : out std_logic_vector(WORD_SIZE - 1 downto 0);
|
60 |
|
|
dob : out std_logic_vector(WORD_SIZE - 1 downto 0));
|
61 |
|
|
end component reg_mem;
|
62 |
|
|
|
63 |
|
|
component control is
|
64 |
|
|
port(
|
65 |
|
|
clk : in std_logic;
|
66 |
|
|
rst : in std_logic;
|
67 |
|
|
status_in : in std_logic_vector(STATUS_REG_SIZE - 1 downto 0);
|
68 |
|
|
data_rdy : in std_logic;
|
69 |
|
|
sync : in std_logic;
|
70 |
|
|
opcode : in std_logic_vector(OPCODE_SIZE - 1 downto 0);
|
71 |
|
|
breakpoint : in std_logic;
|
72 |
|
|
debug_en : in std_logic;
|
73 |
|
|
break_mask : in std_logic_vector(STATUS_REG_SIZE - 1 downto 0);
|
74 |
|
|
break_flags : in std_logic_vector(STATUS_REG_SIZE - 1 downto 0);
|
75 |
|
|
indir_reg1 : in std_logic;
|
76 |
|
|
indir_reg2 : in std_logic;
|
77 |
|
|
write_reg_en : out std_logic;
|
78 |
|
|
indir_reg1_sel : out std_logic;
|
79 |
|
|
indir_reg2_sel : out std_logic;
|
80 |
|
|
alu_func : out std_logic_vector(FUNCT_SIZE-1 downto 0);
|
81 |
|
|
alu_op1_sel : out std_logic;
|
82 |
|
|
alu_op2_sel : out std_logic;
|
83 |
|
|
status_reg_w_en : out std_logic_vector(STATUS_REG_SIZE-1 downto 0);
|
84 |
|
|
pc_write_en : out std_logic;
|
85 |
|
|
branch_taken : out std_logic;
|
86 |
|
|
write : out std_logic;
|
87 |
|
|
read : out std_logic;
|
88 |
|
|
mem_to_reg_sel : out std_logic;
|
89 |
|
|
write_indir_addr_wr_en : out std_logic);
|
90 |
|
|
-- state_out : out std_logic_vector(3 downto 0));
|
91 |
|
|
end component control;
|
92 |
|
|
|
93 |
|
|
signal instr : std_logic_vector(MC_INSTR_SIZE-1 downto 0);
|
94 |
|
|
signal pc_write_en : std_logic;
|
95 |
|
|
|
96 |
|
|
-- Skratch memory input lines
|
97 |
|
|
signal r1_addr : std_logic_vector(SCRATCH_ADDR_SIZE-1 downto 0);
|
98 |
|
|
signal r2_addr : std_logic_vector(SCRATCH_ADDR_SIZE-1 downto 0);
|
99 |
|
|
signal scratch_we : std_logic; -- Enable register writing
|
100 |
|
|
signal wr_value : std_logic_vector(WORD_SIZE-1 downto 0);
|
101 |
|
|
|
102 |
|
|
-- from SCRATCH
|
103 |
|
|
signal r1_value : std_logic_vector(WORD_SIZE-1 downto 0);
|
104 |
|
|
signal r2_value : std_logic_vector(WORD_SIZE-1 downto 0);
|
105 |
|
|
-- to ALU
|
106 |
|
|
signal alu_func : std_logic_vector(FUNCT_SIZE-1 downto 0);
|
107 |
|
|
signal alu_op1_val : std_logic_vector(WORD_SIZE-1 downto 0);
|
108 |
|
|
signal alu_op2_val : std_logic_vector(WORD_SIZE-1 downto 0);
|
109 |
|
|
-- from ALU
|
110 |
|
|
signal alu_status : std_logic_vector(STATUS_REG_SIZE-1 downto 0);
|
111 |
|
|
signal alu_out : std_logic_vector(WORD_SIZE-1 downto 0);
|
112 |
|
|
-- to CONTROL
|
113 |
|
|
-- from CONTROL
|
114 |
|
|
signal alu_op2_sel : std_logic;
|
115 |
|
|
signal branch : std_logic;
|
116 |
|
|
signal SRWriteEnable : std_logic_vector(STATUS_REG_SIZE-1 downto 0);
|
117 |
|
|
signal r1_in_mux, r2_in_mux : std_logic;
|
118 |
|
|
signal write_s, read_s : std_logic;
|
119 |
|
|
signal mem_to_reg : std_logic;
|
120 |
|
|
|
121 |
|
|
-- instruction
|
122 |
|
|
signal opcode : std_logic_vector(OPCODE_SIZE-1 downto 0);
|
123 |
|
|
signal db_enable, b_point : std_logic;
|
124 |
|
|
signal imm : std_logic_vector(WORD_SIZE-1 downto 0);
|
125 |
|
|
signal r1_indir, r2_indir : std_logic; -- Indirection bits (set if indirect)
|
126 |
|
|
signal bmask_s, bflags_s : std_logic_vector(7 downto 0);
|
127 |
|
|
signal inst_r1_addr : std_logic_vector(SCRATCH_ADDR_SIZE-1 downto 0);--Reg1 addr
|
128 |
|
|
signal inst_r2_addr : std_logic_vector(SCRATCH_ADDR_SIZE-1 downto 0);--Reg2 addr
|
129 |
|
|
|
130 |
|
|
-- registers
|
131 |
|
|
signal pc : std_logic_vector(MC_ADDR_SIZE-1 downto 0) := (others => '0');
|
132 |
|
|
signal reg1 : std_logic_vector(SCRATCH_ADDR_SIZE-1 downto 0) := (others => '0');
|
133 |
|
|
signal reg2 : std_logic_vector(SCRATCH_ADDR_SIZE-1 downto 0) := (others => '0');
|
134 |
|
|
signal status : std_logic_vector(STATUS_REG_SIZE-1 downto 0) := (others => '0');
|
135 |
|
|
|
136 |
|
|
signal alu_op1_sel : std_logic;
|
137 |
|
|
signal write_indir_addr_wr_en : std_logic;
|
138 |
|
|
begin
|
139 |
|
|
-- -- DEBUG signals
|
140 |
|
|
-- status_out <= status;
|
141 |
|
|
-- pc_out <= pc;
|
142 |
|
|
-- pc_write_out <= pc_write_en;
|
143 |
|
|
led <= pc(7 downto 0);
|
144 |
|
|
|
145 |
|
|
-- map memory control signals outside
|
146 |
|
|
write <= write_s;
|
147 |
|
|
read <= read_s;
|
148 |
|
|
|
149 |
|
|
-- MUX for ALU immidiate/r2 value
|
150 |
|
|
alu_op1_val <= r2_value when alu_op1_sel = '1' else r1_value;
|
151 |
|
|
alu_op2_val <= imm when alu_op2_sel = '1' else r2_value;
|
152 |
|
|
|
153 |
|
|
-- MUXes for SCRATCH addresses, select either instruction
|
154 |
|
|
-- 's addreses or, if we're indirect, the indirect-regs
|
155 |
|
|
r1_addr <= reg1 when r1_in_mux = '1' else inst_r1_addr;
|
156 |
|
|
r2_addr <= reg2 when r2_in_mux = '1' else inst_r2_addr;
|
157 |
|
|
|
158 |
|
|
-- set data out
|
159 |
|
|
data_out <= r1_value;
|
160 |
|
|
|
161 |
|
|
-- MUX for result
|
162 |
|
|
wr_value <= data_in when mem_to_reg = '1' else alu_out;
|
163 |
|
|
|
164 |
|
|
-- Address bus
|
165 |
|
|
addr_bus <= alu_out(ADDR_SIZE-1 downto 0);
|
166 |
|
|
|
167 |
|
|
-- Split fetched instruction into sub-signals
|
168 |
|
|
opcode <= instr(47 downto 42); --opcode
|
169 |
|
|
db_enable <= instr(41); -- debug bit
|
170 |
|
|
b_point <= instr(40); -- break point bit
|
171 |
|
|
r1_indir <= instr(39); -- reg1 indirection bit
|
172 |
|
|
inst_r1_addr <= instr(38 downto 29); --reg1 address
|
173 |
|
|
r2_indir <= instr(28); -- reg2 indir bit
|
174 |
|
|
inst_r2_addr <= instr(27 downto 18); --reg2 address
|
175 |
|
|
imm <= "000000" & sign_extend_18_26(instr(17 downto 0));
|
176 |
|
|
-- Branch instruction signals (branch mask and branch flags)
|
177 |
|
|
bflags_s <= instr(20 downto 13);
|
178 |
|
|
bmask_s <= instr(28 downto 21);
|
179 |
|
|
|
180 |
|
|
scrmem : reg_mem
|
181 |
|
|
port map (
|
182 |
|
|
clk => clk,
|
183 |
|
|
we => scratch_we,
|
184 |
|
|
a => r1_addr,
|
185 |
|
|
b => r2_addr,
|
186 |
|
|
dia => wr_value,
|
187 |
|
|
doa => r1_value,
|
188 |
|
|
dob => r2_value);
|
189 |
|
|
|
190 |
|
|
alu_inst : alu
|
191 |
|
|
port map (
|
192 |
|
|
in_a => alu_op1_val,
|
193 |
|
|
in_b => alu_op2_val,
|
194 |
|
|
funct => alu_func,
|
195 |
|
|
status => alu_status,
|
196 |
|
|
output => alu_out);
|
197 |
|
|
|
198 |
|
|
instrmem : inst_mem
|
199 |
|
|
port map (
|
200 |
|
|
clk => clk,
|
201 |
|
|
addr => pc,
|
202 |
|
|
dout => instr,
|
203 |
|
|
din => "000000000000000000000000000000000000000000000000",
|
204 |
|
|
we => '0');
|
205 |
|
|
|
206 |
|
|
pc_incer_inst : pc_incer
|
207 |
|
|
port map (
|
208 |
|
|
clk => clk,
|
209 |
|
|
rst => rst,
|
210 |
|
|
pause => pc_write_en,
|
211 |
|
|
offset => alu_out(MC_ADDR_SIZE-1 downto 0),
|
212 |
|
|
branch => branch,
|
213 |
|
|
pc_next => pc);
|
214 |
|
|
|
215 |
|
|
control_unit : control
|
216 |
|
|
port map (
|
217 |
|
|
clk => clk,
|
218 |
|
|
rst => rst,
|
219 |
|
|
sync => sync,
|
220 |
|
|
status_in => status,
|
221 |
|
|
data_rdy=> wait_s,
|
222 |
|
|
opcode => opcode,
|
223 |
|
|
breakpoint=> b_point,
|
224 |
|
|
debug_en=> db_enable,
|
225 |
|
|
break_mask=> bmask_s,
|
226 |
|
|
break_flags=> bflags_s,
|
227 |
|
|
indir_reg1=> r1_indir,
|
228 |
|
|
indir_reg2=> r2_indir,
|
229 |
|
|
write_reg_en=> scratch_we,
|
230 |
|
|
alu_op1_sel => alu_op1_sel,
|
231 |
|
|
indir_reg1_sel => r1_in_mux,
|
232 |
|
|
indir_reg2_sel => r2_in_mux,
|
233 |
|
|
alu_func=> alu_func,
|
234 |
|
|
alu_op2_sel=> alu_op2_sel,
|
235 |
|
|
status_reg_w_en=> SRWriteEnable,
|
236 |
|
|
pc_write_en => pc_write_en,
|
237 |
|
|
branch_taken => branch,
|
238 |
|
|
write => write_s,
|
239 |
|
|
read => read_s,
|
240 |
|
|
mem_to_reg_sel => mem_to_reg,
|
241 |
|
|
write_indir_addr_wr_en => write_indir_addr_wr_en);
|
242 |
|
|
-- state_out => state_out);
|
243 |
|
|
|
244 |
|
|
-- update registers on rising clock edge
|
245 |
|
|
update_regs : process(clk, rst)
|
246 |
|
|
begin
|
247 |
|
|
if rising_edge(clk) then
|
248 |
|
|
-- update status register with status from alu masked by SRWriteEnable
|
249 |
|
|
status <= (status and (not SRWriteEnable)) or (SRWriteEnable and alu_status);
|
250 |
|
|
-- update addresses from indirect registers
|
251 |
|
|
if write_indir_addr_wr_en = '1' then
|
252 |
|
|
reg1 <= r1_value(SCRATCH_ADDR_SIZE - 1 downto 0);
|
253 |
|
|
reg2 <= r2_value(SCRATCH_ADDR_SIZE - 1 downto 0);
|
254 |
|
|
end if;
|
255 |
|
|
end if;
|
256 |
|
|
end process update_regs;
|
257 |
|
|
end rtl;
|