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

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_decode.vhd] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 ring0_mipt
---------------------------------------------------------------------
2
-- Instruction decoder
3
--
4
-- Part of the LXP32 CPU
5
--
6
-- Copyright (c) 2016 by Alex I. Kuznetsov
7
--
8
-- The second stage of the LXP32 pipeline.
9
---------------------------------------------------------------------
10
 
11
library ieee;
12
use ieee.std_logic_1164.all;
13
use ieee.numeric_std.all;
14
 
15
entity lxp32_decode is
16
        port(
17
                clk_i: in std_logic;
18
                rst_i: in std_logic;
19
 
20
                word_i: in std_logic_vector(31 downto 0);
21
                next_ip_i: in std_logic_vector(29 downto 0);
22
                current_ip_i: in std_logic_vector(29 downto 0);
23
                valid_i: in std_logic;
24
                jump_valid_i: in std_logic;
25
                ready_o: out std_logic;
26
 
27
                interrupt_valid_i: in std_logic;
28
                interrupt_vector_i: in std_logic_vector(2 downto 0);
29
                interrupt_ready_o: out std_logic;
30 12 ring0_mipt
 
31
                wakeup_i: in std_logic;
32 9 ring0_mipt
 
33
                sp_raddr1_o: out std_logic_vector(7 downto 0);
34
                sp_rdata1_i: in std_logic_vector(31 downto 0);
35
                sp_raddr2_o: out std_logic_vector(7 downto 0);
36
                sp_rdata2_i: in std_logic_vector(31 downto 0);
37
 
38
                ready_i: in std_logic;
39
                valid_o: out std_logic;
40
 
41
                cmd_loadop3_o: out std_logic;
42
                cmd_signed_o: out std_logic;
43
                cmd_dbus_o: out std_logic;
44
                cmd_dbus_store_o: out std_logic;
45
                cmd_dbus_byte_o: out std_logic;
46
                cmd_addsub_o: out std_logic;
47
                cmd_mul_o: out std_logic;
48
                cmd_div_o: out std_logic;
49
                cmd_div_mod_o: out std_logic;
50
                cmd_cmp_o: out std_logic;
51
                cmd_jump_o: out std_logic;
52
                cmd_negate_op2_o: out std_logic;
53
                cmd_and_o: out std_logic;
54
                cmd_xor_o: out std_logic;
55
                cmd_shift_o: out std_logic;
56
                cmd_shift_right_o: out std_logic;
57
 
58
                jump_type_o: out std_logic_vector(3 downto 0);
59
 
60
                op1_o: out std_logic_vector(31 downto 0);
61
                op2_o: out std_logic_vector(31 downto 0);
62
                op3_o: out std_logic_vector(31 downto 0);
63
                dst_o: out std_logic_vector(7 downto 0)
64
        );
65
end entity;
66
 
67
architecture rtl of lxp32_decode is
68
 
69
-- Decoder FSM state
70
 
71
type DecoderState is (Regular,ContinueLc,ContinueCjmp,ContinueInterrupt,Halt);
72
signal state: DecoderState:=Regular;
73
 
74
-- Input instruction portions
75
 
76
signal opcode: std_logic_vector(5 downto 0);
77
signal t1: std_logic;
78
signal t2: std_logic;
79
signal destination: std_logic_vector(7 downto 0);
80
signal rd1: std_logic_vector(7 downto 0);
81
signal rd2: std_logic_vector(7 downto 0);
82
 
83
-- Signals related to pipeline control
84
 
85
signal downstream_busy: std_logic;
86
signal self_busy: std_logic:='0';
87
signal busy: std_logic;
88
signal valid_out: std_logic:='0';
89
 
90
signal dst_out: std_logic_vector(7 downto 0);
91
 
92
-- Signals related to RD operand decoding
93
 
94
signal rd1_reg: std_logic_vector(7 downto 0);
95
signal rd2_reg: std_logic_vector(7 downto 0);
96
 
97
signal rd1_select: std_logic;
98
signal rd1_direct: std_logic_vector(31 downto 0);
99
signal rd2_select: std_logic;
100
signal rd2_direct: std_logic_vector(31 downto 0);
101
 
102
-- Signals related to interrupt handling
103
 
104
signal interrupt_ready: std_logic:='0';
105 12 ring0_mipt
signal wakeup_reg: std_logic:='0';
106 9 ring0_mipt
 
107
begin
108
 
109
-- Dissect input word
110
 
