]> rtime.felk.cvut.cz Git - fpga/openmsp430.git/blob - core/omsp_frontend.v
OpenMSP430 core verilog source files moved to "core" subdirectory.
[fpga/openmsp430.git] / core / omsp_frontend.v
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2001 Authors
3 //
4 // This source file may be used and distributed without restriction provided
5 // that this copyright statement is not removed from the file and that any
6 // derivative work contains the original copyright notice and the associated
7 // disclaimer.
8 //
9 // This source file is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU Lesser General Public License as published
11 // by the Free Software Foundation; either version 2.1 of the License, or
12 // (at your option) any later version.
13 //
14 // This source is distributed in the hope that it will be useful, but WITHOUT
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with this source; if not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 //----------------------------------------------------------------------------
24 //
25 // *File Name: omsp_frontend.v
26 // 
27 // *Module Description:
28 //                       openMSP430 Instruction fetch and decode unit
29 //
30 // *Author(s):
31 //              - Olivier Girard,    olgirard@gmail.com
32 //
33 //----------------------------------------------------------------------------
34 // $Rev: 60 $
35 // $LastChangedBy: olivier.girard $
36 // $LastChangedDate: 2010-02-03 22:12:25 +0100 (Wed, 03 Feb 2010) $
37 //----------------------------------------------------------------------------
38 `include "timescale.v"
39 `include "openMSP430_defines.v"
40
41 module  omsp_frontend (
42
43 // OUTPUTs
44     dbg_halt_st,                   // Halt/Run status from CPU
45     decode_noirq,                  // Frontend decode instruction
46     e_state,                       // Execution state
47     exec_done,                     // Execution completed
48     inst_ad,                       // Decoded Inst: destination addressing mode
49     inst_as,                       // Decoded Inst: source addressing mode
50     inst_alu,                      // ALU control signals
51     inst_bw,                       // Decoded Inst: byte width
52     inst_dest,                     // Decoded Inst: destination (one hot)
53     inst_dext,                     // Decoded Inst: destination extended instruction word
54     inst_irq_rst,                  // Decoded Inst: Reset interrupt
55     inst_jmp,                      // Decoded Inst: Conditional jump
56     inst_sext,                     // Decoded Inst: source extended instruction word
57     inst_so,                       // Decoded Inst: Single-operand arithmetic
58     inst_src,                      // Decoded Inst: source (one hot)
59     inst_type,                     // Decoded Instruction type
60     irq_acc,                       // Interrupt request accepted (one-hot signal)
61     mab,                           // Frontend Memory address bus
62     mb_en,                         // Frontend Memory bus enable
63     nmi_acc,                       // Non-Maskable interrupt request accepted
64     pc,                            // Program counter
65     pc_nxt,                        // Next PC value (for CALL & IRQ)
66
67 // INPUTs
68     cpuoff,                        // Turns off the CPU
69     dbg_halt_cmd,                  // Halt CPU command
70     dbg_reg_sel,                   // Debug selected register for rd/wr access
71     fe_pmem_wait,                  // Frontend wait for Instruction fetch
72     gie,                           // General interrupt enable
73     irq,                           // Maskable interrupts
74     mclk,                          // Main system clock
75     mdb_in,                        // Frontend Memory data bus input
76     nmi_evt,                       // Non-maskable interrupt event
77     pc_sw,                         // Program counter software value
78     pc_sw_wr,                      // Program counter software write
79     puc,                           // Main system reset
80     wdt_irq                        // Watchdog-timer interrupt
81 );
82
83 // OUTPUTs
84 //=========
85 output              dbg_halt_st;   // Halt/Run status from CPU
86 output              decode_noirq;  // Frontend decode instruction
87 output        [3:0] e_state;       // Execution state
88 output              exec_done;     // Execution completed
89 output        [7:0] inst_ad;       // Decoded Inst: destination addressing mode
90 output        [7:0] inst_as;       // Decoded Inst: source addressing mode
91 output       [11:0] inst_alu;      // ALU control signals
92 output              inst_bw;       // Decoded Inst: byte width
93 output       [15:0] inst_dest;     // Decoded Inst: destination (one hot)
94 output       [15:0] inst_dext;     // Decoded Inst: destination extended instruction word
95 output              inst_irq_rst;  // Decoded Inst: Reset interrupt
96 output        [7:0] inst_jmp;      // Decoded Inst: Conditional jump
97 output       [15:0] inst_sext;     // Decoded Inst: source extended instruction word
98 output        [7:0] inst_so;       // Decoded Inst: Single-operand arithmetic
99 output       [15:0] inst_src;      // Decoded Inst: source (one hot)
100 output        [2:0] inst_type;     // Decoded Instruction type
101 output       [13:0] irq_acc;       // Interrupt request accepted (one-hot signal)
102 output       [15:0] mab;           // Frontend Memory address bus
103 output              mb_en;         // Frontend Memory bus enable
104 output              nmi_acc;       // Non-Maskable interrupt request accepted
105 output       [15:0] pc;            // Program counter
106 output       [15:0] pc_nxt;        // Next PC value (for CALL & IRQ)
107
108 // INPUTs
109 //=========
110 input               cpuoff;        // Turns off the CPU
111 input               dbg_halt_cmd;  // Halt CPU command
112 input         [3:0] dbg_reg_sel;   // Debug selected register for rd/wr access
113 input               fe_pmem_wait;  // Frontend wait for Instruction fetch
114 input               gie;           // General interrupt enable
115 input        [13:0] irq;           // Maskable interrupts
116 input               mclk;          // Main system clock
117 input        [15:0] mdb_in;        // Frontend Memory data bus input
118 input               nmi_evt;       // Non-maskable interrupt event
119 input        [15:0] pc_sw;         // Program counter software value
120 input               pc_sw_wr;      // Program counter software write
121 input               puc;           // Main system reset
122 input               wdt_irq;       // Watchdog-timer interrupt
123
124
125 //=============================================================================
126 // 1)  FRONTEND STATE MACHINE
127 //=============================================================================
128
129 // The wire "conv" is used as state bits to calculate the next response
130 reg  [2:0] i_state;
131 reg  [2:0] i_state_nxt;
132
133 reg  [1:0] inst_sz;
134 wire [1:0] inst_sz_nxt;
135 wire       irq_detect;
136 wire [2:0] inst_type_nxt;
137 wire       is_const;
138 reg [15:0] sconst_nxt;
139 reg  [3:0] e_state_nxt;
140            
141 // State machine definitons
142 parameter I_IRQ_FETCH = 3'h0;
143 parameter I_IRQ_DONE  = 3'h1;
144 parameter I_DEC       = 3'h2; // New instruction ready for decode
145 parameter I_EXT1      = 3'h3; // 1st Extension word
146 parameter I_EXT2      = 3'h4; // 2nd Extension word
147 parameter I_IDLE      = 3'h5; // CPU is in IDLE mode
148
149 // States Transitions
150 always @(i_state   or inst_sz    or inst_sz_nxt or pc_sw_wr     or exec_done or
151          exec_done or irq_detect or cpuoff      or dbg_halt_cmd or e_state)
152     case(i_state)
153       I_IDLE     : i_state_nxt = (irq_detect & ~dbg_halt_cmd) ? I_IRQ_FETCH :
154                                  (~cpuoff    & ~dbg_halt_cmd) ? I_DEC       : I_IDLE;
155       I_IRQ_FETCH: i_state_nxt =  I_IRQ_DONE;
156       I_IRQ_DONE : i_state_nxt =  I_DEC;
157       I_DEC      : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
158                           (cpuoff | dbg_halt_cmd) & exec_done ? I_IDLE      :
159                             dbg_halt_cmd & (e_state==`E_IDLE) ? I_IDLE      :
160                                   pc_sw_wr                    ? I_DEC       :
161                              ~exec_done & ~(e_state==`E_IDLE) ? I_DEC       :        // Wait in decode state
162                                   (inst_sz_nxt!=2'b00)        ? I_EXT1      : I_DEC; // until execution is completed
163       I_EXT1     : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
164                                   pc_sw_wr                    ? I_DEC       : 
165                                   (inst_sz!=2'b01)            ? I_EXT2      : I_DEC;
166       I_EXT2     : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH : I_DEC;
167       default    : i_state_nxt =  I_IRQ_FETCH;
168     endcase
169
170 // State machine
171 always @(posedge mclk or posedge puc)
172   if (puc) i_state  <= I_IRQ_FETCH;
173   else     i_state  <= i_state_nxt;
174
175 // Utility signals
176 wire   decode_noirq =  ((i_state==I_DEC) &  (exec_done | (e_state==`E_IDLE)));
177 wire   decode       =  decode_noirq | irq_detect;
178 wire   fetch        = ~((i_state==I_DEC) & ~(exec_done | (e_state==`E_IDLE))) & ~(e_state_nxt==`E_IDLE);
179
180 // Debug interface cpu status
181 reg    dbg_halt_st;
182 always @(posedge mclk or posedge puc)
183   if (puc)  dbg_halt_st <= 1'b0;
184   else      dbg_halt_st <= dbg_halt_cmd & (i_state_nxt==I_IDLE);
185
186
187 //=============================================================================
188 // 2)  INTERRUPT HANDLING
189 //=============================================================================
190
191 // Detect nmi interrupt
192 reg         inst_nmi;
193 always @(posedge mclk or posedge puc)
194   if (puc)                      inst_nmi <= 1'b0;
195   else if (nmi_evt)             inst_nmi <= 1'b1;
196   else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0;
197
198
199 // Detect reset interrupt
200 reg         inst_irq_rst;
201 always @(posedge mclk or posedge puc)
202   if (puc)                      inst_irq_rst <= 1'b1;
203   else if (exec_done)           inst_irq_rst <= 1'b0;
204
205 //  Detect other interrupts
206 assign  irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~dbg_halt_cmd & (exec_done | (i_state==I_IDLE));
207
208 // Select interrupt vector
209 reg  [3:0] irq_num;
210 always @(posedge mclk or posedge puc)
211   if (puc)             irq_num <= 4'hf;
212   else if (irq_detect) irq_num <= inst_nmi           ?  4'he :
213                                   irq[13]            ?  4'hd :
214                                   irq[12]            ?  4'hc :
215                                   irq[11]            ?  4'hb :
216                                  (irq[10] | wdt_irq) ?  4'ha :
217                                   irq[9]             ?  4'h9 :
218                                   irq[8]             ?  4'h8 :
219                                   irq[7]             ?  4'h7 :
220                                   irq[6]             ?  4'h6 :
221                                   irq[5]             ?  4'h5 :
222                                   irq[4]             ?  4'h4 :
223                                   irq[3]             ?  4'h3 :
224                                   irq[2]             ?  4'h2 :
225                                   irq[1]             ?  4'h1 :
226                                   irq[0]             ?  4'h0 : 4'hf;
227
228 wire [15:0] irq_addr    = {11'h7ff, irq_num, 1'b0};
229
230 // Interrupt request accepted
231 wire [15:0] irq_acc_all = (16'h0001 << irq_num) & {16{(i_state==I_IRQ_FETCH)}};
232 wire [13:0] irq_acc     = irq_acc_all[13:0];
233 wire        nmi_acc     = irq_acc_all[14];
234
235
236 //=============================================================================
237 // 3)  FETCH INSTRUCTION
238 //=============================================================================
239
240 //
241 // 3.1) PROGRAM COUNTER & MEMORY INTERFACE
242 //-----------------------------------------
243
244 // Program counter
245 reg  [15:0] pc;
246
247 // Compute next PC value
248 wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
249 wire [15:0] pc_nxt  = pc_sw_wr               ? pc_sw    :
250                       (i_state==I_IRQ_FETCH) ? irq_addr :
251                       (i_state==I_IRQ_DONE)  ? mdb_in   :  pc_incr;
252
253 always @(posedge mclk or posedge puc)
254   if (puc)  pc <= 16'h0000;
255   else      pc <= pc_nxt;
256
257 // Check if ROM has been busy in order to retry ROM access
258 reg pmem_busy;
259 always @(posedge mclk or posedge puc)
260   if (puc)  pmem_busy <= 16'h0000;
261   else      pmem_busy <= fe_pmem_wait;
262    
263 // Memory interface
264 wire [15:0] mab      = pc_nxt;
265 wire        mb_en    = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~dbg_halt_cmd);
266
267
268 //
269 // 3.2) INSTRUCTION REGISTER
270 //--------------------------------
271
272 // Instruction register
273 wire [15:0] ir  = mdb_in;
274
275 // Detect if source extension word is required
276 wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);
277
278 // Detect if destination extension word is required
279 wire is_dext = (inst_ad[`IDX] | inst_ad[`SYMB] | inst_ad[`ABS]);
280
281 // For the Symbolic addressing mode, add -2 to the extension word in order
282 // to make up for the PC address
283 wire [15:0] ext_incr = ((i_state==I_EXT1)     &  inst_as[`SYMB]) |
284                        ((i_state==I_EXT2)     &  inst_ad[`SYMB]) |
285                        ((i_state==I_EXT1)     & ~inst_as[`SYMB] &
286                        ~(i_state_nxt==I_EXT2) &  inst_ad[`SYMB])   ? 16'hfffe : 16'h0000;
287
288 wire [15:0] ext_nxt  = ir + ext_incr;
289
290 // Store source extension word
291 reg [15:0] inst_sext;
292 always @(posedge mclk or posedge puc)
293   if (puc)                                     inst_sext <= 16'h0000;
294   else if (decode & is_const)                  inst_sext <= sconst_nxt;
295   else if (decode & inst_type_nxt[`INST_JMP])  inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
296   else if ((i_state==I_EXT1) & is_sext)        inst_sext <= ext_nxt;
297
298 // Source extension word is ready
299 wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;
300
301
302 // Store destination extension word
303 reg [15:0] inst_dext;
304 always @(posedge mclk or posedge puc)
305   if (puc)                               inst_dext <= 16'h0000;
306   else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
307   else if  (i_state==I_EXT2)             inst_dext <= ext_nxt;
308
309 // Destination extension word is ready
310 wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));
311
312
313 //=============================================================================
314 // 4)  DECODE INSTRUCTION
315 //=============================================================================
316
317 //
318 // 4.1) OPCODE: INSTRUCTION TYPE
319 //----------------------------------------
320 // Instructions type is encoded in a one hot fashion as following:
321 //
322 // 3'b001: Single-operand arithmetic
323 // 3'b010: Conditional jump
324 // 3'b100: Two-operand arithmetic
325
326 reg  [2:0] inst_type;
327 assign     inst_type_nxt = {(ir[15:14]!=2'b00),
328                             (ir[15:13]==3'b001),
329                             (ir[15:13]==3'b000)} & {3{~irq_detect}};
330    
331 always @(posedge mclk or posedge puc)
332   if (puc)                      inst_type <= 3'b000;
333   else if (decode)              inst_type <= inst_type_nxt;
334
335 //
336 // 4.2) OPCODE: SINGLE-OPERAND ARITHMETIC
337 //----------------------------------------
338 // Instructions are encoded in a one hot fashion as following:
339 //
340 // 8'b00000001: RRC
341 // 8'b00000010: SWPB
342 // 8'b00000100: RRA
343 // 8'b00001000: SXT
344 // 8'b00010000: PUSH
345 // 8'b00100000: CALL
346 // 8'b01000000: RETI
347 // 8'b10000000: IRQ
348
349 reg   [7:0] inst_so;
350 wire  [7:0] inst_so_nxt = irq_detect ? 8'h80 : ((8'h01<<ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});
351
352 always @(posedge mclk or posedge puc)
353   if (puc)         inst_so <= 8'h00;
354   else if (decode) inst_so <= inst_so_nxt;
355
356 //
357 // 4.3) OPCODE: CONDITIONAL JUMP
358 //--------------------------------
359 // Instructions are encoded in a one hot fashion as following:
360 //
361 // 8'b00000001: JNE/JNZ
362 // 8'b00000010: JEQ/JZ
363 // 8'b00000100: JNC/JLO
364 // 8'b00001000: JC/JHS
365 // 8'b00010000: JN
366 // 8'b00100000: JGE
367 // 8'b01000000: JL
368 // 8'b10000000: JMP
369
370 reg   [2:0] inst_jmp_bin;
371 always @(posedge mclk or posedge puc)
372   if (puc)         inst_jmp_bin <= 3'h0;
373   else if (decode) inst_jmp_bin <= ir[12:10];
374
375 wire [7:0] inst_jmp = (8'h01<<inst_jmp_bin) & {8{inst_type[`INST_JMP]}};
376
377
378 //
379 // 4.4) OPCODE: TWO-OPERAND ARITHMETIC
380 //-------------------------------------
381 // Instructions are encoded in a one hot fashion as following:
382 //
383 // 12'b000000000001: MOV
384 // 12'b000000000010: ADD
385 // 12'b000000000100: ADDC
386 // 12'b000000001000: SUBC
387 // 12'b000000010000: SUB
388 // 12'b000000100000: CMP
389 // 12'b000001000000: DADD
390 // 12'b000010000000: BIT
391 // 12'b000100000000: BIC
392 // 12'b001000000000: BIS
393 // 12'b010000000000: XOR
394 // 12'b100000000000: AND
395
396 wire [15:0] inst_to_1hot = (16'h0001<<ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
397 wire [11:0] inst_to_nxt  = inst_to_1hot[15:4];
398
399
400 //
401 // 4.5) SOURCE AND DESTINATION REGISTERS
402 //---------------------------------------
403
404 // Destination register
405 reg [3:0] inst_dest_bin;
406 always @(posedge mclk or posedge puc)
407   if (puc)         inst_dest_bin <= 4'h0;
408   else if (decode) inst_dest_bin <= ir[3:0];
409
410 wire  [15:0] inst_dest = dbg_halt_st          ? (16'h0001 << dbg_reg_sel) :
411                          inst_type[`INST_JMP] ? 16'h0001                  :
412                          inst_so[`IRQ]  |
413                          inst_so[`PUSH] |
414                          inst_so[`CALL]       ? 16'h0002                  :
415                                                 (16'h0001 << inst_dest_bin);
416
417
418 // Source register
419 reg [3:0] inst_src_bin;
420 always @(posedge mclk or posedge puc)
421   if (puc)         inst_src_bin <= 4'h0;
422   else if (decode) inst_src_bin <= ir[11:8];
423
424 wire  [15:0] inst_src = inst_type[`INST_TO] ? (16'h0001 << inst_src_bin)  :
425                         inst_so[`RETI]      ? 16'h0002                    :
426                         inst_so[`IRQ]       ? 16'h0001                    :
427                         inst_type[`INST_SO] ? (16'h0001 << inst_dest_bin) : 16'h0000;
428
429
430 //
431 // 4.6) SOURCE ADDRESSING MODES
432 //--------------------------------
433 // Source addressing modes are encoded in a one hot fashion as following:
434 //
435 // 13'b0000000000001: Register direct.
436 // 13'b0000000000010: Register indexed.
437 // 13'b0000000000100: Register indirect.
438 // 13'b0000000001000: Register indirect autoincrement.
439 // 13'b0000000010000: Symbolic (operand is in memory at address PC+x).
440 // 13'b0000000100000: Immediate (operand is next word in the instruction stream).
441 // 13'b0000001000000: Absolute (operand is in memory at address x).
442 // 13'b0000010000000: Constant 4.
443 // 13'b0000100000000: Constant 8.
444 // 13'b0001000000000: Constant 0.
445 // 13'b0010000000000: Constant 1.
446 // 13'b0100000000000: Constant 2.
447 // 13'b1000000000000: Constant -1.
448
449 reg [12:0] inst_as_nxt;
450
451 wire [3:0] src_reg = inst_type_nxt[`INST_SO] ? ir[3:0] : ir[11:8];
452
453 always @(src_reg or ir or inst_type_nxt)
454   begin
455      if (inst_type_nxt[`INST_JMP])
456        inst_as_nxt =  13'b0000000000001;
457      else if (src_reg==4'h3) // Addressing mode using R3
458        case (ir[5:4])
459          2'b11  : inst_as_nxt =  13'b1000000000000;
460          2'b10  : inst_as_nxt =  13'b0100000000000;
461          2'b01  : inst_as_nxt =  13'b0010000000000;
462          default: inst_as_nxt =  13'b0001000000000;
463        endcase
464      else if (src_reg==4'h2) // Addressing mode using R2
465        case (ir[5:4])
466          2'b11  : inst_as_nxt =  13'b0000100000000;
467          2'b10  : inst_as_nxt =  13'b0000010000000;
468          2'b01  : inst_as_nxt =  13'b0000001000000;
469          default: inst_as_nxt =  13'b0000000000001;
470        endcase
471      else if (src_reg==4'h0) // Addressing mode using R0
472        case (ir[5:4])
473          2'b11  : inst_as_nxt =  13'b0000000100000;
474          2'b10  : inst_as_nxt =  13'b0000000000100;
475          2'b01  : inst_as_nxt =  13'b0000000010000;
476          default: inst_as_nxt =  13'b0000000000001;
477        endcase
478      else                    // General Addressing mode
479        case (ir[5:4])
480          2'b11  : inst_as_nxt =  13'b0000000001000;
481          2'b10  : inst_as_nxt =  13'b0000000000100;
482          2'b01  : inst_as_nxt =  13'b0000000000010;
483          default: inst_as_nxt =  13'b0000000000001;
484        endcase
485   end
486 assign    is_const = |inst_as_nxt[12:7];
487
488 reg [7:0] inst_as;
489 always @(posedge mclk or posedge puc)
490   if (puc)         inst_as <= 8'h00;
491   else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
492
493
494 // 13'b0000010000000: Constant 4.
495 // 13'b0000100000000: Constant 8.
496 // 13'b0001000000000: Constant 0.
497 // 13'b0010000000000: Constant 1.
498 // 13'b0100000000000: Constant 2.
499 // 13'b1000000000000: Constant -1.
500 always @(inst_as_nxt)
501   begin
502      if (inst_as_nxt[7])        sconst_nxt = 16'h0004;
503      else if (inst_as_nxt[8])   sconst_nxt = 16'h0008;
504      else if (inst_as_nxt[9])   sconst_nxt = 16'h0000;
505      else if (inst_as_nxt[10])  sconst_nxt = 16'h0001;
506      else if (inst_as_nxt[11])  sconst_nxt = 16'h0002;
507      else if (inst_as_nxt[12])  sconst_nxt = 16'hffff;
508      else                       sconst_nxt = 16'h0000;
509   end
510
511
512 //
513 // 4.7) DESTINATION ADDRESSING MODES
514 //-----------------------------------
515 // Destination addressing modes are encoded in a one hot fashion as following:
516 //
517 // 8'b00000001: Register direct.
518 // 8'b00000010: Register indexed.
519 // 8'b00010000: Symbolic (operand is in memory at address PC+x).
520 // 8'b01000000: Absolute (operand is in memory at address x).
521
522 reg  [7:0] inst_ad_nxt;
523
524 wire [3:0] dest_reg = ir[3:0];
525
526 always @(dest_reg or ir or inst_type_nxt)
527   begin
528      if (~inst_type_nxt[`INST_TO])
529        inst_ad_nxt =  8'b00000000;
530      else if (dest_reg==4'h2)   // Addressing mode using R2
531        case (ir[7])
532          1'b1   : inst_ad_nxt =  8'b01000000;
533          default: inst_ad_nxt =  8'b00000001;
534        endcase
535      else if (dest_reg==4'h0)   // Addressing mode using R0
536        case (ir[7])
537          2'b1   : inst_ad_nxt =  8'b00010000;
538          default: inst_ad_nxt =  8'b00000001;
539        endcase
540      else                       // General Addressing mode
541        case (ir[7])
542          2'b1   : inst_ad_nxt =  8'b00000010;
543          default: inst_ad_nxt =  8'b00000001;
544        endcase
545   end
546
547 reg [7:0] inst_ad;
548 always @(posedge mclk or posedge puc)
549   if (puc)         inst_ad <= 8'h00;
550   else if (decode) inst_ad <= inst_ad_nxt;
551
552
553 //
554 // 4.8) REMAINING INSTRUCTION DECODING
555 //-------------------------------------
556
557 // Operation size
558 reg       inst_bw;
559 always @(posedge mclk or posedge puc)
560   if (puc)         inst_bw     <= 1'b0;
561   else if (decode) inst_bw     <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~dbg_halt_cmd;
562
563 // Extended instruction size
564 assign    inst_sz_nxt = {1'b0,  (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
565                         {1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
566 always @(posedge mclk or posedge puc)
567   if (puc)         inst_sz     <= 2'b00;
568   else if (decode) inst_sz     <= inst_sz_nxt;
569
570
571 //=============================================================================
572 // 5)  EXECUTION-UNIT STATE MACHINE
573 //=============================================================================
574
575 // State machine registers
576 reg  [3:0] e_state;
577
578
579 // State machine control signals
580 //--------------------------------
581
582 wire src_acalc_pre =  inst_as_nxt[`IDX]   | inst_as_nxt[`SYMB]    | inst_as_nxt[`ABS];
583 wire src_rd_pre    =  inst_as_nxt[`INDIR] | inst_as_nxt[`INDIR_I] | inst_as_nxt[`IMM]  | inst_so_nxt[`RETI];
584 wire dst_acalc_pre =  inst_ad_nxt[`IDX]   | inst_ad_nxt[`SYMB]    | inst_ad_nxt[`ABS];
585 wire dst_acalc     =  inst_ad[`IDX]       | inst_ad[`SYMB]        | inst_ad[`ABS];
586 wire dst_rd_pre    =  inst_ad_nxt[`IDX]   | inst_so_nxt[`PUSH]    | inst_so_nxt[`CALL] | inst_so_nxt[`RETI];
587 wire dst_rd        =  inst_ad[`IDX]       | inst_so[`PUSH]        | inst_so[`CALL]     | inst_so[`RETI];
588
589 wire inst_branch   =  (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI];
590
591 reg exec_jmp;
592 always @(posedge mclk or posedge puc)
593   if (puc)                       exec_jmp <= 1'b0;
594   else if (inst_branch & decode) exec_jmp <= 1'b1;
595   else if (e_state==`E_JUMP)     exec_jmp <= 1'b0;
596
597 reg exec_dst_wr;
598 always @(posedge mclk or posedge puc)
599   if (puc)                     exec_dst_wr <= 1'b0;
600   else if (e_state==`E_DST_RD) exec_dst_wr <= 1'b1;
601   else if (e_state==`E_DST_WR) exec_dst_wr <= 1'b0;
602
603 reg exec_src_wr;
604 always @(posedge mclk or posedge puc)
605   if (puc)                                               exec_src_wr <= 1'b0;
606   else if (inst_type[`INST_SO] & (e_state==`E_SRC_RD))   exec_src_wr <= 1'b1;
607   else if ((e_state==`E_SRC_WR) || (e_state==`E_DST_WR)) exec_src_wr <= 1'b0;
608
609 reg exec_dext_rdy;
610 always @(posedge mclk or posedge puc)
611   if (puc)                     exec_dext_rdy <= 1'b0;
612   else if (e_state==`E_DST_RD) exec_dext_rdy <= 1'b0;
613   else if (inst_dext_rdy)      exec_dext_rdy <= 1'b1;
614
615 // Execution first state
616 //wire [3:0] e_first_state = dbg_halt_cmd        ? `E_IDLE   :
617 wire [3:0] e_first_state = ~dbg_halt_st  & inst_so_nxt[`IRQ] ? `E_IRQ_0  :
618                             dbg_halt_cmd | (i_state==I_IDLE) ? `E_IDLE   :
619                             cpuoff                           ? `E_IDLE   :
620                             src_acalc_pre                    ? `E_SRC_AD :
621                             src_rd_pre                       ? `E_SRC_RD :
622                             dst_acalc_pre                    ? `E_DST_AD :
623                             dst_rd_pre                       ? `E_DST_RD : `E_EXEC;
624
625
626 // State machine
627 //--------------------------------
628
629 // States Transitions
630 always @(e_state       or dst_acalc     or dst_rd   or inst_sext_rdy or
631          inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr   or
632          e_first_state or exec_src_wr)
633     case(e_state)
634       `E_IDLE   : e_state_nxt =  e_first_state;
635       `E_IRQ_0  : e_state_nxt =  `E_IRQ_1;
636       `E_IRQ_1  : e_state_nxt =  `E_IRQ_2;
637       `E_IRQ_2  : e_state_nxt =  `E_IRQ_3;
638       `E_IRQ_3  : e_state_nxt =  `E_IRQ_4;
639       `E_IRQ_4  : e_state_nxt =  `E_EXEC;
640
641       `E_SRC_AD : e_state_nxt =  inst_sext_rdy     ? `E_SRC_RD : `E_SRC_AD;
642
643       `E_SRC_RD : e_state_nxt =  dst_acalc         ? `E_DST_AD : 
644                                  dst_rd            ? `E_DST_RD : `E_EXEC;
645
646       `E_DST_AD : e_state_nxt =  (inst_dext_rdy |
647                                  exec_dext_rdy)    ? `E_DST_RD : `E_DST_AD;
648
649       `E_DST_RD : e_state_nxt =  `E_EXEC;
650
651       `E_EXEC   : e_state_nxt =  exec_dst_wr       ? `E_DST_WR :
652                                 exec_jmp           ? `E_JUMP   :
653                                 exec_src_wr        ? `E_SRC_WR : e_first_state;
654
655       `E_JUMP   : e_state_nxt =  e_first_state;
656       `E_DST_WR : e_state_nxt =  exec_jmp           ? `E_JUMP   : e_first_state;
657       `E_SRC_WR : e_state_nxt =  e_first_state;
658       default  : e_state_nxt =  `E_IRQ_0;
659     endcase
660
661 // State machine
662 always @(posedge mclk or posedge puc)
663   if (puc)     e_state  <= `E_IRQ_1;
664   else         e_state  <= e_state_nxt;
665
666
667 // Frontend State machine control signals
668 //----------------------------------------
669
670 wire exec_done = exec_jmp        ? (e_state==`E_JUMP)   :
671                  exec_dst_wr     ? (e_state==`E_DST_WR) :
672                  exec_src_wr     ? (e_state==`E_SRC_WR) : (e_state==`E_EXEC);
673
674
675 //=============================================================================
676 // 6)  EXECUTION-UNIT STATE CONTROL
677 //=============================================================================
678
679 //
680 // 6.1) ALU CONTROL SIGNALS
681 //-------------------------------------
682 //
683 // 12'b000000000001: Enable ALU source inverter
684 // 12'b000000000010: Enable Incrementer
685 // 12'b000000000100: Enable Incrementer on carry bit
686 // 12'b000000001000: Select Adder
687 // 12'b000000010000: Select AND
688 // 12'b000000100000: Select OR
689 // 12'b000001000000: Select XOR
690 // 12'b000010000000: Select DADD
691 // 12'b000100000000: Update N, Z & C (C=~Z)
692 // 12'b001000000000: Update all status bits
693 // 12'b010000000000: Update status bit for XOR instruction
694 // 12'b100000000000: Don't write to destination
695
696 reg  [11:0] inst_alu;
697
698 wire        alu_src_inv   = inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
699                             inst_to_nxt[`CMP]  | inst_to_nxt[`BIC] ;
700
701 wire        alu_inc       = inst_to_nxt[`SUB]  | inst_to_nxt[`CMP];
702
703 wire        alu_inc_c     = inst_to_nxt[`ADDC] | inst_to_nxt[`DADD] |
704                             inst_to_nxt[`SUBC];
705
706 wire        alu_add       = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC]       |
707                             inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC]       |
708                             inst_to_nxt[`CMP]  | inst_type_nxt[`INST_JMP] |
709                             inst_so_nxt[`RETI];
710
711  
712 wire        alu_and       = inst_to_nxt[`AND]  | inst_to_nxt[`BIC]  |
713                             inst_to_nxt[`BIT];
714
715 wire        alu_or        = inst_to_nxt[`BIS];
716
717 wire        alu_xor       = inst_to_nxt[`XOR];
718
719 wire        alu_dadd      = inst_to_nxt[`DADD];
720
721 wire        alu_stat_7    = inst_to_nxt[`BIT]  | inst_to_nxt[`AND]  |
722                             inst_so_nxt[`SXT];
723
724 wire        alu_stat_f    = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC] |
725                             inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
726                             inst_to_nxt[`CMP]  | inst_to_nxt[`DADD] |
727                             inst_to_nxt[`BIT]  | inst_to_nxt[`XOR]  |
728                             inst_to_nxt[`AND]  |
729                             inst_so_nxt[`RRC]  | inst_so_nxt[`RRA]  |
730                             inst_so_nxt[`SXT];
731
732 wire        alu_shift     = inst_so_nxt[`RRC]  | inst_so_nxt[`RRA];
733
734 wire        exec_no_wr    = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];
735
736 always @(posedge mclk or posedge puc)
737   if (puc)         inst_alu <= 12'h000;
738   else if (decode) inst_alu <= {exec_no_wr,
739                                 alu_shift,
740                                 alu_stat_f,
741                                 alu_stat_7,
742                                 alu_dadd,
743                                 alu_xor,
744                                 alu_or,
745                                 alu_and,
746                                 alu_add,
747                                 alu_inc_c,
748                                 alu_inc,
749                                 alu_src_inv};
750
751
752 endmodule // omsp_frontend
753
754 `include "openMSP430_undefines.v"