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

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [core.v] - Blame information for rev 3

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

Line No. Rev Author Line
1 2 sinclairrf
/*******************************************************************************
2
 *
3
 * Copyright 2012-2013, Sinclair R.F., Inc.
4
 *
5
 * SSBCC.9x8 -- Small Stack Based Computer Compiler, 9-bit opcode, 8-bit data.
6
 *
7
 * The repository for this open-source project is at
8
 *   https://github.com/sinclairrf/SSBCC
9
 *
10
 ******************************************************************************/
11
 
12
//@SSBCC@ user_header
13
 
14
//@SSBCC@ module
15
 
16
// configuration file determined parameters
17
//@SSBCC@ localparam
18
 
19
/*******************************************************************************
20
 *
21
 * Declare the signals used throughout the system.
22
 *
23
 ******************************************************************************/
24
 
25
// listed in useful display order
26
reg            [C_PC_WIDTH-1:0] s_PC;           // program counter
27
reg                       [8:0] s_opcode;       // current opcode
28
reg    [C_RETURN_PTR_WIDTH-1:0] s_R_stack_ptr;  // pointer into return stack memory
29
reg        [C_RETURN_WIDTH-1:0] s_R;            // top of return stack
30
reg                       [7:0] s_T;            // top of the data stack
31
reg                       [7:0] s_N;            // next-to-top on the data stack
32
reg      [C_DATA_PTR_WIDTH-1:0] s_Np_stack_ptr; // pointer into data stack memory
33
 
34
//@SSBCC@ functions
35
 
36
//@SSBCC@ verilator_tracing
37
 
38
//@SSBCC@ signals
39
 
40
/*******************************************************************************
41
 *
42
 * Instantiate the ALU operations.  These are listed in the order in which they
43
 * first occur in the opcodes.
44
 *
45
 ******************************************************************************/
46
 
47
// opcode = 000000_xxx
48
// shifter operations (including "nop" as no shift)
49
// 6-input LUT formulation -- 3-bit opcode, 3 bits of T centered at current bit
50
reg [7:0] s_math_rotate;
51
always @ (s_T,s_opcode)
52
  case (s_opcode[0+:3])
53
     3'b000 : s_math_rotate = s_T;                      // nop
54
     3'b001 : s_math_rotate = { s_T[0+:7], 1'b0 };      // <<0
55
     3'b010 : s_math_rotate = { s_T[0+:7], 1'b1 };      // <<1
56
     3'b011 : s_math_rotate = { s_T[0+:7], s_T[7] };    // <<msb
57
     3'b100 : s_math_rotate = { 1'b0,      s_T[1+:7] }; // 0>>
58
     3'b101 : s_math_rotate = { 1'b1,      s_T[1+:7] }; // 1>>
59
     3'b110 : s_math_rotate = { s_T[7],    s_T[1+:7] }; // msb>>
60
     3'b111 : s_math_rotate = { s_T[0],    s_T[1+:7] }; // lsb>>
61
    default : s_math_rotate = s_T;
62
  endcase
63
 
64
// opcode = 000001_0xx
65
// T pre-multiplexer for pushing repeated values onto the data stack
66
reg [7:0] s_T_stack;
67
always @ (*)
68
  case (s_opcode[0+:2])
69
      2'b00 : s_T_stack = s_T;                  // dup
70
      2'b01 : s_T_stack = s_R[0+:8];            // r@
71
      2'b10 : s_T_stack = s_N;                  // over
72
    default : s_T_stack = s_T;
73
  endcase
74
 
