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

Subversion Repositories oms8051mini

[/] [oms8051mini/] [trunk/] [rtl/] [8051/] [oc8051_memory_interface.v] - Blame information for rev 36

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dinesha
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  8051 memory interface                                       ////
4
////                                                              ////
5
////  This file is part of the 8051 cores project                 ////
6
////  http://www.opencores.org/cores/oms8051mini/                 ////
7
////                                                              ////
8
////  Description                                                 ////
9
////   comunication betwen cpu and memory                         ////
10
////                                                              ////
11
////  To Do:                                                      ////
12
////   nothing                                                    ////
13
////                                                              ////
14
////  Author(s):                                                  ////
15
////      - Simon Teran, simont@opencores.org                     ////
16
////      - Dinesh Annayya, dinesha@opencores.org                 ////
17
////                                                              ////
18
//////////////////////////////////////////////////////////////////////
19 25 dinesha
////   v0.0 - Dinesh A, 5th Jan 2017
20
////        1. Active edge of reset changed from High to Low
21 26 dinesha
////   v0.1 - Dinesh A, 6th Jan 2017
22
////        1. pc_next logic added
23 25 dinesha
//////////////////////////////////////////////////////////////////////
24 2 dinesha
////                                                              ////
25
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
26
////                                                              ////
27
//// This source file may be used and distributed without         ////
28
//// restriction provided that this copyright statement is not    ////
29
//// removed from the file and that any derivative work contains  ////
30
//// the original copyright notice and the associated disclaimer. ////
31
////                                                              ////
32
//// This source file is free software; you can redistribute it   ////
33
//// and/or modify it under the terms of the GNU Lesser General   ////
34
//// Public License as published by the Free Software Foundation; ////
35
//// either version 2.1 of the License, or (at your option) any   ////
36
//// later version.                                               ////
37
////                                                              ////
38
//// This source is distributed in the hope that it will be       ////
39
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
40
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
41
//// PURPOSE.  See the GNU Lesser General Public License for more ////
42
//// details.                                                     ////
43
////                                                              ////
44
//// You should have received a copy of the GNU Lesser General    ////
45
//// Public License along with this source; if not, download it   ////
46
//// from http://www.opencores.org/lgpl.shtml                     ////
47
////                                                              ////
48
//////////////////////////////////////////////////////////////////////
49
//
50
// CVS Revision History
51
//
52
// $Log: not supported by cvs2svn $
53
// Revision 1.12  2003/07/01 20:47:39  simont
54
// add /* synopsys xx_case */ to case statments.
55
//
56
// Revision 1.11  2003/06/20 13:35:10  simont
57
// simualtion `ifdef added
58
//
59
// Revision 1.10  2003/06/05 11:15:02  simont
60
// fix bug.
61
//
62
// Revision 1.9  2003/06/03 17:09:57  simont
63
// pipelined acces to axternal instruction interface added.
64
//
65
// Revision 1.8  2003/05/12 16:27:40  simont
66
// fix bug in movc intruction.
67
//
68
// Revision 1.7  2003/05/06 09:39:34  simont
69
// cahnge assigment to pc_wait (remove istb_o)
70
//
71
// Revision 1.6  2003/05/05 15:46:37  simont
72
// add aditional alu destination to solve critical path.
73
//
74
// Revision 1.5  2003/04/25 17:15:51  simont
75
// change branch instruction execution (reduse needed clock periods).
76
//
77
// Revision 1.4  2003/04/16 10:04:09  simont
78
// chance idat_ir to 24 bit wide
79
//
80
// Revision 1.3  2003/04/11 10:05:08  simont
81
// Change pc add value from 23'h to 16'h
82
//
83
// Revision 1.2  2003/04/09 16:24:03  simont
84
// change wr_sft to 2 bit wire.
85
//
86
// Revision 1.1  2003/01/13 14:13:12  simont
87
// initial import
88
//
89
//
90
 
91
 
