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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64/] [rtl/] [seq/] [FT64seq.v] - Blame information for rev 43

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 43 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2017-2018  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
// FT64seq.v
9
// - FT64 processing core - sequential version
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//
24
// ============================================================================
25
//
26
// Comment out the following line to exclude AMO operations from the core.
27
`define EXT_A   1'b1
28
// Comment out the following line to exclude multiply/divide operations from the core.
29
`define EXT_M   1'b1
30
 
31
`define BRK             6'h00
32
`define R2              6'h02
33
`define R1                      6'h01
34
`define ABS                             5'h04
35
`define NOT             5'h05
36
`define SUB                     6'h05
37
`define Scc                 6'h06
38
`define Sccu        6'h07
39
`define SHIFTW          6'h0F
40
`define SHIFTB          6'h1F
41
`define LEAX            6'h18
42
`define SYNC            6'h22
43
`define SHIFTC          6'h2F
44
`define SEI                     6'h30
45
`define WAIT            6'h31
46
`define RTI                     6'h32
47
`define RTE                     6'h32
48
`define DIVMODU         6'h3C
49
`define DIVMODSU        6'h3D
50
`define DIVMOD          6'h3E
51
`define SHIFTH          6'h3F
52
`define BccR    6'h03
53
`define ADD             6'h04
54
`define CMP             6'h06
55
`define CMPU    6'h07
56
`define AND             6'h08
57
`define OR              6'h09
58
`define XOR             6'h0A
59
`define REX             6'h0D
60
`define CSR             6'h0E
61
`define LH              6'h10
62
`define LHU             6'h11
63
`define LW              6'h12
64
`define LB              6'h13
65
`define SH              6'h14
66
`define SB              6'h15
67
`define SW              6'h16
68
`define SWC             6'h17
69
`define JAL             6'h18
70
`define CALL    6'h19
71
`define QOPI    6'h1A
72
`define QOR                     3'd0
73
`define QADD            3'd1
74
`define QAND            3'd2
75
`define QXOR            3'd3
76
`define SccI    6'h1B
77
`define NOP             6'h1C
78
`define LWR             6'h1D
79
`define LC              6'h20
80
`define LCU             6'h21
81
`define BITFLD  6'h22
82
`define LBU             6'h23
83
`define SC              6'h24
84
`define BBc0    6'h26
85
`define BBc1    6'h27
86
`define JMP             6'h28
87
`define LINK    6'h2A
88
`define MODUI   6'h2C
89
`define MODSUI  6'h2D
90
`define MODI    6'h2E
91
`define AMO             6'h2F
92
`define AMOSWAP         6'h00
93
`define AMOADD          6'h04
94
`define AMOAND          6'h08
95
`define AMOOR           6'h09
96
`define AMOXOR          6'h0A
97
`define AMOSHL          6'h0C
98
`define AMOSHR          6'h0D
99
`define AMOASR          6'h0E
100
`define AMOROL          6'h0F
101
`define AMOMIN          6'h1C
102
`define AMOMAX          6'h1D
103
`define AMOMINU         6'h1E
104
`define AMOMAXU         6'h1F
105
`define AMOSWAPI        6'h20
106
`define AMOADDI         6'h24
107
`define AMOANDI         6'h28
108
`define AMOORI          6'h29
109
`define AMOXORI         6'h2A
110
`define AMOSHLI         6'h2C
111
`define AMOSHRI         6'h2D
112
`define AMOASRI         6'h2E
113
`define AMOROLI         6'h2F
114
`define AMOMINI         6'h3C
115
`define AMOMAXI         6'h3D
116
`define AMOMINUI        6'h3E
117
`define AMOMAXUI        6'h3F
118
`define Bcc0    6'h30
119
`define Bcc1    6'h31
120
`define BEQ0    6'h32
121
`define BEQ1    6'h33
122
`define MULU    6'h38
123
`define MULSU   6'h39
124
`define MUL             6'h3A
125
`define DIVUI   6'h3C
126
`define DIVSUI  6'h3D
127
`define DIVI    6'h3E
128
 
129
`define SHL             4'h0
130
`define SHR             4'h1
131
`define ASL             4'h2
132
`define ASR             4'h3
133
`define ROL             4'h4
134
`define ROR             4'h5
135
`define SHLI    4'h8
136
`define SHRI    4'h9
137
`define ASLI    4'hA
138
`define ASRI    4'hB
139
`define ROLI    4'hC
140
`define RORI    4'hD
141
 
142
`define BEQ             4'h0
143
`define BNE             4'h1
144
`define BLT             4'h2
145
`define BGE             4'h3
146
`define BLTU    4'h4
147
`define BGEU    4'h5
148
`define FBEQ    4'h8
149
`define FBNE    4'h9
150
`define FBLT    4'hA
151
`define FBGE    4'hB
152
 
153
`define HARTID  11'h001
154
`define TICK    11'h002
155
`define CAUSE   11'h006
156
`define SCRATCH 11'h009
157
`define SEMA    11'h00C
158
`define TVEC    11'b000_0011_0???
159
`define TIME    11'h7E0
160
`define INSTRET 11'h7E1
161
 
162
module FT64seq(hartid_i, sig_i, rst_i, clk_i, tm_clk_i, irq_i, cause_i,
163
        cyc_o, stb_o, ack_i, sel_o, we_o, adr_o, dat_i, dat_o, sr_o, cr_o, rb_i,
164
        state);
165
input [63:0] hartid_i;
166
input [63:0] sig_i;
167
input rst_i;
168
input clk_i;
169
input tm_clk_i;                         // 100 MHz
170
input [2:0] irq_i;
171
input [8:0] cause_i;
172
output reg cyc_o;
173
output reg stb_o;
174
input ack_i;
175
output reg [15:0] sel_o;
176
output reg we_o;
177
output reg [31:0] adr_o;
178
input [127:0] dat_i;
179
output reg [127:0] dat_o;
180
output reg sr_o;
181
output reg cr_o;
182
input rb_i;
183
output reg [7:0] state;
184
 
185
// Wall clock timing parameter. Number of tm_clk_i cycles for 1s interval
186
parameter WCTIME1S = 32'd100000000;
187
 
188
parameter RST_ADDR = 32'hFFFC0100;
189
parameter RESET = 8'd0;
190
parameter IFETCH = 8'd1;
191
parameter IFETCH_ACK = 8'd2;
192
parameter IFETCH_NACK = 8'd3;
193
parameter REGFETCH = 8'd4;
194
parameter DECODE = 8'd5;
195
parameter EXECUTE = 8'd6;
196
parameter MEMORY = 8'd7;
197
parameter MEMORY_NACK = 8'd8;
198
parameter MULDIV2 = 8'd9;
199
parameter AMOOP = 8'd10;
200
parameter AMOMEM = 8'd11;
201
parameter word = 2'd3;
202
parameter half = 2'd2;
203
parameter char = 2'd1;
204
parameter byt_ = 2'd0;
205
 
206
integer n, m;
207
reg [63:0] sema;
208
reg [43:0] brkstack [0:4];
209
reg [31:0] tvec [0:7];
210
reg [2:0] ol;
211
reg [2:0] im;
212
reg [7:0] pl;
213
reg [31:0] pc,opc;
214
reg [31:0] ir;
215
wire [5:0] opcode = ir[5:0];
216
wire [5:0] funct = ir[31:26];
217
wire [4:0] func5 = ir[25:21];
218
wire [3:0] func4 = ir[25:22];
219
reg [1:0] opsize;
220
reg [31:0] ibuf_adr [0:7];
221
reg [31:0] ibuf [0:7];
222
reg [2:0] ibuf_cnt;
223
reg rfwr;
224
reg [4:0] Ra, Rb, Rc, Rt;
225
reg [63:0] regfile [0:31];
226
wire [63:0] rfoa = regfile[Ra];
227
wire [63:0] rfob = regfile[Rb];
228
wire [63:0] rfoc = regfile[Rc];
229
reg [63:0] a,b,c,res,amores;
230
reg [31:0] rasstack [0:511];
231
reg [8:0] rassp;
232
reg [4:0] regLR = 5'd29;
233
 
234
// CSR's
235
reg [8:0] cause;
236
reg [63:0] scratch;
237
reg [63:0] tick;
238
reg [63:0] wctime, times;
239
reg [63:0] instret;
240
 
241
wire [127:0] produ;// = a * b;
242
wire [127:0] prods;// = $signed(a) * $signed(b);
243
wire [127:0] prodsu;// = $signed(a) * b;
244
wire [2:0] npl = ir[23:16] | a;
245
wire [63:0] sum = a + b;
246
wire [63:0] dif = a - b;
247
wire [31:0] eandx = a + (b << ir[22:21]);
248
wire [63:0] am8 = a - 32'd8;     // for link
249
wire [31:0] xIncea = ir[25] ? a + {{59{ir[25]}},ir[25:21]} : a;  // for POP / PUSH
250
 
251
reg [63:0] opimp;
252
reg [63:0] fnimp;
253
 
254
function [23:0] regname;
255
input [4:0] regno;
256
case(regno)
257
5'd0:   regname = "r0";
258
5'd1:   regname = "r1";
259
5'd2:   regname = "r2";
260
5'd3:   regname = "r3";
261
5'd4:   regname = "r4";
262
5'd5:   regname = "r5";
263
5'd6:   regname = "r6";
264
5'd7:   regname = "r7";
265
5'd8:   regname = "r8";
266
5'd9:   regname = "r9";
267
5'd10:  regname = "r10";
268
5'd11:  regname = "r11";
269
5'd12:  regname = "r12";
270
5'd13:  regname = "r13";
271
5'd14:  regname = "r14";
272
5'd15:  regname = "r15";
273
5'd16:  regname = "r16";
274
5'd17:  regname = "r17";
275
5'd18:  regname = "r18";
276
5'd19:  regname = "r19";
277
5'd20:  regname = "r20";
278
5'd21:  regname = "r21";
279
5'd22:  regname = "r22";
280
5'd23:  regname = "r23";
281
5'd24:  regname = "r24";
282
5'd25:  regname = "r25";
283
5'd26:  regname = "r26";
284
5'd27:  regname = "r27";
285
5'd28:  regname = "r28";
286
5'd29:  regname = "lr";
287
5'd30:  regname = "bp";
288
5'd31:  regname = "sp";
289
endcase
290
endfunction
291
 
292
always @*
293
begin
294
m <= 4'hF;
295
for (n = 0; n < 8; n = n + 1)
296
        if (pc==ibuf_adr[n])
297
                m <= n;
298
end
299
 
300
reg [127:0] din; // input data latch
301
reg [3:0] dshift;
302
wire [7:0] byte_in = din >> {dshift[3:0],3'b0};
303
wire [15:0] char_in = din >> {dshift[3:1],4'h0};
304
wire [31:0] half_in = din >> {dshift[3:2],5'h0};
305
wire [63:0] word_in = din >> {dshift[3],6'h0};
306
 
307
wire [127:0] shlo = {64'd0,a} << b[5:0];
308
wire [127:0] shro = {a,64'd0} >> b[5:0];
309
wire [31:0]  asro32 = a[31] ? ~(32'hFFFFFFFFFFFFFFFF >> b[5:0]) | shro[95:64] : shro[95:64];
310
 
311
wire [63:0] bfo;
312
wire [63:0] shiftwo;
313
wire [31:0] shiftho;
314
 
315
FT64_shift uws1
316
(
317
        .instr(ir),
318
        .a(a),
319
        .b(b),
320
        .res(shiftwo),
321
        .ov()
322
);
323
 
324
FT64_shifth uhws1
325
(
326
        .instr(ir),
327
        .a(a[31:0]),
328
        .b(b[31:0]),
329
        .res(shiftho),
330
        .ov()
331
);
332
 
333
FT64_bitfield ubf1
334
(
335
        .inst(ir),
336
        .a(a),
337
        .b(b),
338
        .o(bfo),
339
        .masko()
340
);
341
 
342
reg div_ld, mul_ld;
343
reg [4:0] mul_cnt;
344
wire div_done;
345
wire [63:0] div_qo, div_ro;
346
wire div_sgn = opcode==`DIVI || opcode==`MODI || (opcode==`R2 && (funct==`DIVMOD));
347
wire div_sgnus = opcode==`DIVSUI || opcode==`MODSUI || (opcode==`R2 && (funct==`DIVMODSU));
348
 
349
`ifdef EXT_M
350
FT64_divider udiv1
351
(
352
        .rst(rst_i),
353
        .clk(clk_i),
354
        .ld(div_ld),
355
        .abort(),
356
        .sgn(div_sgn),
357
        .sgnus(div_sgnus),
358
        .a(a),
359
        .b(b),
360
        .qo(div_qo),
361
        .ro(div_ro),
362
        .dvByZr(),
363
        .done(div_done),
364
        .idle()
365
);
366
 
367
FT64_mul umul1
368
(
369
        .CLK(clk_i),
370
        .A(a),
371
        .B(b),
372
        .P(prods)
373
);
374
 
375
FT64_mulu umul2
376
(
377
        .CLK(clk_i),
378
        .A(a),
379
        .B(b),
380
        .P(produ)
381
);
382
 
383
FT64_mulsu umul3
384
(
385
        .CLK(clk_i),
386
        .A(a),
387
        .B(b),
388
        .P(prodsu)
389
);
390
`endif
391
 
392
wire takb;
393
 
394
FT64_EvalBranch ube1
395
(
396
        .instr(ir),
397
        .a(a),
398
        .b(b),
399
        .takb(takb)
400
);
401
 
402
always @(posedge clk_i)
403
if (rst_i)
404
        mul_cnt <= 5'd19;
405
else begin
406
        if (mul_ld)
407
                mul_cnt <= 5'd1;
408
        else if (mul_cnt < 5'd19)
409
                mul_cnt <= mul_cnt + 5'd1;
410
end
411
wire mul_done = mul_cnt==5'd19;
412
 
413
always @(posedge clk_i)
414
        if (ack_i)
415
                din <= dat_i;
416
always @(posedge clk_i)
417
        if (ack_i)
418
                dshift <= adr_o[3:0];
419
 
420
reg rbl;
421
always @(posedge clk_i)
422
        if (ack_i)
423
                rbl <= rb_i;
424
 
425
always @(posedge clk_i)
426
        if (rst_i)
427
                tick <= 63'd0;
428
        else
429
                tick <= tick + 64'd1;
430
 
431
always @(posedge clk_i)
432
if (rst_i)
433
        state <= RESET;
434
else begin
435
 
436
// Cause these signals to pulse for just one clock cycle. They are set
437
// active below.
438
div_ld <= `FALSE;
439
mul_ld <= `FALSE;
440
rfwr <= `FALSE;
441
 
442
case(state)
443
 
444
// RESET:
445
// Reset only the signals critical to the proper operation of the core.
446
// This includes setting the PC address and deactivating the bus
447
// controls.
448
RESET:
449
        begin
450
        im <= 3'd7;
451
        ol <= 3'd0;
452
        pl <= 8'h00;
453
        pc <= RST_ADDR;
454
        cyc_o <= `LOW;
455
        stb_o <= `LOW;
456
        we_o <= `LOW;
457
        sel_o <= 16'h0000;
458
        adr_o <= 32'hFFFFFFFF;
459
        instret <= 64'd0;
460
        opimp <= 64'h000F_F1FF_3FFF_67DD;
461
`ifdef EXT_A
462
        opimp[47] <= 1'b1;
463
`endif
464
`ifdef EXT_M
465
        opimp[63:55] <= 8'h77;
466
`endif
467
        fnimp <= 64'h8005_701F_A1FF_87F4;
468
`ifdef EXT_M
469
        fnimp[63:55] <= 8'h77;
470
`endif
471
        goto(IFETCH);
472
        end
473
 
474
// IFETCH:
475
// Fetch instructions from memory located by the program counter. A fully
476
// associative buffer (cache) of the most recently used eight instructions
477
// is maintained. A memory access won't be required if the instruction can
478
// be found in the buffer.
479
// Also update the register file for the previous instruction. Rather than
480
// have another state in the state machine to perform the register update
481
// it is done here to improve performance.
482
IFETCH:
483
        begin
484
                opc <= pc;
485
                instret <= instret + 64'd1;
486
                if (irq_i > im) begin
487
                        ir <= {13'd0,irq_i,1'b0,cause_i,`BRK};
488
                        goto(DECODE);
489
                end
490
                else if (m[3]) begin
491
                        cyc_o <= `HIGH;
492
                        stb_o <= `HIGH;
493
                        sel_o <= 16'hF << {pc[3:2],2'b0};