75
//  opcode = 000011_x00 (adder) and 001xxx_x.. (incrementers)
76
reg [7:0] s_T_adder;
77
always @ (*)
78
  if (s_opcode[6] == 1'b0)
79
    case (s_opcode[2])
80
       1'b0: s_T_adder = s_N + s_T;
81
       1'b1: s_T_adder = s_N - s_T;
82
    endcase
83
  else
84
    case (s_opcode[2])
85
       1'b0: s_T_adder = s_T + 8'h01;
86
       1'b1: s_T_adder = s_T - 8'h01;
87
    default: s_T_adder = s_T + 8'h01;
88
    endcase
89
 
90
// opcode = 000100_0xx
91
//                   ^ 0 ==> "=", 1 ==> "<>"
92
//                  ^  0 ==> all zero, 1 ==> all ones
93
wire s_T_compare = s_opcode[0] ^ &(s_T == {(8){s_opcode[1]}});
94
 
95
// opcode = 001010_xxx
96
// add,sub,and,or,xor,TBD,drop,nip
97
reg [7:0] s_T_logic;
98
always @ (*)
99
  case (s_opcode[0+:3])
100
     3'b000 : s_T_logic = s_N & s_T;    // and
101
     3'b001 : s_T_logic = s_N | s_T;    // or
102
     3'b010 : s_T_logic = s_N ^ s_T;    // xor
103
     3'b011 : s_T_logic = s_T;          // nip
104
     3'b100 : s_T_logic = s_N;          // drop
105
     3'b101 : s_T_logic = s_N;          // drop
106
     3'b110 : s_T_logic = s_N;          // drop
107
     3'b111 : s_T_logic = s_N;          // drop
108
    default : s_T_logic = s_N;          // drop
109
  endcase
110
 
111
// increment PC
112
reg [C_PC_WIDTH-1:0] s_PC_plus1 = {(C_PC_WIDTH){1'b0}};
113
always @ (*)
114
  s_PC_plus1 = s_PC + { {(C_PC_WIDTH-1){1'b0}}, 1'b1 };
115
 
116
// Reduced-warning-message method to extract the jump address from the top of
117
// the stack and the current opcode.
118
wire [C_PC_WIDTH-1:0] s_PC_jump;
119
generate
120
  if (C_PC_WIDTH <= 8) begin : gen_pc_jump_narrow
121
    assign s_PC_jump = s_T[0+:C_PC_WIDTH];
122
  end else begin : gen_pc_jump_wide
123
    assign s_PC_jump = { s_opcode[0+:C_PC_WIDTH-8], s_T };
124
  end
125
endgenerate
126
 
127
/*******************************************************************************
128
 *
129
 * Instantiate the input port data selection.
130
 *
131
 * Note:  This creates and computes an 8-bit wire called "s_T_inport".
132
 *
133
 ******************************************************************************/
134
 
135
reg [7:0] s_T_inport = 8'h00;
136
reg       s_inport   = 1'b0;
137
//@SSBCC@ inports
138
 
139
/*******************************************************************************
140
 *
141
 * Instantiate the memory banks.
142
 *
143
 ******************************************************************************/
144
 
145
reg s_mem_wr = 1'b0;
146
//@SSBCC@ s_memory
147
 
148
/*******************************************************************************
149
 *
150
 * Define the states for the bus muxes and then compute these states from the
151
 * 6 msb of the opcode.
152
 *
153
 ******************************************************************************/
154
 
155
localparam C_BUS_PC_NORMAL      = 2'b00;
156
localparam C_BUS_PC_JUMP        = 2'b01;
157
localparam C_BUS_PC_RETURN      = 2'b11;
158
reg [1:0] s_bus_pc;
159
 
160
localparam C_BUS_R_T            = 1'b0;         // no-op and push T onto return stack
161
localparam C_BUS_R_PC           = 1'b1;         // push PC onto return stack
162
reg s_bus_r;
163
 
164
localparam C_RETURN_NOP         = 2'b00;        // don't change return stack pointer
165
localparam C_RETURN_INC         = 2'b01;        // add element to return stack
166
localparam C_RETURN_DEC         = 2'b10;        // remove element from return stack
167
reg [1:0] s_return;
168
 
169
localparam C_BUS_T_MATH_ROTATE  = 4'b0000;      // nop and rotate operations
170
localparam C_BUS_T_OPCODE       = 4'b0001;
171
localparam C_BUS_T_N            = 4'b0010;
172
localparam C_BUS_T_PRE          = 4'b0011;
173
localparam C_BUS_T_ADDER        = 4'b0100;
174
localparam C_BUS_T_COMPARE      = 4'b0101;
175
localparam C_BUS_T_INPORT       = 4'b0110;
176
localparam C_BUS_T_LOGIC        = 4'b0111;
177
localparam C_BUS_T_MEM          = 4'b1010;
178
reg [3:0] s_bus_t;
179
 
180
localparam C_BUS_N_N            = 2'b00;       // don't change N
181
localparam C_BUS_N_STACK        = 2'b01;       // replace N with third-on-stack
182
localparam C_BUS_N_T            = 2'b10;       // replace N with T
183
localparam C_BUS_N_MEM          = 2'b11;       // from memory
184
reg [1:0] s_bus_n;
185
 
186
localparam C_STACK_NOP          = 2'b00;        // don't change internal data stack pointer
187
localparam C_STACK_INC          = 2'b01;        // add element to internal data stack
188
localparam C_STACK_DEC          = 2'b10;        // remove element from internal data stack
189
reg [1:0] s_stack;
190
 
191
reg s_outport                   = 1'b0;
192
 
193
always @ (*) begin
194
  // default operation is nop/math_rotate
195
  s_bus_pc      = C_BUS_PC_NORMAL;
196
  s_bus_r       = C_BUS_R_T;
197
  s_return      = C_RETURN_NOP;
198
  s_bus_t       = C_BUS_T_MATH_ROTATE;
199
  s_bus_n       = C_BUS_N_N;
200
  s_stack       = C_STACK_NOP;
201
  s_inport      = 1'b0;
202
  s_outport     = 1'b0;
203
  s_mem_wr      = 1'b0;
204
  if (s_opcode[8] == 1'b1) begin // push
205
    s_bus_t     = C_BUS_T_OPCODE;
206
    s_bus_n     = C_BUS_N_T;
207
    s_stack     = C_STACK_INC;
208
  end else if (s_opcode[7] == 1'b1) begin // jump, jumpc, call, callc
209
    if (!s_opcode[5] || (|s_N)) begin // always or conditional
210
      s_bus_pc  = C_BUS_PC_JUMP;
211
      if (s_opcode[6])                  // call or callc
212
        s_return = C_RETURN_INC;
213
    end
214
    s_bus_r     = C_BUS_R_PC;
215
    s_bus_t     = C_BUS_T_N;
216
    s_bus_n     = C_BUS_N_STACK;
217
    s_stack     = C_STACK_DEC;
218
  end else case (s_opcode[3+:4])
219
      4'b0000:  // nop, math_rotate
220
                ;
221
      4'b0001:  begin // dup, r@, over
222
                s_bus_t         = C_BUS_T_PRE;
223
                s_bus_n         = C_BUS_N_T;
224
                s_stack         = C_STACK_INC;
225
                end
226
      4'b0010:  begin // swap
227
                s_bus_t         = C_BUS_T_N;
228
                s_bus_n         = C_BUS_N_T;
229
                end
230
      4'b0011:  begin // dual-operand adder:  add,sub
231
                s_bus_t         = C_BUS_T_ADDER;
232
                s_bus_n         = C_BUS_N_STACK;
233
                s_stack         = C_STACK_DEC;
234
                end
235
      4'b0100:  begin // 0=, -1=, 0<>, -1<>
236
                s_bus_t         = C_BUS_T_COMPARE;
237
                end
238
      4'b0101:  begin // return
239
                s_bus_pc        = C_BUS_PC_RETURN;
240
                s_return        = C_RETURN_DEC;
241
                end
242
      4'b0110:  begin // inport
243
                s_bus_t         = C_BUS_T_INPORT;
244
                s_inport        = 1'b1;
245
                end
246
      4'b0111:  begin // outport
247
                s_bus_t         = C_BUS_T_N;
248
                s_bus_n         = C_BUS_N_STACK;
249
                s_stack         = C_STACK_DEC;
250
                s_outport       = 1'b1;
251
                end
252
      4'b1000:  begin // >r
253
                s_return        = C_RETURN_INC;
254
                s_bus_t         = C_BUS_T_N;
255
                s_bus_n         = C_BUS_N_STACK;
256
                s_stack         = C_STACK_DEC;
257
                end
258
      4'b1001:  begin // r> (pop the return stack and push it onto the data stack)
259
                s_return        = C_RETURN_DEC;
260
                s_bus_t         = C_BUS_T_PRE;
261
                s_bus_n         = C_BUS_N_T;
262
                s_stack         = C_STACK_INC;
263
                end
264
      4'b1010:  begin // &, or, ^, nip, and drop
265
                s_bus_t         = C_BUS_T_LOGIC;
266
                s_bus_n         = C_BUS_N_STACK;
267
                s_stack         = C_STACK_DEC;
268
                end
269
      4'b1011:  begin // 8-bit increment/decrement
270
                s_bus_t         = C_BUS_T_ADDER;
271
                end
272
      4'b1100:  begin // store
273
                s_bus_t         = C_BUS_T_N;
274
                s_bus_n         = C_BUS_N_STACK;
275
                s_stack         = C_STACK_DEC;
276
                s_mem_wr        = 1'b1;
277
                end
278
      4'b1101:  begin // fetch
279
                s_bus_t       = C_BUS_T_MEM;
280
                end
281
      4'b1110:  begin // store+/store-
282
                s_bus_t         = C_BUS_T_ADDER;
283
                s_bus_n         = C_BUS_N_STACK;
284
                s_stack         = C_STACK_DEC;
285
                s_mem_wr        = 1'b1;
286
                end
287
      4'b1111:  begin // fetch+/fetch-
288
                s_bus_t         = C_BUS_T_ADDER;
289
                s_bus_n         = C_BUS_N_MEM;
290
                s_stack         = C_STACK_INC;
291
                end
292
      default:  // nop
293
                ;
294
    endcase
295
end
296
 
297
/*******************************************************************************
298
 *
299
 * Operate the MUXes
300
 *
301
 ******************************************************************************/
302
 
303
// non-clocked PC required for shadow register in SRAM blocks
304
reg [C_PC_WIDTH-1:0] s_PC_next;
305
always @ (*)
306
  case (s_bus_pc)
307
    C_BUS_PC_NORMAL:
308
      s_PC_next = s_PC_plus1;
309
    C_BUS_PC_JUMP:
310
      s_PC_next = s_PC_jump;
311
    C_BUS_PC_RETURN:
312
      s_PC_next = s_R[0+:C_PC_WIDTH];
313
    default:
314
      s_PC_next = s_PC_plus1;
315
  endcase
316
 
317
// Return stack candidate
318
reg [C_RETURN_WIDTH-1:0] s_R_pre;
319
generate
320
  if (C_PC_WIDTH < 8) begin : gen_r_narrow
321
    always @ (*)
322
      case (s_bus_r)
323
        C_BUS_R_T:
324
          s_R_pre = s_T;
325
        C_BUS_R_PC:
326
          s_R_pre = { {(8-C_PC_WIDTH){1'b0}}, s_PC_plus1 };
327
        default:
328
          s_R_pre = s_T;
329
      endcase
330
  end else if (C_PC_WIDTH == 8) begin : gen_r_same
331
    always @ (*)
332
      case (s_bus_r)
333
        C_BUS_R_T:
334
          s_R_pre = s_T;
335
        C_BUS_R_PC:
336
          s_R_pre = s_PC_plus1;
337
        default:
338
          s_R_pre = s_T;
339
      endcase
340
  end else begin : gen_r_wide
341
    always @ (*)
342
      case (s_bus_r)
343
        C_BUS_R_T:
344
          s_R_pre = { {(C_PC_WIDTH-8){1'b0}}, s_T };
345
        C_BUS_R_PC:
346
          s_R_pre = s_PC_plus1;
347
        default:
348
          s_R_pre = { {(C_PC_WIDTH-8){1'b0}}, s_T };
349
      endcase
350
  end
351
endgenerate
352
 
353
/*******************************************************************************
354
 *
355
 * run the state machines for the processor components.
356
 *
357
 ******************************************************************************/
358
 
359
/*
360
 * Operate the program counter.
361
 */
362
 
363
initial s_PC = {(C_PC_WIDTH){1'b0}};
364
always @ (posedge i_clk)
365
  if (i_rst)
366
    s_PC <= {(C_PC_WIDTH){1'b0}};
367
  else
368
    s_PC <= s_PC_next;
369
 
370
/*
371
 * Operate the return stack.
372
 */
373
 
374
reg [C_RETURN_PTR_WIDTH-1:0] s_R_stack_ptr_next;
375
 
376
// reference data stack pointer
377
initial s_R_stack_ptr = {(C_RETURN_PTR_WIDTH){1'b1}};
378
always @ (posedge i_clk)
379
  if (i_rst)
380
    s_R_stack_ptr <= {(C_RETURN_PTR_WIDTH){1'b1}};
381
  else
382
    s_R_stack_ptr <= s_R_stack_ptr_next;
383
 
384
// reference data stack pointer
385
initial s_R_stack_ptr_next = {(C_RETURN_PTR_WIDTH){1'b1}};
386
always @ (*)
387
  case (s_return)
388
    C_RETURN_INC: s_R_stack_ptr_next = s_R_stack_ptr + { {(C_RETURN_PTR_WIDTH-1){1'b0}}, 1'b1 };
389
    C_RETURN_DEC: s_R_stack_ptr_next = s_R_stack_ptr - { {(C_RETURN_PTR_WIDTH-1){1'b0}}, 1'b1 };
390
         default: s_R_stack_ptr_next = s_R_stack_ptr;
391
  endcase
392
 
393
/*
394
 * Operate the top of the data stack.
395
 */
396
 
397
reg [7:0] s_T_pre = 8'd0;
398
always @ (*)
399
  case (s_bus_t)
400
    C_BUS_T_MATH_ROTATE:        s_T_pre = s_math_rotate;
401
    C_BUS_T_OPCODE:             s_T_pre = s_opcode[0+:8];  // push 8-bit value
402
    C_BUS_T_N:                  s_T_pre = s_N;
403
    C_BUS_T_PRE:                s_T_pre = s_T_stack;
404
    C_BUS_T_ADDER:              s_T_pre = s_T_adder;
405
    C_BUS_T_COMPARE:            s_T_pre = {(8){s_T_compare}};
406
    C_BUS_T_INPORT:             s_T_pre = s_T_inport;
407
    C_BUS_T_LOGIC:              s_T_pre = s_T_logic;
408
    C_BUS_T_MEM:                s_T_pre = s_memory;
409
    default:                    s_T_pre = s_T;
410
  endcase
411
 
412
initial s_T = 8'h00;
413
always @ (posedge i_clk)
414
  if (i_rst)
415
    s_T <= 8'h00;
416
  else
417
    s_T <= s_T_pre;
418
 
419
/*
420
 * Operate the next-to-top of the data stack.
421
 */
422
 
423
// reference data stack pointer
424
reg [C_DATA_PTR_WIDTH-1:0] s_Np_stack_ptr_next;
425
always @ (*)
426
  case (s_stack)
427
    C_STACK_INC: s_Np_stack_ptr_next = s_Np_stack_ptr + { {(C_DATA_PTR_WIDTH-1){1'b0}}, 1'b1 };
428
    C_STACK_DEC: s_Np_stack_ptr_next = s_Np_stack_ptr - { {(C_DATA_PTR_WIDTH-1){1'b0}}, 1'b1 };
429
        default: s_Np_stack_ptr_next = s_Np_stack_ptr;
430
  endcase
431
 
432
initial s_Np_stack_ptr = { {(C_DATA_PTR_WIDTH-2){1'b1}}, 2'b01 };
433
always @ (posedge i_clk)
434
  if (i_rst)
435
    s_Np_stack_ptr <= { {(C_DATA_PTR_WIDTH-2){1'b1}}, 2'b01 };
436
  else
437
    s_Np_stack_ptr <= s_Np_stack_ptr_next;
438
 
439
reg [7:0] s_Np;
440
 
441
initial s_N = 8'h00;
442
always @ (posedge i_clk)
443
  if (i_rst)
444
    s_N <= 8'h00;
445
  else case (s_bus_n)
446
    C_BUS_N_N:          s_N <= s_N;
447
    C_BUS_N_STACK:      s_N <= s_Np;
448
    C_BUS_N_T:          s_N <= s_T;
449
    C_BUS_N_MEM:        s_N <= s_memory;
450
    default:            s_N <= s_N;
451
  endcase
452
 
453
/*******************************************************************************
454
 *
455
 * Instantiate the output signals.
456
 *
457
 ******************************************************************************/
458
 
459
//@SSBCC@ outports
460
 
461
/*******************************************************************************
462
 *
463
 * Instantiate the instruction memory and the PC access of that memory.
464
 *
465
 ******************************************************************************/
466
 
467
//@SSBCC@ memories
468
 
469
/*******************************************************************************
470
 *
471
 * Instantiate the peripherals (if any).
472
 *
473
 ******************************************************************************/
474
 
475
//@SSBCC@ peripherals
476
 
477
endmodule

powered by: WebSVN 2.1.0

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