92
`include "top_defines.v"
93
 
94
 
95 25 dinesha
module oc8051_memory_interface (clk, resetn,
96 2 dinesha
 
97
//decoder
98
     wr_i,
99
     wr_bit_i,
100
     rd_sel,
101
     wr_sel,
102
     pc_wr_sel,
103
     pc_wr,
104
     pc,
105 26 dinesha
     pc_next,
106 2 dinesha
     rd,
107
     mem_wait,
108
     mem_act,
109
     istb,
110
 
111
//internal ram
112
     wr_o,
113
     wr_bit_o,
114
     rd_addr,
115
     wr_addr,
116
     rd_ind,
117
     wr_ind,
118
     wr_dat,
119
 
120
     bit_in,
121
     in_ram,
122
     sfr,
123
     sfr_bit,
124
     bit_out,
125
     iram_out,
126
 
127
//program rom
128
     iadr_o,
129
     ea,
130
     ea_int,
131
     op1_out,
132
     op2_out,
133
     op3_out,
134
 
135
//internal
136
     idat_onchip,
137
 
138 20 dinesha
//external
139
     iack_i,
140
     istb_o,
141
     idat_i,
142 2 dinesha
 
143
//external data ram
144
     dadr_o,
145
     dwe_o,
146
     dstb_o,
147
     dack_i,
148
     ddat_i,
149
     ddat_o,
150
 
151
//interrupt interface
152
     intr,
153
     int_v,
154
     int_ack,
155
 
156
//alu
157
     des_acc,
158
     des1,
159
     des2,
160
 
161
//sfr's
162
     dptr,
163
     ri,
164
     sp,
165
     sp_w,
166
     rn,
167
     acc,
168
     reti
169
   );
170
 
171
 
172
input         clk,
173 25 dinesha
              resetn,
174 2 dinesha
              wr_i,
175
              wr_bit_i;
176
 
177
input         bit_in,
178
              sfr_bit,
179
              dack_i;
180
input [2:0]   mem_act;
181
input [7:0]   in_ram,
182
              sfr,
183
              acc,
184
              sp_w;
185 20 dinesha
input [31:0]  idat_i;
186 2 dinesha
 
187
output        bit_out,
188
              mem_wait,
189
              reti;
190
output [7:0]  iram_out,
191
              wr_dat;
192
 
193
reg           bit_out,
194
              reti;
195
reg [7:0]     iram_out,
196
              sp_r;
197
reg           rd_addr_r;
198
output        wr_o,
199
              wr_bit_o;
200
 
201
//????
202
reg           dack_ir;
203
reg [7:0]     ddat_ir;
204
reg [23:0]    idat_ir;
205
 
206
/////////////////////////////
207
//
208
//  rom_addr_sel
209
//
210
/////////////////////////////
211 20 dinesha
input         iack_i;
212 2 dinesha
input [7:0]   des_acc,
213
              des1,
214
              des2;
215
output [15:0] iadr_o;
216
 
217
wire          ea_rom_sel;
218
 
219
/////////////////////////////
220
//
221
// ext_addr_sel
222
//
223
/////////////////////////////
224
input [7:0]   ri,
225
              ddat_i;
226
input [15:0]  dptr;
227
 
228
output        dstb_o,
229
              dwe_o;
230
output [7:0]  ddat_o;
231
output [15:0] dadr_o;
232
 
233
/////////////////////////////
234
//
235
// ram_adr_sel
236
//
237
/////////////////////////////
238
 
239
input [2:0]   rd_sel,
240
              wr_sel;
241
input [4:0]   rn;
242
input [7:0]   sp;
243
 
244
output        rd_ind,
245
              wr_ind;
246
output [7:0]  wr_addr,
247
              rd_addr;
248
reg           rd_ind,
249
              wr_ind;
250
reg [7:0]     wr_addr,
251
              rd_addr;
252
 
253
reg [4:0]     rn_r;
254
reg [7:0]     ri_r,
255
              imm_r,
256
              imm2_r,
257
              op1_r;
258
wire [7:0]    imm,
259
              imm2;
260
 
261
/////////////////////////////
262
//
263
// op_select
264
//
265
/////////////////////////////
266
 
267
input         intr,
268
              rd,
269
              ea,
270
              ea_int,
271
              istb;
272
 
273
input  [7:0]  int_v;
274
 
275
input  [31:0] idat_onchip;
276
 
277 20 dinesha
output        int_ack,
278
              istb_o;
279 2 dinesha
 
280
output  [7:0] op1_out,
281
              op3_out,
282
              op2_out;
283
 
284
reg           int_ack_t,
285
              int_ack,
286
              int_ack_buff;
287
 
288
reg [7:0]     int_vec_buff;
289
reg [7:0]     op1_out,
290
              op2_buff,
291
              op3_buff;
292
reg [7:0]     op1_o,
293
              op2_o,
294
              op3_o;
295
 
296
reg [7:0]     op1_xt,
297
              op2_xt,
298
              op3_xt;
299
 
300
reg [7:0]     op1,
301
              op2,
302
              op3;
303
wire [7:0]    op2_direct;
304
 
305
input [2:0]   pc_wr_sel;
306
 
307
input         pc_wr;
308
output [15:0] pc;
309 26 dinesha
output [15:0] pc_next;
310 2 dinesha
 
311 26 dinesha
reg [15:0]    pc,pc_next;
312 2 dinesha
 
313
//
314
//pc            program counter register, save current value
315
reg [15:0]    pc_buf;
316
wire [15:0]   alu;
317
 
318
 
319
reg           int_buff,
320
              int_buff1; // interrupt buffer: used to prevent interrupting in the middle of executin instructions
321
 
322
 
323
//
324
//
325
////////////////////////////
326
reg           istb_t,
327
              imem_wait,
328
              dstb_o,
329
              dwe_o;
330
 
331
reg [7:0]     ddat_o;
332
reg [15:0]    iadr_t,
333
              dadr_ot;
334
reg           dmem_wait;
335
wire          pc_wait;
336
wire [1:0]    bank;
337
wire [7:0]    isr_call;
338
 
339
reg [1:0]     op_length;
340
reg [2:0]     op_pos;
341
wire          inc_pc;
342
 
343
reg           pc_wr_r;
344
 
345
wire [15:0]   pc_out;
346
 
347
reg [31:0]    idat_cur,
348
              idat_old;
349
 
350
reg           inc_pc_r,
351
              pc_wr_r2;
352
 
353
reg [7:0]     cdata;
354
reg           cdone;
355
 
356
 
357
assign bank       = rn[4:3];
358
assign imm        = op2_out;
359
assign imm2       = op3_out;
360
assign alu        = {des2, des_acc};
361
assign ea_rom_sel = ea && ea_int;
362
assign wr_o       = wr_i;
363
assign wr_bit_o   = wr_bit_i;
364
 
365 20 dinesha
//assign mem_wait   = dmem_wait || imem_wait || pc_wr_r;
366 2 dinesha
assign mem_wait   = dmem_wait || imem_wait || pc_wr_r2;
367 20 dinesha
//assign mem_wait   = dmem_wait || imem_wait;
368
assign istb_o     = (istb || (istb_t & !iack_i)) && !dstb_o && !ea_rom_sel;
369 2 dinesha
 
370 20 dinesha
assign pc_wait    = rd && (ea_rom_sel || (!istb_t && iack_i));
371 2 dinesha
 
372
assign wr_dat     = des1;
373
 
374
 
375
`ifdef OC8051_SIMULATION
376 25 dinesha
  always @(negedge resetn) begin