494
                        adr_o <= pc;
495
                        goto(IFETCH_ACK);
496
                end
497
                else begin
498
                        ir <= ibuf[m];
499
                        pc <= pc + 32'd4;
500
                        $display("ir: %h (from ibuf)", ibuf[m]);
501
                        goto(DECODE);
502
                end
503
        end
504
IFETCH_ACK:
505
        if (ack_i) begin
506
                cyc_o <= `LOW;
507
                stb_o <= `LOW;
508
                sel_o <= 16'h0000;
509
                //adr_o <= 32'hFFFFFFFF;
510
                goto(IFETCH_NACK);
511
        end
512
IFETCH_NACK:
513
        if (~ack_i) begin
514
                ir <= half_in;
515
                ibuf[ibuf_cnt] <= half_in;
516
                ibuf_adr[ibuf_cnt] <= pc;
517
                ibuf_cnt <= ibuf_cnt + 3'd1;
518
                pc <= pc + 32'd4;
519
                $display("ir: %h", half_in);
520
                goto(DECODE);
521
        end
522
 
523
// DECODE:
524
// Setup for register file access. Ra, Rb, Rc are almost always decoded from
525
// the same spot in the instruction register to keep the decoding simple and
526
// access to the register file fast. For the call instruction Ra is forced to
527
// r31 since it doesn't come from the ir. Rt tends to float around depending on
528
// the instruction.
529
// Several instructions which do not have register operands (JMP,NOP,RTI, and
530
// BRK) are executed directly in the decode stage to improve performance.
531
DECODE:
532
        begin
