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

Subversion Repositories ssbcc

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

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

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

powered by: WebSVN 2.1.0

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