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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [core/] [rtl/] [verilog/] [omsp_frontend.v] - Blame information for rev 105

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

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

powered by: WebSVN 2.1.0

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