533
                goto(REGFETCH);
534
                Ra <= ir[10:6];
535
                Rb <= ir[15:11];
536
                Rc <= ir[20:16];
537
                Rt <= 5'd0;
538
                opsize <= word;
539
                if (!opimp[opcode])
540
                        exe_brk(9'd485);        // unimplemented
541
                case(opcode)
542
                `BRK:
543
                        exe_brk(ir[14:6]);
544
                `R2:
545
                        begin
546
                                if (!fnimp[opcode])
547
                                        exe_brk(9'd485);        // unimplemented
548
                                Rt <= ir[20:16];
549
                                case(funct)
550
                                `R1:
551
                                        case(func5)
552
                                        `ABS,`NOT:      Rt <= ir[15:11];
553
                                        endcase
554
                                `ADD,`SUB:
555
                                    opsize <= ir[22:21];
556
                                `AND,`OR,`XOR:
557
                                        Rt <= ir[25:21];
558
                                `SHIFTB,`SHIFTC,`SHIFTH,`SHIFTW:
559
                                        Rt <= ir[25] ? ir[15:11] : ir[20:16];
560
                                // The SYNC instruction is treated as a NOP since this machine
561
                                // is strictly in order.
562
                                `SYNC:  goto(IFETCH);
563
                                `SB,`SC,`SH,`SW,`SWC:   Rt <= 5'd0;
564
                                endcase
565
                        end
566
                `NOP:   goto(IFETCH);
567
                `JMP:
568
                        begin
569
                        pc <= {pc[31:28],ir[31:6],2'b00};
570
                        goto(IFETCH);
571
                        end
572
                `CALL:
573
                        Rt <= regLR;
574
                `JAL:
575
                        Rt <= ir[15:11];
576
                `CSR:
577
                        Rt <= ir[15:11];
578
                `QOPI:
579
                        begin
580
                        Ra <= ir[15:11];
581
                        Rt <= ir[15:11];
582
                        end
583
                `BITFLD:
584
                        Rt <= ir[15:11];
585
                `ADD,`CMP,`CMPU,`AND,`OR,`XOR,
586
`ifdef EXT_M
587
                `MULU,`MUL,`MULSU,
588
                `DIVI,`DIVUI,`DIVSUI,`MODI,`MODUI,`MODSUI,
589
`endif
590
                `LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWR:
591
                        Rt <= ir[15:11];
592
                `SB,`SC,`SH,`SW,`SWC:
593
                        Rt <= 5'd0;
594
`ifdef EXT_A
595
                `AMO:
596
                        Rt <= ir[31] ? ir[15:11] : ir[20:16];
597
`endif
598
                default: ;
599
                endcase
600
        end
601
 
602
// REGFETCH:
603
// Set operands from the register file, or the instruction register for
604
// immediate operands.
605
REGFETCH:
606
        begin
607
                goto(EXECUTE);
608
                a <= rfoa;
609
                b <= rfob;
610
                case(opcode)
611
                `R2:
612
                        case(funct)
613
                        `SHIFTW,`SHIFTB,`SHIFTC,`SHIFTH:
614
                                if (ir[25]) b <= ir[21:16];
615
                        `AND,`OR,`XOR:
616
                                c <= rfoc;
617
`ifdef EXT_M
618
                        `MUL,`MULU,`MULSU:
619
                                mul_ld <= `TRUE;
620
                        `DIVMOD,`DIVMODU,`DIVMODSU:
621
                                div_ld <= `TRUE;
622
`endif
623
                        `LB,`LBU,`LH,`LHU,`LC,`LCU,`LW,`LWR,
624
                        `SB,`SC,`SH,`SW,`SWC:
625
                                c <= rfoc;
626
                        endcase
627
                `ADD,`CMP,`CMPU,`AND,`OR,`XOR:
628
                        b <= {{48{ir[31]}},ir[31:16]};
629
                `SccI:
630
                        b <= {{52{ir[27]}},ir[27:16]};
631
`ifdef EXT_M
632
                `MUL,`MULU,`MULSU:
633
                        begin
634
                        b <= {{48{ir[31]}},ir[31:16]};
635
                        mul_ld <= `TRUE;
636
                        end
637
                `DIVI,`MODI,`DIVUI,`DIVSUI,`MODUI,`MODSUI:
638
                        begin
639
                        b <= {{48{ir[31]}},ir[31:16]};
640
                        div_ld <= `TRUE;
641
                        end
642
`endif
643
                `QOPI:
644
                        begin
645
                                case(ir[10:8])
646
                                3'd0,3'd3:      // OR, XOR
647
                                        case(ir[7:6])
648
                                        2'd0:   b <= {{48{1'b0}},ir[31:16]};
649
                                        2'd1:   b <= {{32{1'b0}},ir[31:16]} << 16;
650
                                        2'd2:   b <= {{16{1'b0}},ir[31:16]} << 32;
651
                                        2'd3:   b <= {ir[31:16]} << 48;
652
                                        endcase
653
                                3'd1:   // ADD
654
                                        case(ir[7:6])
655
                                        2'd0:   b <= {{48{ir[31]}},ir[31:16]};
656
                                        2'd1:   b <= {{32{ir[31]}},ir[31:16]} << 16;
657
                                        2'd2:   b <= {{16{ir[31]}},ir[31:16]} << 32;
658
                                        2'd3:   b <= {ir[31:16]} << 48;
659
                                        endcase
660
                                3'd2:   // AND
661
                                        case(ir[7:6])
662
                                        2'd0:   b <= {{48{1'b1}},ir[31:16]};
663
                                        2'd1:   b <= {{32{1'b1}},ir[31:16],16'hFFFF};
664
                                        2'd2:   b <= {{16{1'b1}},ir[31:16],32'hFFFFFFFF};
665
                                        2'd3:   b <= {ir[31:16],48'hFFFFFFFFFFFF};
666
                                        endcase
667
                                default:        b <= 64'd0;
668
                                endcase
669
                        end
670
                `Bcc0,`Bcc1,`BccR,`BBc0,`BBc1:
671
                        c <= rfoc;
672
                `BEQ0,`BEQ1:
673
                        b <= {{55{ir[19]}},ir[19:11]};
674
                `JAL:
675
                        b <= {{48{ir[31]}},ir[31:16]};
676
                `LB,`LBU,`LH,`LHU,`LC,`LCU,`LW,`LWR,
677
                `SB,`SC,`SH,`SW,`SWC:
678
                        begin
679
                        b <= {{48{ir[31]}},ir[31:16]};
680
                        c <= rfob;
681
                        end
682
`ifdef EXT_A
683
                `AMO:
684
                        if (ir[31])
685
                                b <= {{59{ir[20]}},ir[20:16]};
686
`endif
687
                endcase
688
        end
689
 
690
// EXECUTE:
691
// Execute the instruction. Compute results and begin any memory access.
692
EXECUTE:
693
        begin
694
                goto(IFETCH);
695
                case(opcode)
696
                `R2:
697
                        case(funct)
698
                        `RTE:
699
                                begin
700
                                        pc <= {brkstack[0][43:14],2'b00};
701
                                        pl <= brkstack[0][13:6];
702
                                        ol <= brkstack[0][5:3];
703
                                        im <= brkstack[0][2:0];
704
                                        for (n = 0; n < 4; n = n + 1)
705
                                                brkstack[n] <= brkstack[n+1];
706
                                        sema[0] <= 1'b0;
707
                                        sema[ir[21:16]|a[5:0]] <= 1'b0;
708
                                end
709
                        `R1:
710
                                case(func5)
711
                                `ABS:   begin res <= a[63] ? -a : a; rfwr <= `TRUE; end
712
                                `NOT:   begin res <= a!=0 ? 64'd0 : 64'd1; rfwr <= `TRUE; end
713
                                endcase
714
                        `SEI:   im <= a[2:0] | ir[18:16];
715
                        `SHIFTW:
716
                            begin
717
                            rfwr <= `TRUE;
718
                            res <= shiftwo;
719
                end
720
                        `SHIFTH:
721
                begin
722
                rfwr <= `TRUE;
723
                case(func4)
724
                `SHL,`SHLI:    res <= {32'd0,shiftho};
725
                `SHR,`SHRI:    res <= {32'd0,shiftho};
726
                `ASL,`ASLI:    res <= {{32{shiftho[31]}},shiftho};
727
                `ASR,`ASRI:    res <= {{32{shiftho[31]}},shiftho};
728
                `ROL,`ROLI: begin
729
                            res[31:0] <= shiftho;
730
                            res[63:32] <= {32{shiftho[31]}};
731
                            end
732
                `ROR,`RORI: begin
733
                            res[31:0] <= shiftho;
734
                            res[63:32] <= {32{shiftho[31]}};
735
                            end
736
                endcase
737
                end
738
            `ADD:       begin
739
                    rfwr <= `TRUE;
740
                    case(opsize)
741
                    word:   res <= sum;
742
                    half:   res <= {{32{sum[31]}},sum[31:0]};
743
                    char:   res <= {{48{sum[15]}},sum[15:0]};
744
                    byt_:   res <= {{56{sum[7]}},sum[7:0]};
745
                    endcase
746
                    end
747
            `SUB:       begin
748
                    rfwr <= `TRUE;
749
                    case(opsize)
750
                    word:   res <= dif;
751
                    half:   res <= {{32{dif[31]}},dif[31:0]};
752
                    char:   res <= {{48{dif[15]}},dif[15:0]};
753
                    byt_:   res <= {{56{dif[7]}},dif[7:0]};
754
                    endcase
755
                    end
756
                        `Scc:   begin
757
                                        rfwr <= `TRUE;
758
                                        case(ir[25:23])
759
                                        3'd0:   res <= $signed(a) < $signed(b) ? 64'hFFFFFFFFFFFFFFFF : a==b ? 64'h0 : 64'h1;
760
                                        3'd2:   res <= a==b;
761
                                        3'd3:   res <= a!=b;
762
                                        3'd4:   res <= $signed(a) < $signed(b);
763
                                        3'd5:   res <= $signed(a) >= $signed(b);
764
                                        3'd6:   res <= $signed(a) <= $signed(b);
765
                                        3'd7:   res <= $signed(a) > $signed(b);
766
                                        endcase
767
                                        end
768
                        `Sccu:  begin
769
                                        rfwr <= `TRUE;
770
                                        case(ir[25:23])
771
                                        3'd0:   res <= a < b ? 64'hFFFFFFFFFFFFFFFF : a==b ? 64'h0 : 64'h1;
772
                                        3'd2:   res <= a==b;
773
                                        3'd3:   res <= a!=b;
774
                                        3'd4:   res <= a < b;
775
                                        3'd5:   res <= a >= b;
776
                                        3'd6:   res <= a <= b;
777
                                        3'd7:   res <= a > b;
778
                                        endcase
779
                                        end
780
`ifdef EXT_M
781
                        `MULU:  if (mul_done) begin
782
                                                res <= ir[25:23]==3'd0 ? produ[63:0] : produ[127:64];
783
                                                rfwr <= `TRUE;
784
                                                goto(IFETCH);
785
                                        end
786
                                        else
787
                                                goto(EXECUTE);
788
                        `MUL:   if (mul_done) begin
789
                                                res <= ir[25:23]==3'd0 ? prods[63:0] : prods[127:64];
790
                                                rfwr <= `TRUE;
791
                                                goto(IFETCH);
792
                                        end
793
                                        else
794
                                                goto(EXECUTE);
795
                        `MULSU: if (mul_done) begin
796
                                                res <= ir[25:23]==3'd0 ? prodsu[63:0] : prodsu[127:64];
797
                                                rfwr <= `TRUE;
798
                                                goto(IFETCH);
799
                                        end
800
                                        else
801
                                                goto(EXECUTE);
802
                        // For divide stay in the EXECUTE state until the divide is done.
803
                        `DIVMOD,`DIVMODU,`DIVMODSU:
804
                                        if (div_done) begin
805
                                                res <= ir[25:23]==3'd0 ? div_qo : div_ro;
806
                                                rfwr <= `TRUE;
807
                                                goto(IFETCH);
808
                                        end
809
                                        else
810
                                                goto(EXECUTE);
811
`endif
812
                        `AND:   begin res <= a & b & c; rfwr <= `TRUE; end
813
                        `OR:    begin res <= a | b | c; rfwr <= `TRUE; end
814
                        `XOR:   begin res <= a ^ b ^ c; rfwr <= `TRUE; end
815
                        `LEAX:
816
                                begin
817
                                        rfwr <= `TRUE;
818
                                        res <= eandx;
819
                                end
820
                        `LB,`LBU:       wb_read(16'h01 << eandx[3:0], eandx);
821
                        `LC,`LCU:       wb_read(16'h03 << {eandx[3:1],1'b0}, eandx);
822
                        `LH,`LHU:       wb_read(16'h0F << {eandx[3:2],2'b0}, eandx);
823
                        `LW:            wb_read(16'hFF << {eandx[3],3'b0}, eandx);
824
                        `LWR: begin wb_read(16'hFF << {eandx[3],3'b0}, eandx); sr_o <= `HIGH; end
825
                        `SB:    wb_write(16'h01 << eandx[3:0],eandx,{8{c[7:0]}});
826
                        `SC:    wb_write(16'h03 << {eandx[3:1],1'b0},eandx,{4{c[15:0]}});
827
                        `SH:    wb_write(16'h0F << {eandx[3:2],2'b0},eandx,{2{c[31:0]}});
828
                        `SW:    wb_write(16'hFF << {eandx[3],3'b0},eandx,c);
