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

Subversion Repositories lxp32

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 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
                valid_i: in std_logic;
23
                jump_valid_i: in std_logic;
24
                ready_o: out std_logic;
25
 
26
                interrupt_valid_i: in std_logic;
27
                interrupt_vector_i: in std_logic_vector(2 downto 0);
28
                interrupt_ready_o: out std_logic;
29
 
30
                sp_raddr1_o: out std_logic_vector(7 downto 0);
31
                sp_rdata1_i: in std_logic_vector(31 downto 0);
32
                sp_raddr2_o: out std_logic_vector(7 downto 0);
33
                sp_rdata2_i: in std_logic_vector(31 downto 0);
34
 
35
                ready_i: in std_logic;
36
                valid_o: out std_logic;
37
 
38
                cmd_loadop3_o: out std_logic;
39
                cmd_signed_o: out std_logic;
40
                cmd_dbus_o: out std_logic;
41
                cmd_dbus_store_o: out std_logic;
42
                cmd_dbus_byte_o: out std_logic;
43
                cmd_addsub_o: out std_logic;
44
                cmd_mul_o: out std_logic;
45
                cmd_div_o: out std_logic;
46
                cmd_div_mod_o: out std_logic;
47
                cmd_cmp_o: out std_logic;
48
                cmd_jump_o: out std_logic;
49
                cmd_negate_op2_o: out std_logic;
50
                cmd_and_o: out std_logic;
51
                cmd_or_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