111
opcode<=word_i(31 downto 26);
112
t1<=word_i(25);
113
t2<=word_i(24);
114
destination<=word_i(23 downto 16);
115
rd1<=word_i(15 downto 8);
116
rd2<=word_i(7 downto 0);
117
 
118
-- Pipeline control
119
 
120
downstream_busy<=valid_out and not ready_i;
121
busy<=downstream_busy or self_busy;
122
 
123
process (clk_i) is
124
begin
125
        if rising_edge(clk_i) then
126
                if rst_i='1' then
127
                        valid_out<='0';
128
                        self_busy<='0';
129
                        state<=Regular;
130
                        interrupt_ready<='0';
131
                        cmd_loadop3_o<='-';
132
                        cmd_signed_o<='-';
133
                        cmd_dbus_o<='-';
134
                        cmd_dbus_store_o<='-';
135
                        cmd_dbus_byte_o<='-';
136
                        cmd_addsub_o<='-';
137
                        cmd_negate_op2_o<='-';
138
                        cmd_mul_o<='-';
139
                        cmd_div_o<='-';
140
                        cmd_div_mod_o<='-';
141
                        cmd_cmp_o<='-';
142
                        cmd_jump_o<='-';
143
                        cmd_and_o<='-';
144
                        cmd_xor_o<='-';
145
                        cmd_shift_o<='-';
146
                        cmd_shift_right_o<='-';
147
                        rd1_select<='-';
148
                        rd1_direct<=(others=>'-');
149
                        rd2_select<='-';
150
                        rd2_direct<=(others=>'-');
151
                        op3_o<=(others=>'-');
152
                        jump_type_o<=(others=>'-');
153
                        dst_out<=(others=>'-');
154 12 ring0_mipt
                        wakeup_reg<='0';
155 9 ring0_mipt
                else
156
                        interrupt_ready<='0';
157 12 ring0_mipt
                        wakeup_reg<=wakeup_reg or wakeup_i;
158 9 ring0_mipt
                        if jump_valid_i='1' then
159
                                valid_out<='0';
160
                                self_busy<='0';
161
                                state<=Regular;
162
                        elsif downstream_busy='0' then
163
                                op3_o<=(others=>'-');