829
                        `SWC:
830
                                begin
831
                                        cr_o <= `HIGH;
832
                                        wb_write(16'hFF << {eandx[3],3'b0},eandx,c);
833
                                end
834
                        endcase
835
                `ADD:   begin res <= sum; rfwr <= `TRUE; end
836
                `CMP:   begin res <= $signed(a) < $signed(b) ? 64'hFFFFFFFFFFFFFFFF : a==b ? 64'h0 : 64'h1; rfwr <= `TRUE; end
837
                `CMPU:  begin res <= a < b ? 64'hFFFFFFFFFFFFFFFF : a==b ? 64'h0 : 64'h1; rfwr <= `TRUE; end
838
                `SccI:
839
                                begin
840
                                rfwr <= `TRUE;
841
                                case(ir[31:28])
842
                                4'd2:   res <= a==b;
843
                                4'd3:   res <= a!=b;
844
                                4'd4:   res <= $signed(a) < $signed(b);
845
                                4'd5:   res <= $signed(a) >= $signed(b);
846
                                4'd6:   res <= $signed(a) <= $signed(b);
847
                                4'd7:   res <= $signed(a) > $signed(b);
848
                                4'd12:  res <= a < b;
849
                                4'd13:  res <= a >= b;
850
                                4'd14:  res <= a <= b;