377 2 dinesha
    #5
378
    if (ea_rom_sel)
379
      $display("   progran execution from external rom");
380
    else
381
      $display("   progran execution from internal rom");
382
  end
383
 
384
`endif
385
 
386
 
387
/////////////////////////////
388
//
389
//  ram_select
390
//
391
/////////////////////////////
392
always @(rd_addr_r or in_ram or sfr or bit_in or sfr_bit or rd_ind)
393
begin
394
  if (rd_addr_r && !rd_ind) begin
395
    iram_out = sfr;
396
    bit_out = sfr_bit;
397
  end else begin
398
    iram_out = in_ram;
399
    bit_out = bit_in;
400
  end
401
end
402
 
403
/////////////////////////////
404
//
405
// ram_adr_sel
406
//
407
/////////////////////////////
408
 
409 20 dinesha
always @(rd_sel or sp or ri or rn or imm or dadr_o[15:0] or bank)
410 2 dinesha
begin
411
  case (rd_sel) /* synopsys full_case parallel_case */
412
    `OC8051_RRS_RN   : rd_addr = {3'h0, rn};
413
    `OC8051_RRS_I    : rd_addr = ri;
414
    `OC8051_RRS_D    : rd_addr = imm;
415
    `OC8051_RRS_SP   : rd_addr = sp;
416
 
417
    `OC8051_RRS_B    : rd_addr = `OC8051_SFR_B;
418
    `OC8051_RRS_DPTR : rd_addr = `OC8051_SFR_DPTR_LO;
419
    `OC8051_RRS_PSW  : rd_addr = `OC8051_SFR_PSW;
420
    `OC8051_RRS_ACC  : rd_addr = `OC8051_SFR_ACC;
421 20 dinesha
//    default          : rd_addr = 2'bxx;
422 2 dinesha
  endcase
423
 
424
end
425
 
426
 
427
//
428
//
429 20 dinesha
always @(wr_sel or sp_w or rn_r or imm_r or ri_r or imm2_r or op1_r or dadr_o[15:0])
430 2 dinesha
begin
431
  case (wr_sel) /* synopsys full_case parallel_case */
432
    `OC8051_RWS_RN : wr_addr = {3'h0, rn_r};
433
    `OC8051_RWS_I  : wr_addr = ri_r;
434
    `OC8051_RWS_D  : wr_addr = imm_r;
435
    `OC8051_RWS_SP : wr_addr = sp_w;
436
    `OC8051_RWS_D3 : wr_addr = imm2_r;
437
    `OC8051_RWS_B  : wr_addr = `OC8051_SFR_B;
438 36 dinesha
    default        : wr_addr = 2'b00;
439 2 dinesha
  endcase
440
end
441
 
442 25 dinesha
always @(posedge clk or negedge resetn)
443
  if (resetn == 1'b0)
444 36 dinesha
    rd_ind <= 1'b0;
445 2 dinesha
  else if ((rd_sel==`OC8051_RRS_I) || (rd_sel==`OC8051_RRS_SP))
446 36 dinesha
    rd_ind <= 1'b1;
447 2 dinesha
  else
448 36 dinesha
    rd_ind <= 1'b0;
449 2 dinesha
 
450
always @(wr_sel)
451
  if ((wr_sel==`OC8051_RWS_I) || (wr_sel==`OC8051_RWS_SP))
452
    wr_ind = 1'b1;
453
  else
454
    wr_ind = 1'b0;
455
 
456
 
457
/////////////////////////////
458
//
459
//  rom_addr_sel
460
//
461
/////////////////////////////
462
//
463
// output address is alu destination
464
// (instructions MOVC)
465
 
466 20 dinesha
//assign iadr_o = (istb_t & !iack_i) ? iadr_t : pc_out;
467 2 dinesha
assign iadr_o = (istb_t) ? iadr_t : pc_out;
468
 
469
 
470 25 dinesha
always @(posedge clk or negedge resetn)
471 2 dinesha
begin
472 25 dinesha
  if (resetn == 1'b0) begin
473 36 dinesha
    iadr_t <= 23'h0;
474
    istb_t <= 1'b0;
475
    imem_wait <= 1'b0;
476
    idat_ir <= 24'h0;
477 2 dinesha
  end else if (mem_act==`OC8051_MAS_CODE) begin
478 36 dinesha
    iadr_t <= alu;
479
    istb_t <= 1'b1;
480
    imem_wait <= 1'b1;
481 2 dinesha
  end else if (ea_rom_sel && imem_wait) begin
482 36 dinesha
    imem_wait <= 1'b0;
483 2 dinesha
  end else if (!imem_wait && istb_t) begin
484 36 dinesha
    istb_t <= 1'b0;
485 20 dinesha
  end else if (iack_i) begin
486 36 dinesha
    imem_wait <= 1'b0;
487
    idat_ir <= idat_i [23:0];
488 20 dinesha
  end
489 2 dinesha
end
490
 
491
/////////////////////////////
492
//
493
// ext_addr_sel
494
//
495
/////////////////////////////
496
 
497
assign dadr_o = dadr_ot;
498
 
499 25 dinesha
always @(posedge clk or negedge resetn)
500 2 dinesha
begin
501 25 dinesha
  if (resetn == 1'b0) begin
502 36 dinesha
    dwe_o <= 1'b0;
503
    dmem_wait <= 1'b0;
504
    dstb_o <= 1'b0;
505
    ddat_o <= 8'h00;
506
    dadr_ot <= 23'h0;
507 2 dinesha
  end else if (dack_i) begin
508 36 dinesha
    dwe_o <= 1'b0;
509
    dstb_o <= 1'b0;
510
    dmem_wait <= 1'b0;
511 2 dinesha
  end else begin
512
    case (mem_act) /* synopsys full_case parallel_case */
513
      `OC8051_MAS_DPTR_R: begin  // read from external rom: acc=(dptr)
514 36 dinesha
        dwe_o <= 1'b0;
515
        dstb_o <= 1'b1;
516
        ddat_o <= 8'h00;
517
        dadr_ot <= {7'h0, dptr};
518
        dmem_wait <= 1'b1;
519 2 dinesha
      end
520
      `OC8051_MAS_DPTR_W: begin  // write to external rom: (dptr)=acc
521 36 dinesha
        dwe_o <= 1'b1;
522
        dstb_o <= 1'b1;
523
        ddat_o <= acc;
524
        dadr_ot <= {7'h0, dptr};
525
        dmem_wait <= 1'b1;
526 2 dinesha
      end
527
      `OC8051_MAS_RI_R:   begin  // read from external rom: acc=(Ri)
528 36 dinesha
        dwe_o <= 1'b0;
529
        dstb_o <= 1'b1;
530
        ddat_o <= 8'h00;
531
        dadr_ot <= {15'h0, ri};
532
        dmem_wait <= 1'b1;
533 2 dinesha
      end
534
      `OC8051_MAS_RI_W: begin    // write to external rom: (Ri)=acc
535 36 dinesha
        dwe_o <= 1'b1;
536
        dstb_o <= 1'b1;
537
        ddat_o <= acc;
538
        dadr_ot <= {15'h0, ri};
539
        dmem_wait <= 1'b1;
540 2 dinesha
      end
541 36 dinesha
    default: begin
542
       dwe_o <= dwe_o;
543
       dmem_wait <= dmem_wait;
544
       dstb_o <= dstb_o;
545
       ddat_o <= ddat_o;
546
       dadr_ot <= dadr_ot;
547
      end
548 2 dinesha
    endcase
549
  end
550
end
551
 
552
/////////////////////////////
553
//
554
// op_select
555
//
556
/////////////////////////////
557
 
558
 
559
 
560 25 dinesha
always @(posedge clk or negedge resetn)
561 2 dinesha
begin
562 25 dinesha
  if (resetn == 1'b0) begin
563 36 dinesha
    idat_cur <= 32'h0;
564
    idat_old <= 32'h0;
565 20 dinesha
  end else if ((iack_i | ea_rom_sel) & (inc_pc | pc_wr_r2)) begin
566 36 dinesha
    idat_cur <= ea_rom_sel ? idat_onchip : idat_i;
567
    idat_old <= idat_cur;
568 2 dinesha
  end
569
 
570
end
571
 
572 25 dinesha
always @(posedge clk or negedge resetn)
573 2 dinesha
begin
574 25 dinesha
  if (resetn == 1'b0) begin
575 36 dinesha
    cdata <= 8'h00;
576
    cdone <= 1'b0;
577 2 dinesha
  end else if (istb_t) begin
578 36 dinesha
    cdata <= ea_rom_sel ? idat_onchip[7:0] : idat_i[7:0];
579
    cdone <= 1'b1;
580 2 dinesha
  end else begin
581 36 dinesha
    cdone <= 1'b0;
582 2 dinesha
  end
583
end
584
 
585 20 dinesha
always @(op_pos or idat_cur or idat_old)
586 2 dinesha
begin
587
  case (op_pos)  /* synopsys parallel_case */
588
    3'b000: begin
589
       op1 = idat_old[7:0]  ;
590
       op2 = idat_old[15:8] ;
591
       op3 = idat_old[23:16];
592
      end
593
    3'b001: begin
594
       op1 = idat_old[15:8] ;
595
       op2 = idat_old[23:16];
596
       op3 = idat_old[31:24];
597
      end
598
    3'b010: begin
599
       op1 = idat_old[23:16];
600
       op2 = idat_old[31:24];
601
       op3 = idat_cur[7:0]  ;
602
      end
603
    3'b011: begin
604
       op1 = idat_old[31:24];
605
       op2 = idat_cur[7:0]  ;
606
       op3 = idat_cur[15:8] ;
607
      end
608
    3'b100: begin
609
       op1 = idat_cur[7:0]  ;
610
       op2 = idat_cur[15:8] ;
611
       op3 = idat_cur[23:16];
612
      end
613
    default: begin
614
       op1 = idat_cur[15:8] ;
615
       op2 = idat_cur[23:16];
616
       op3 = idat_cur[31:24];
617
      end
618
  endcase
619
end
620
 
621 20 dinesha
 
622
always @(dack_ir or ddat_ir or op1_o or iram_out or cdone or cdata)
623 2 dinesha
  if (dack_ir)
624
    op1_out = ddat_ir;
625
  else if (cdone)
626
    op1_out = cdata;
627
  else
628
    op1_out = op1_o;
629
 
630
assign op3_out = (rd) ? op3_o : op3_buff;
631
assign op2_out = (rd) ? op2_o : op2_buff;
632
 
633 20 dinesha
always @(idat_i or iack_i or idat_ir or rd)
634 2 dinesha
begin
635 20 dinesha
  if (iack_i) begin
636
    op1_xt = idat_i[7:0];
637
    op2_xt = idat_i[15:8];
638
    op3_xt = idat_i[23:16];
639
  end else if (!rd) begin
640 2 dinesha
    op1_xt = idat_ir[7:0];
641
    op2_xt = idat_ir[15:8];
642
    op3_xt = idat_ir[23:16];
643
  end else begin
644
    op1_xt = 8'h00;
645
    op2_xt = 8'h00;
646
    op3_xt = 8'h00;
647
  end
648
end
649
 
650
 
651
//
652
// in case of interrupts
653 20 dinesha
always @(op1 or op2 or op3 or int_ack_t or int_vec_buff or iack_i or ea_rom_sel)
654 2 dinesha
begin
655 20 dinesha
  if (int_ack_t && (iack_i || ea_rom_sel)) begin
656 2 dinesha
    op1_o = `OC8051_LCALL;
657
    op2_o = 8'h00;
658
    op3_o = int_vec_buff;
659
  end else begin
660
    op1_o = op1;
661
    op2_o = op2;
662
    op3_o = op3;
663
  end
664
end
665
 
666
//
667
//in case of reti
668 25 dinesha
always @(posedge clk or negedge resetn)
669 36 dinesha
  if (resetn == 1'b0) reti <= 1'b0;
670
  else if ((op1_o==`OC8051_RETI) & rd & !mem_wait) reti <= 1'b1;
671
  else reti <= 1'b0;
672 2 dinesha
 
673
//
674
// remember inputs
675 25 dinesha
always @(posedge clk or negedge resetn)
676 2 dinesha
begin
677 25 dinesha
  if (resetn == 1'b0) begin
678 36 dinesha
    op2_buff <= 8'h0;
679
    op3_buff <= 8'h0;
680 2 dinesha
  end else if (rd) begin
681 36 dinesha
    op2_buff <= op2_o;
682
    op3_buff <= op3_o;
683 2 dinesha
  end
684
end
685
 
686
/////////////////////////////
687
//
688
//  pc
689
//
690
/////////////////////////////
691
 
692 20 dinesha
always @(op1_out)
693 2 dinesha
begin
694
        casex (op1_out) /* synopsys parallel_case */
695
          `OC8051_ACALL :  op_length = 2'h2;
696
          `OC8051_AJMP :   op_length = 2'h2;
697
 
698
        //op_code [7:3]
699
          `OC8051_CJNE_R : op_length = 2'h3;
700
          `OC8051_DJNZ_R : op_length = 2'h2;
701
          `OC8051_MOV_DR : op_length = 2'h2;
702
          `OC8051_MOV_CR : op_length = 2'h2;
703
          `OC8051_MOV_RD : op_length = 2'h2;
704
 
705
        //op_code [7:1]
706
          `OC8051_CJNE_I : op_length = 2'h3;
707
          `OC8051_MOV_ID : op_length = 2'h2;
708
          `OC8051_MOV_DI : op_length = 2'h2;
709
          `OC8051_MOV_CI : op_length = 2'h2;
710
 
711
        //op_code [7:0]
712
          `OC8051_ADD_D :  op_length = 2'h2;
713
          `OC8051_ADD_C :  op_length = 2'h2;
714
          `OC8051_ADDC_D : op_length = 2'h2;
715
          `OC8051_ADDC_C : op_length = 2'h2;
716
          `OC8051_ANL_D :  op_length = 2'h2;
717
          `OC8051_ANL_C :  op_length = 2'h2;
718
          `OC8051_ANL_DD : op_length = 2'h2;
719
          `OC8051_ANL_DC : op_length = 2'h3;
720
          `OC8051_ANL_B :  op_length = 2'h2;
721
          `OC8051_ANL_NB : op_length = 2'h2;
722
          `OC8051_CJNE_D : op_length = 2'h3;
723
          `OC8051_CJNE_C : op_length = 2'h3;
724
          `OC8051_CLR_B :  op_length = 2'h2;
725
          `OC8051_CPL_B :  op_length = 2'h2;
726
          `OC8051_DEC_D :  op_length = 2'h2;
727
          `OC8051_DJNZ_D : op_length = 2'h3;
728
          `OC8051_INC_D :  op_length = 2'h2;
729
          `OC8051_JB :     op_length = 2'h3;
730
          `OC8051_JBC :    op_length = 2'h3;
731
          `OC8051_JC :     op_length = 2'h2;
732
          `OC8051_JNB :    op_length = 2'h3;
733
          `OC8051_JNC :    op_length = 2'h2;
734
          `OC8051_JNZ :    op_length = 2'h2;
735
          `OC8051_JZ :     op_length = 2'h2;
736
          `OC8051_LCALL :  op_length = 2'h3;
737
          `OC8051_LJMP :   op_length = 2'h3;
738
          `OC8051_MOV_D :  op_length = 2'h2;
739
          `OC8051_MOV_C :  op_length = 2'h2;
740
          `OC8051_MOV_DA : op_length = 2'h2;
741
          `OC8051_MOV_DD : op_length = 2'h3;
742
          `OC8051_MOV_CD : op_length = 2'h3;
743
          `OC8051_MOV_BC : op_length = 2'h2;
744
          `OC8051_MOV_CB : op_length = 2'h2;
745
          `OC8051_MOV_DP : op_length = 2'h3;
746
          `OC8051_ORL_D :  op_length = 2'h2;
747
          `OC8051_ORL_C :  op_length = 2'h2;
748
          `OC8051_ORL_AD : op_length = 2'h2;
749
          `OC8051_ORL_CD : op_length = 2'h3;
750
          `OC8051_ORL_B :  op_length = 2'h2;
751
          `OC8051_ORL_NB : op_length = 2'h2;
752
          `OC8051_POP :    op_length = 2'h2;
753
          `OC8051_PUSH :   op_length = 2'h2;
754
          `OC8051_SETB_B : op_length = 2'h2;
755
          `OC8051_SJMP :   op_length = 2'h2;
756
          `OC8051_SUBB_D : op_length = 2'h2;
757
          `OC8051_SUBB_C : op_length = 2'h2;
758
          `OC8051_XCH_D :  op_length = 2'h2;
759
          `OC8051_XRL_D :  op_length = 2'h2;
760
          `OC8051_XRL_C :  op_length = 2'h2;
761
          `OC8051_XRL_AD : op_length = 2'h2;
762
          `OC8051_XRL_CD : op_length = 2'h3;
763
          default:         op_length = 2'h1;
764
        endcase
765
end
766
 
767
 
768
assign inc_pc = ((op_pos[2] | (&op_pos[1:0])) & rd) | pc_wr_r2;
769
 
770 25 dinesha
always @(posedge clk or negedge resetn)
771 2 dinesha
begin
772 25 dinesha
  if (resetn == 1'b0) begin
773 36 dinesha
    op_pos <= 3'h0;
774 2 dinesha
  end else if (pc_wr_r2) begin
775 36 dinesha
    op_pos <= 3'h4;// - op_length;////****??????????
776 2 dinesha
  end else if (inc_pc & rd) begin
777 36 dinesha
    op_pos[2]   <= op_pos[2] & !op_pos[1] & op_pos[0] & (&op_length);
778
    op_pos[1:0] <= op_pos[1:0] + op_length;
779 2 dinesha
  end else if (rd) begin
780 36 dinesha
    op_pos <= op_pos + {1'b0, op_length};
781 2 dinesha
  end
782
end
783
 
784
//
785
// remember interrupt
786
// we don't want to interrupt instruction in the middle of execution
787 25 dinesha
always @(posedge clk or negedge resetn)
788
 if (resetn == 1'b0) begin
789 36 dinesha
   int_ack_t <= 1'b0;
790
   int_vec_buff <= 8'h00;
791 2 dinesha
 end else if (intr) begin
792 36 dinesha
   int_ack_t <= 1'b1;
793
   int_vec_buff <= int_v;
794
 end else if (rd && (ea_rom_sel || iack_i) && !pc_wr_r2) int_ack_t <= 1'b0;
795 2 dinesha
 
796 25 dinesha
always @(posedge clk or negedge resetn)
797 36 dinesha
  if (resetn == 1'b0) int_ack_buff <= 1'b0;
798
  else int_ack_buff <= int_ack_t;
799 2 dinesha
 
800 25 dinesha
always @(posedge clk or negedge resetn)
801 36 dinesha
  if (resetn == 1'b0) int_ack <= 1'b0;
802 2 dinesha
  else begin
803
    if ((int_ack_buff) & !(int_ack_t))
804 36 dinesha
      int_ack <= 1'b1;
805
    else int_ack <= 1'b0;
806 2 dinesha
  end
807
 
808
 
809
//
810
//interrupt buffer
811 25 dinesha
always @(posedge clk or negedge resetn)
812
  if (resetn == 1'b0) begin
813 36 dinesha
    int_buff1 <= 1'b0;
814 2 dinesha
  end else begin
815 36 dinesha
    int_buff1 <= int_buff;
816 2 dinesha
  end
817
 
818 25 dinesha
always @(posedge clk or negedge resetn)
819
  if (resetn == 1'b0) begin
820 36 dinesha
    int_buff <= 1'b0;
821 2 dinesha
  end else if (intr) begin
822 36 dinesha
    int_buff <= 1'b1;
823 2 dinesha
  end else if (pc_wait)
824 36 dinesha
    int_buff <= 1'b0;
825 2 dinesha
 
826
wire [7:0]  pcs_source;
827
reg  [15:0] pcs_result;
828
reg         pcs_cy;
829
 
830
assign pcs_source = pc_wr_sel[0] ? op3_out : op2_out;
831
 
832
always @(pcs_source or pc or pcs_cy)
833
begin
834
  if (pcs_source[7]) begin
835
    {pcs_cy, pcs_result[7:0]} = {1'b0, pc[7:0]} + {1'b0, pcs_source};
836
    pcs_result[15:8] = pc[15:8] - {7'h0, !pcs_cy};
837
  end else pcs_result = pc + {8'h00, pcs_source};
838
end
839
 
840 20 dinesha
 
841 25 dinesha
always @(posedge clk or negedge resetn)
842 2 dinesha
begin
843 25 dinesha
  if (resetn == 1'b0)
844 36 dinesha
    pc <= 16'h0;
845 2 dinesha
  else if (pc_wr_r2)
846 36 dinesha
    pc <= pc_buf;
847 26 dinesha
  else if (rd && !int_ack_t && !(pc_wr && (pc_wr_sel != `OC8051_PIS_AH)) && !pc_wr_r)
848 36 dinesha
    pc <= pc_buf - 16'h8 + {13'h0, op_pos} + {14'h0, op_length};
849 2 dinesha
end
850
 
851 26 dinesha
always @(posedge clk or negedge resetn)
852
begin
853
  if (resetn == 1'b0)
854 36 dinesha
    pc_next <= 16'h0;
855 26 dinesha
  else if (pc_wr_r2)
856 36 dinesha
    pc_next <= pc_buf;
857 26 dinesha
  else if (rd && !int_ack_t)
858 36 dinesha
    pc_next <= pc_buf - 16'h8 + {13'h0, op_pos} + {14'h0, op_length};
859 26 dinesha
end
860 2 dinesha
 
861 25 dinesha
always @(posedge clk or negedge resetn)
862 2 dinesha
begin
863 25 dinesha
  if (resetn == 1'b0) begin
864 36 dinesha
    pc_buf <= `OC8051_RST_PC;
865 2 dinesha
  end else if (pc_wr) begin
866
//
867
//case of writing new value to pc (jupms)
868
      case (pc_wr_sel) /* synopsys full_case parallel_case */
869 36 dinesha
        `OC8051_PIS_ALU: pc_buf        <= alu;
870
        `OC8051_PIS_AL:  pc_buf[7:0]   <= alu[7:0];
871
        `OC8051_PIS_AH:  pc_buf[15:8]  <= alu[7:0];
872
        `OC8051_PIS_I11: pc_buf[10:0]  <= {op1_out[7:5], op2_out};
873
        `OC8051_PIS_I16: pc_buf        <= {op2_out, op3_out};
874
        `OC8051_PIS_SO1: pc_buf        <= pcs_result;
875
        `OC8051_PIS_SO2: pc_buf        <= pcs_result;
876
        default: pc_buf <= `OC8051_RST_PC;
877 2 dinesha
      endcase
878
//  end else if (inc_pc) begin
879
  end else begin
880
//
881
//or just remember current
882 36 dinesha
      pc_buf <= pc_out;
883 2 dinesha
  end
884
end
885
 
886
 
887
assign pc_out = inc_pc ? pc_buf + 16'h4
888
                       : pc_buf ;
889
 
890
 
891
 
892
 
893
 
894 25 dinesha
always @(posedge clk or negedge resetn)
895
  if (resetn == 1'b0)
896 36 dinesha
    ddat_ir <= 8'h00;
897 2 dinesha
  else if (dack_i)
898 36 dinesha
    ddat_ir <= ddat_i;
899 2 dinesha
 
900 20 dinesha
 
901 2 dinesha
////////////////////////
902 25 dinesha
always @(posedge clk or negedge resetn)
903
  if (resetn == 1'b0) begin
904 36 dinesha
    rn_r      <= 5'd0;
905
    ri_r      <= 8'h00;
906
    imm_r     <= 8'h00;
907
    imm2_r    <= 8'h00;
908
    rd_addr_r <= 1'b0;
909
    op1_r     <= 8'h0;
910
    dack_ir   <= 1'b0;
911
    sp_r      <= 1'b0;
912
    pc_wr_r   <= 1'b0;
913
    pc_wr_r2  <= 1'b0;
914 2 dinesha
  end else begin
915 36 dinesha
    rn_r      <= rn;
916
    ri_r      <= ri;
917
    imm_r     <= imm;
918
    imm2_r    <= imm2;
919
    rd_addr_r <= rd_addr[7];
920
    op1_r     <= op1_out;
921
    dack_ir   <= dack_i;
922
    sp_r      <= sp;
923
    pc_wr_r   <= pc_wr && (pc_wr_sel != `OC8051_PIS_AH);
924
    pc_wr_r2  <= pc_wr_r;
925 2 dinesha
  end
926
 
927 25 dinesha
always @(posedge clk or negedge resetn)
928
  if (resetn == 1'b0) begin
929 36 dinesha
    inc_pc_r  <= 1'b1;
930 2 dinesha
  end else if (istb) begin
931 36 dinesha
    inc_pc_r  <= inc_pc;
932 2 dinesha
  end
933
 
934
`ifdef OC8051_SIMULATION
935
 
936
initial
937
begin
938 25 dinesha
  wait (!resetn)
939 2 dinesha
  if (ea_rom_sel) begin
940
    $display(" ");
941
    $display("\t Program running from internal rom !");
942
    $display(" ");
943
  end else begin
944
    $display(" ");
945
    $display("\t Program running from external rom !");
946
    $display(" ");
947
  end
948
end
949
`endif
950
 
951
 
952
endmodule

powered by: WebSVN 2.1.0

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