164
                                rd1_direct<=std_logic_vector(resize(signed(rd1),rd1_direct'length));
165
                                rd2_direct<=std_logic_vector(resize(signed(rd2),rd2_direct'length));
166
 
167
                                cmd_signed_o<=opcode(0);
168
                                cmd_div_mod_o<=opcode(1);
169
                                cmd_shift_right_o<=opcode(1);
170
                                cmd_dbus_byte_o<=opcode(1);
171
                                cmd_dbus_store_o<=opcode(2);
172
 
173
                                case state is
174
                                when Regular =>
175
                                        cmd_loadop3_o<='0';
176
                                        cmd_dbus_o<='0';
177
                                        cmd_addsub_o<='0';
178
                                        cmd_negate_op2_o<='0';
179
                                        cmd_mul_o<='0';
180
                                        cmd_div_o<='0';
181
                                        cmd_cmp_o<='0';
182
                                        cmd_jump_o<='0';
183
                                        cmd_and_o<='0';
184
                                        cmd_xor_o<='0';
185
                                        cmd_shift_o<='0';
186
 
187
                                        jump_type_o<=opcode(3 downto 0);
188
 
189
                                        if interrupt_valid_i='1' and valid_i='1' then
190
                                                cmd_jump_o<='1';
191
                                                cmd_loadop3_o<='1';
192
                                                op3_o<=current_ip_i&"01"; -- LSB indicates interrupt return
193
                                                dst_out<=X"FD"; -- interrupt return pointer
194
                                                rd1_select<='1';
195
                                                rd2_select<='0';
196
                                                valid_out<='1';
197
                                                interrupt_ready<='1';
198
                                                self_busy<='1';
199
                                                state<=ContinueInterrupt;
200
                                        else
201
                                                if opcode(5 downto 3)="101" or opcode="000001" then -- lc or lcs
202
                                                        cmd_loadop3_o<='1';
203
-- Setting op3_o here only affects the lcs instruction
204
                                                        op3_o<=std_logic_vector(resize(signed(opcode(2 downto 0)&
205
                                                                t1&t2&rd1&rd2),op3_o'length));
206
                                                end if;
207
 
208
                                                if opcode(5 downto 3)="001" then
209
                                                        cmd_dbus_o<='1';
210
                                                end if;
211
 
212
                                                if opcode(5 downto 1)="01000" then
213
                                                        cmd_addsub_o<='1';
214
                                                end if;
215
 
216
                                                cmd_negate_op2_o<=opcode(0);
217
 
218
                                                if opcode="010010" then
219
                                                        cmd_mul_o<='1';
220
                                                end if;
221
 
222
                                                if opcode(5 downto 2)="0101" then
223
                                                        cmd_div_o<='1';
224
                                                end if;
225
 
226
                                                if opcode(5 downto 3)="100" then -- jump or call
227
                                                        cmd_jump_o<='1';
228
                                                        cmd_loadop3_o<=opcode(0);
229
-- Setting op3_o here only affects the call instruction
230
                                                        op3_o<=next_ip_i&"00";
231
                                                end if;
232
 
233
                                                -- Note: (a or b) = (a and b) or (a xor b)
234
 
235
                                                if opcode(5 downto 1)="01100" then
236
                                                        cmd_and_o<='1';
237
                                                end if;
238
 
239
                                                if opcode="011010" or opcode="011001" then
240
                                                        cmd_xor_o<='1';
241
                                                end if;
242
 
243
                                                if opcode(5 downto 2)="0111" then
244
                                                        cmd_shift_o<='1';
245
                                                end if;
246
 
247
                                                if opcode(5 downto 4)="11" then
248
                                                        cmd_cmp_o<='1';
249
                                                        cmd_negate_op2_o<='1';
250
                                                end if;
251
 
252
                                                rd1_select<=t1;
253
                                                rd2_select<=t2;
254
 
255
                                                dst_out<=destination;
256
 
257
                                                if valid_i='1' then
258
                                                        if opcode="000001" then
259
                                                                valid_out<='0';
260
                                                                self_busy<='0';
261
                                                                state<=ContinueLc;
262
                                                        elsif opcode="000010" then
263
                                                                valid_out<='0';
264
                                                                self_busy<='1';
265 12 ring0_mipt
                                                                wakeup_reg<='0';
266 9 ring0_mipt
                                                                state<=Halt;
267
                                                        elsif opcode(5 downto 4)="11" then
268
                                                                valid_out<='1';
269
                                                                self_busy<='1';
270
                                                                state<=ContinueCjmp;
271
                                                        else
272
                                                                valid_out<='1';
273
                                                        end if;
274
                                                else
275
                                                        valid_out<='0';
276
                                                end if;
277
                                        end if;
278
                                when ContinueLc =>
279
                                        if valid_i='1' then
280
                                                valid_out<='1';
281
                                                op3_o<=word_i;
282
                                                self_busy<='0';
283
                                                state<=Regular;
284
                                        end if;
285
                                when ContinueCjmp =>
286
                                        valid_out<='1';
287
                                        cmd_jump_o<='1';
288
                                        rd1_select<='1';
289
                                        self_busy<='0';
290
                                        state<=Regular;
291
                                when ContinueInterrupt =>
292
                                        valid_out<='0';
293
                                when Halt =>
294 12 ring0_mipt
                                        if interrupt_valid_i='1' or wakeup_i='1' or wakeup_reg='1' then
295 9 ring0_mipt
                                                self_busy<='0';
296
                                                state<=Regular;
297
                                        end if;
298
                                end case;
299
                        end if;
300
                end if;
301
        end if;
302
end process;
303
 
304
valid_o<=valid_out;
305
dst_o<=dst_out;
306
 
307
ready_o<=not busy;
308
 
309
interrupt_ready_o<=interrupt_ready;
310
 
311
-- Decode RD (register/direct) operands
312
 
313
process (clk_i) is
314
begin
315
        if rising_edge(clk_i) then
316
                if busy='0' then
317
                        rd1_reg<=rd1;
318
                        rd2_reg<=rd2;
319
                end if;
320
        end if;
321
end process;
322
 
323
sp_raddr1_o<="11110"&interrupt_vector_i when (state=Regular and interrupt_valid_i='1' and downstream_busy='0') or state=ContinueInterrupt else
324
        dst_out when (state=ContinueCjmp and downstream_busy='0') else
325
        rd1_reg when busy='1' else
326
        rd1;
327
 
328
sp_raddr2_o<=rd2_reg when busy='1' else rd2;
329
 
330
op1_o<=sp_rdata1_i when rd1_select='1' else rd1_direct;
331
op2_o<=sp_rdata2_i when rd2_select='1' else rd2_direct;
332
 
333
end architecture;

powered by: WebSVN 2.1.0

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