851
                                4'd15:  res <= a > b;
852
                                endcase
853
                                end
854
`ifdef EXT_M
855
                `MULU:  if (mul_done) begin res <= produ[63:0]; rfwr <= `TRUE; end else goto(EXECUTE);
856
                `MUL:   if (mul_done) begin res <= prods[63:0]; rfwr <= `TRUE; end else goto(EXECUTE);
857
                `MULSU: if (mul_done) begin res <= prodsu[63:0]; rfwr <= `TRUE; end else goto(EXECUTE);
858
                // Stay in execute state until divide is done.
859
                `DIVI,`DIVUI,`DIVSUI:
860
                                if (div_done) begin
861
                                        res <= div_qo;
862
                                        rfwr <= `TRUE;
863
                                end
864
                                else
865
                                        goto(EXECUTE);
866
                `MODI,`MODUI,`MODSUI:
867
                                if (div_done) begin
868
                                        res <= div_ro;
869
                                        rfwr <= `TRUE;
870
                                end
871
                                else
872
                                        goto(EXECUTE);
873
`endif
874
                `BITFLD:        begin res <= bfo; rfwr <= `TRUE; end
875
                `AND:   begin res <= a & b; rfwr <= `TRUE; end
876
                `OR:    begin res <= a | b; rfwr <= `TRUE; end