signal current_ip: unsigned(next_ip_i'range);
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
 
106
begin
107
 
108
-- Dissect input word
109
 
110
opcode<=word_i(31 downto 26);
111
t1<=word_i(25);
112
t2<=word_i(24);
113
destination<=word_i(23 downto 16);
114
rd1<=word_i(15 downto 8);
115
rd2<=word_i(7 downto 0);
116
 
117
-- Pipeline control
118
 
119
downstream_busy<=valid_out and not ready_i;
120
busy<=downstream_busy or self_busy;
121
 
122
current_ip<=unsigned(next_ip_i)-1;
123
 
124
process (clk_i) is
125
begin
126
        if rising_edge(clk_i) then
127
                if rst_i='1' then
128
                        valid_out<='0';
129
                        self_busy<='0';
130
                        state<=Regular;
131
                        interrupt_ready<='0';
132
                else
133
                        interrupt_ready<='0';
134
                        if jump_valid_i='1' then
135
                                valid_out<='0';
136
                                self_busy<='0';
137
                                state<=Regular;
138
                        elsif downstream_busy='0' then
139
                                case state is
140
                                when Regular =>
141
                                        cmd_loadop3_o<='0';
142
                                        cmd_signed_o<='0';
143
                                        cmd_dbus_o<='0';
144
                                        cmd_dbus_store_o<='0';
145
                                        cmd_dbus_byte_o<='0';
146
                                        cmd_addsub_o<='0';
147
                                        cmd_negate_op2_o<='0';
148
                                        cmd_mul_o<='0';
149
                                        cmd_div_o<='0';
150
                                        cmd_div_mod_o<='0';
151
                                        cmd_cmp_o<='0';
152
                                        cmd_jump_o<='0';
153
                                        cmd_and_o<='0';
154
                                        cmd_or_o<='0';
155
                                        cmd_xor_o<='0';
156
                                        cmd_shift_o<='0';
157
                                        cmd_shift_right_o<='0';
158
 
159
                                        op3_o<=(others=>'-');
160
 
161
                                        jump_type_o<=opcode(3 downto 0);
162
 
163
                                        if interrupt_valid_i='1' and valid_i='1' then
164
                                                cmd_jump_o<='1';
165
                                                cmd_loadop3_o<='1';
166
                                                op3_o<=std_logic_vector(current_ip)&"01"; -- LSB indicates interrupt return
167
                                                dst_out<=X"FD"; -- interrupt return pointer
168
                                                rd1_select<='1';
169
                                                rd2_select<='0';
170
                                                valid_out<='1';
171
                                                interrupt_ready<='1';
172
                                                self_busy<='1';
173
                                                state<=ContinueInterrupt;
174
                                        else
175
                                                if opcode="000001" then
176
                                                        cmd_loadop3_o<='1';
177
                                                end if;
178
 
179
                                                cmd_signed_o<=opcode(0);
180
 
181
                                                if opcode(5 downto 3)="001" then
182
                                                        cmd_dbus_o<='1';
183
                                                end if;
184
 
185
                                                cmd_dbus_store_o<=opcode(2);
186
                                                cmd_dbus_byte_o<=opcode(1);
187
 
188
                                                if opcode(5 downto 1)="01000" then
189
                                                        cmd_addsub_o<='1';
190
                                                end if;
191
 
192
                                                cmd_negate_op2_o<=opcode(0);
193
 
194
                                                if opcode="010010" then
195
                                                        cmd_mul_o<='1';
196
                                                end if;
197
 
198
                                                if opcode(5 downto 2)="0101" then
199
                                                        cmd_div_o<='1';
200
                                                end if;
201
 
202
                                                cmd_div_mod_o<=opcode(1);
203
 
204
                                                if opcode="100000" then
205
                                                        cmd_jump_o<='1';
206
                                                end if;
207
 
208
                                                if opcode="100001" then
209
                                                        cmd_jump_o<='1';
210
                                                        cmd_loadop3_o<='1';
211
                                                        op3_o<=next_ip_i&"00";
212
                                                end if;
213
 
214
                                                if opcode="011000" then
215
                                                        cmd_and_o<='1';
216
                                                end if;
217
 
218
                                                if opcode="011001" then
219
                                                        cmd_or_o<='1';
220
                                                end if;
221
 
222
                                                if opcode="011010" then
223
                                                        cmd_xor_o<='1';
224
                                                end if;
225
 
226
                                                if opcode(5 downto 2)="0111" then
227
                                                        cmd_shift_o<='1';
228
                                                end if;
229
 
230
                                                cmd_shift_right_o<=opcode(1);
231
 
232
                                                if opcode(5 downto 4)="11" then
233
                                                        cmd_cmp_o<='1';
234
                                                        cmd_negate_op2_o<='1';
235
                                                end if;
236
 
237
                                                rd1_select<=t1;
238
                                                rd1_direct<=std_logic_vector(resize(signed(rd1),rd1_direct'length));
239
                                                rd2_select<=t2;
240
                                                rd2_direct<=std_logic_vector(resize(signed(rd2),rd2_direct'length));
241
 
242
                                                dst_out<=destination;
243
 
244
                                                if valid_i='1' then
245
                                                        if opcode="000001" then
246
                                                                valid_out<='0';
247
                                                                self_busy<='0';
248
                                                                state<=ContinueLc;
249
                                                        elsif opcode="000010" then
250
                                                                valid_out<='0';
251
                                                                self_busy<='1';
252
                                                                state<=Halt;
253
                                                        elsif opcode(5 downto 4)="11" then
254
                                                                valid_out<='1';
255
                                                                self_busy<='1';
256
                                                                state<=ContinueCjmp;
257
                                                        else
258
                                                                valid_out<='1';
259
                                                        end if;
260
                                                else
261
                                                        valid_out<='0';
262
                                                end if;
263
                                        end if;
264
                                when ContinueLc =>
265
                                        if valid_i='1' then
266
                                                valid_out<='1';
267
                                                op3_o<=word_i;
268
                                                self_busy<='0';
269
                                                state<=Regular;
270
                                        end if;
271
                                when ContinueCjmp =>
272
                                        valid_out<='1';
273
                                        cmd_jump_o<='1';
274
                                        rd1_select<='1';
275
                                        self_busy<='0';
276
                                        state<=Regular;
277
                                when ContinueInterrupt =>
278
                                        valid_out<='0';
279
                                when Halt =>
280
                                        if interrupt_valid_i='1' then
281
                                                self_busy<='0';
282
                                                state<=Regular;
283
                                        end if;
284
                                end case;
285
                        end if;
286
                end if;
287
        end if;
288
end process;
289
 
290
valid_o<=valid_out;
291
dst_o<=dst_out;
292
 
293
ready_o<=not busy;
294
 
295
interrupt_ready_o<=interrupt_ready;
296
 
297
-- Decode RD (register/direct) operands
298
 
299
process (clk_i) is
300
begin
301
        if rising_edge(clk_i) then
302
                if busy='0' then
303
                        rd1_reg<=rd1;
304
                        rd2_reg<=rd2;
305
                end if;
306
        end if;
307
end process;
308
 
309
sp_raddr1_o<="11110"&interrupt_vector_i when (state=Regular and interrupt_valid_i='1' and downstream_busy='0') or state=ContinueInterrupt else
310
        dst_out when (state=ContinueCjmp and downstream_busy='0') else
311
        rd1_reg when busy='1' else
312
        rd1;
313
 
314
sp_raddr2_o<=rd2_reg when busy='1' else rd2;
315
 
316
op1_o<=sp_rdata1_i when rd1_select='1' else rd1_direct;
317
op2_o<=sp_rdata2_i when rd2_select='1' else rd2_direct;
318
 
319
end architecture;

powered by: WebSVN 2.1.0

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