OpenCores

Subversion Repositories openmsp430

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

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

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

powered by: WebSVN 2.1.0

© copyright 1999-2014 OpenCores.org, equivalent to ORSoC AB, all rights reserved. OpenCores®, registered trademark.