877
                `XOR:   begin res <= a ^ b; rfwr <= `TRUE; end
878
                `QOPI:
879
                      begin
880
                      rfwr <= `TRUE;
881
                      case(ir[10:8])
882
                      3'd0:   res <= a | b;
883
                      3'd1:   res <= a + b;
884
                      3'd2:   res <= a & b;
885
                      3'd3:   res <= a ^ b;
886
                      endcase
887
                      end
888
                `Bcc0,`Bcc1,`BEQ0,`BEQ1,`BBc0,`BBc1:
889
                        begin
890
                                if (takb)
891
                                        pc <= pc + {{21{ir[31]}},ir[31:22],ir[0],2'b00};
892
                                $display("%h: br %h", opc, pc + {{21{ir[31]}},ir[31:22],ir[0],2'b00});
893
                        end
894
                `BccR:
895
                        begin
896
                                if (takb)
897
                                        pc <= c;
898
                                $display("%h: br %h", opc, c);
899
                        end
900
                `JAL:
901
                        begin
902
                                pc <= {sum[31:2],2'b00};
903
                                rfwr <= `TRUE;
904
                                res <= pc;
905
                        end
906
                `CALL:
907
                        begin
908
                                pc <= {pc[31:28],ir[31:6],2'b00};
909
                                res <= pc;
910
                                rfwr <= `TRUE;
911
                                $display("%h: jal %h", opc, {pc[31:28],ir[31:6],2'b00});
912
                        end
913
                `REX:
914
                        begin
915
                                ol <= ir[13:11];
916
                                case(ir[13:11])
917
                                3'd0:           pl <= 8'h00;
918
                                3'd1:           pl <= 8'h01;
919
                                default:        pl <= (npl < 2) ? {5'd0,ir[13:11]} : npl;
920
                                endcase
921
                                if (ir[13:11]!=3'd0)
922
                                        pc <= tvec[ir[13:11]];
923
                                im <= ir[26:24];
924
                        end
925
                `CSR:
926
                        begin
927
                                case(ir[31:30])
928
                                2'd0:   begin read_csr(ir[26:16],res); rfwr <= `TRUE; end
929
                                default:begin
930
                                                        rfwr <= `TRUE;
931
                                                        read_csr(ir[26:16],res);
932
                                                        write_csr(ir[26:16],ir[31:30],a);
933
                                                end
934
                                endcase
935
                        end
936
                `LB,`LBU:       wb_read(16'h01 << sum[3:0],sum);
937
                `LC,`LCU:       wb_read(16'h03 << {sum[3:1],1'b0},sum);
938
                `LH,`LHU:       wb_read(16'h0F << {sum[3:2],2'b0},sum);
939
                `LW:            wb_read(16'hFF << {sum[3],3'b0},sum);
940
                `LWR: begin wb_read(16'hFF << {sum[3],3'b0},sum); sr_o <= `HIGH; end
941
                `SB:    wb_write(16'h01 << sum[3:0],sum,{8{c[7:0]}});
942
                `SC:    wb_write(16'h03 << {sum[3:1],1'b0},sum,{4{c[15:0]}});
943
                `SH:    wb_write(16'h0F << {sum[3:2],2'b0},sum,{2{c[31:0]}});
944
                `SW:    wb_write(16'hFF << {sum[3],3'b0},sum,c);
945
                `SWC:
946
                        begin
947
                                cr_o <= `HIGH;
948
                                wb_write(16'hFF << {sum[3],3'b0},sum,c);
949
                        end
950
`ifdef EXT_A
951
                `AMO:
952
                        case(ir[22:21])
953
                        byt_:   wb_read(16'h01 << sum[3:0],a);
954
                        char:   wb_read(16'h03 << {sum[3:1],1'b0},a);
955
                        half:   wb_read(16'h0F << {sum[3:2],2'b0},a);
956
                        word:   wb_read(16'hFF << {sum[3],3'b0},a);
957
                        endcase
958
`endif
959
                endcase
960
        end
961
 
962
// MEMORY:
963
// Finish memory cycle started in EXECUTE by waiting for an ack. Latch input
964
// data. The data is registered here before subsequent use because it's likely
965
// coming from a large mux. We don't want to cascade the mux and the shift
966
// operation required to align the data into a single clock cycle.
967
// If an AMO operation is in progress keep the cycle active.
968
MEMORY:
969
        if (ack_i) begin
970
                goto(MEMORY_NACK);
971
`ifdef EXT_A
972
                if (opcode!=`AMO)
973
`endif
974
                        cyc_o <= `LOW;
975
                stb_o <= `LOW;
976
                we_o <= `LOW;
977
                sel_o <= 16'h0000;
978
                sr_o <= `LOW;
979
                cr_o <= `LOW;
980
        end
981
 
982
// Wait for ack to go back low again. Nomrally ack should go low immediately
983
// when the bus cycle is terminated within the same clock cycle. However some
984
// bus slaves don't put ack low until the clock edge when seeing the
985
// terminated bus cycle. We want to ensure that a second bus cycle isn't
986
// started until ack is low or the ack could be mistakenly accepted.
987
MEMORY_NACK:
988
        if (~ack_i) begin
989
                goto(IFETCH);
990
                case(opcode)
991
                `R2:
992
                        case(funct)
993
                `LB:    begin res <= {{56{byte_in[7]}},byte_in}; rfwr <= `TRUE; end
994
            `LBU:   begin res <= {{56{1'b0}},byte_in}; rfwr <= `TRUE; end
995
            `LC:    begin res <= {{48{char_in[15]}},char_in}; rfwr <= `TRUE; end
996
            `LCU:   begin res <= {{48{1'b0}},char_in}; rfwr <= `TRUE; end
997
            `LH:    begin res <= {{32{half_in[31]}},half_in}; rfwr <= `TRUE; end
998
            `LHU:   begin res <= {{32{1'b0}},half_in}; rfwr <= `TRUE; end
999
            `LW:    begin res <= word_in; rfwr <= `TRUE; end
1000
                        `SWC:   sema[0] <= rbl;
1001
                        endcase
1002
                `LB:    begin res <= {{56{byte_in[7]}},byte_in}; rfwr <= `TRUE; end
1003
                `LBU:   begin res <= {{56{1'b0}},byte_in}; rfwr <= `TRUE; end
1004
                `LC:    begin res <= {{48{char_in[15]}},char_in}; rfwr <= `TRUE; end
1005
                `LCU:   begin res <= {{48{1'b0}},char_in}; rfwr <= `TRUE; end
1006
                `LH:    begin res <= {{32{half_in[31]}},half_in}; rfwr <= `TRUE; end
1007
                `LHU:   begin res <= {{32{1'b0}},half_in}; rfwr <= `TRUE; end
1008
                `LW:    begin res <= word_in; rfwr <= `TRUE; end
1009
                `SWC:   sema[0] <= rbl;
1010
`ifdef EXT_A
1011
                `AMO:   begin
1012
                                        goto(AMOOP);
1013
                                        case(ir[22:21])
1014
                                        byt_:   begin
1015
                                                                res <= {{56{byte_in[7]}},byte_in};
1016
                                                                a <= {{56{byte_in[7]}},byte_in};
1017
                                                                rfwr <= `TRUE;
1018
                                                        end
1019
                                        char:   begin res <= {{48{char_in[15]}},char_in}; a <= {{48{char_in[15]}},char_in}; rfwr <= `TRUE; end
1020
                                        half:   begin res <= {{32{half_in[31]}},half_in}; a <= {{32{half_in[31]}},half_in}; rfwr <= `TRUE; end
1021
                                        word:   begin res <= word_in; a <= word_in; rfwr <= `TRUE; end
1022
                                        endcase
1023
                                end
1024
`endif
1025
                endcase
1026
        end
1027
`ifdef EXT_A
1028
AMOOP:
1029
        begin
1030
                goto(AMOMEM);
1031
                case(funct)
1032
                `AMOSWAP,`AMOSWAPI:     amores <= b;
1033
                `AMOADD,`AMOADDI:       amores <= a + b;
1034
                `AMOAND,`AMOANDI:       amores <= a & b;
1035
                `AMOOR,`AMOORI:         amores <= a | b;
1036
                `AMOXOR,`AMOXORI:       amores <= a ^ b;
1037
                `AMOSHL,`AMOSHLI,
1038
                `AMOSHR,`AMOSHRI,
1039
                `AMOASR,`AMOASRI,
1040
                `AMOROL,`AMOROLI:
1041
                        case(ir[22:21])
1042
                        half:           amores <= shiftho;
1043
                        default:        amores <= shiftwo;
1044
                        endcase
1045
                `AMOMIN,`AMOMINI:       amores <= $signed(a) < $signed(b) ? a : b;
1046
                `AMOMAX,`AMOMAXI:       amores <= $signed(a) > $signed(b) ? a : b;
1047
                `AMOMINU,`AMOMINUI:     amores <= a < b ? a : b;
1048
                `AMOMAXU,`AMOMAXUI:     amores <= a > b ? a : b;
1049
                default:        ;
1050
                endcase
1051
        end
1052
AMOMEM:
1053
        begin
1054
                goto(MEMORY);
1055
                ir[5:0] <= `NOP; // <- force memory nack back to ifetch
1056
                case(ir[22:21])
1057
                byt_:   wb_write(16'h01 << adr_o[3:0],adr_o,{8{amores[7:0]}});
1058
                char:   wb_write(16'h03 << {adr_o[3:1],1'b0},adr_o,{4{amores[15:0]}});
1059
                half:   wb_write(16'h0F << {adr_o[3:2],2'b0},adr_o,{2{amores[31:0]}});
1060
                word:   wb_write(16'hFF << {adr_o[3],3'b0},adr_o,amores);
1061
                endcase
1062
        end
1063
`endif
1064
endcase
1065
 
1066
// Handle the register file update. The update is caused in a couple of
1067
// different states. There may be two updates for a single instruction.
1068
// Note that r0 is always forced to zero. A write to r0 may be needed
1069
// before it's used anywhere.
1070
if (rfwr) begin
1071
        regfile[Rt] <= |Rt ? res : 64'd0;
1072
        if (|Rt)
1073
                $display("%s=%h",regname(Rt),res);
1074
end
1075
 
1076
$display("Time: %d", $time);
1077
$display("Tick: %d Instret: %d", tick, instret);
1078
 
1079
end
1080
 
1081
always @(posedge tm_clk_i)
1082
if (rst_i)
1083
        wctime <= 64'd1;
1084
else begin
1085
        if (wctime[31:0]==WCTIME1S) begin
1086
                wctime[31:0] <= 32'd1;
1087
                wctime[63:32] <= wctime[63:32] + 32'd1;
1088
        end
1089
        else
1090
                wctime[31:0] <= wctime[31:0] + 32'd1;
1091
end
1092
always @(posedge clk_i)
1093
        times <= wctime;
1094
 
1095
task exe_brk;
1096
input [8:0] caus;
1097
begin
1098
        for (n = 0; n < 4; n = n + 1)
1099
                brkstack[n+1] <= brkstack[n];
1100
        brkstack[0] <= {pc[31:2],pl,ol,im};
1101
        if (ir[15]==1'b0)
1102
                im <= ir[18:16];
1103
        ol <= 3'd0;
1104
        pl <= 8'h00;
1105
        pc <= tvec[0];
1106
        cause <= caus;
1107
        goto(IFETCH);
1108
end
1109
endtask
1110
 
1111
task read_csr;
1112
input [11:0] regno;
1113
output [63:0] val;
1114
begin
1115
        casez(regno)
1116
        `HARTID:        val <= hartid_i;
1117
        `TICK:          val <= tick;
1118
        `CAUSE:         val <= {55'd0,cause};
1119
        `SCRATCH:       val <= scratch;
1120
        `SEMA:          val <= sema;
1121
        `TVEC:          val <= tvec[regno[2:0]];
1122
        `TIME:          val <= times;
1123
        `INSTRET:       val <= instret;
1124
        endcase
1125
end
1126
endtask
1127
 
1128
task write_csr;
1129
input [11:0] regno;
1130
input [1:0] op;
1131
input [63:0] val;
1132
begin
1133
        case(op)
1134
        2'd0:   ;       // read only
1135
        2'd1:
1136
                casez(regno)
1137
                `CAUSE: cause <= val[8:0];
1138
                `SCRATCH:       scratch <= val;
1139
                `SEMA:  sema <= val;
1140
                `TVEC:  tvec[regno[2:0]] <= val;
1141
                endcase
1142
        2'd2:
1143
                casez(regno)
1144
                `SEMA:  sema <= sema | val;
1145
                endcase
1146
        2'd3:
1147
                casez(regno)
1148
                `SEMA:  sema <= sema & ~val;
1149
                endcase
1150
        endcase
1151
end
1152
endtask
1153
 
1154
task wb_read;
1155
input [15:0] sel;
1156
input [31:0] adr;
1157
begin
1158
        cyc_o <= `HIGH;
1159
        stb_o <= `HIGH;
1160
        sel_o <= sel;
1161
        adr_o <= adr;
1162
        $display("%h: l?[u] %h", opc, adr);
1163
        goto(MEMORY);
1164
end
1165
endtask
1166
 
1167
task wb_write;
1168
input [15:0] sel;
1169
input [31:0] adr;
1170
input [63:0] dat;
1171
begin
1172
        cyc_o <= `HIGH;
1173
        stb_o <= `HIGH;
1174
        we_o <= `HIGH;
1175
        sel_o <= sel;
1176
        adr_o <= adr;
1177
        dat_o <= {2{dat}};
1178
        goto(MEMORY);
1179
        $display("%h: s? %h <= %h", opc, adr, dat);
1180
end
1181
endtask
1182
 
1183
task goto;
1184
input [7:0] st;
1185
begin
1186
        state <= st;
1187
end
1188
endtask
1189
 
1190
endmodule

powered by: WebSVN 2.1.0

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