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

Subversion Repositories lxp32

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

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

powered by: WebSVN 2.1.0

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