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

Subversion Repositories ssbcc

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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