Commit f0cbcd17 authored by bp's avatar bp
Browse files

Added files created with make files

git-svn-id: https://www.forth-ev.de/repos/b16-small@1913 3b8d8251-53f3-0310-8f3b-fd1cb8370982
parent ff876d3d
Loading
Loading
Loading
Loading

alu.v

0 → 100644
+46 −0
Original line number Diff line number Diff line
/*
 * b16 core: 16 bits, 
 * inspired by c18 core from Chuck Moore
 * (c) 2002-2011 by Bernd Paysan
 * 
 * This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License or any later.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   This is not the source code of the program, the source code is a LyX
   literate programming style article.
 */
`include "b16-defines.v"

module alu(res, carry, zero, T, N, c, inst);
   parameter l=16;
   input `L T, N;
   input c;
   input [2:0] inst;
   output `L res;
   output carry, zero;

   wire prop, andor, selr;

   assign { prop, selr, andor } = inst;

   wire        `L r1, r2;
   wire [l:0]  carries;

   assign r1 = T ^ N ^ carries;
   assign r2 = (T & N) | 
               (T & carries`L) | 
               (N & carries`L);
// This generates a carry *chain*, not a loop!
   assign carries = 
        prop ? { r2[l-1:0], (c | selr) & andor } 
             : { c, {(l){andor}}};
   assign res = (selr & ~prop) ? r2 : r1;
   assign carry = carries[l];
   assign zero = ~|T;
endmodule // alu

b16-defines.v

0 → 100644
+6 −0
Original line number Diff line number Diff line
`define L [l-1:0]

`define DROP { sp, T } <= { spinc, N }
`define DEBUGGING
`define FPGA
// `define BUSTRI
−122 B (215 KiB)

File changed.

No diff preview for this file type.

+1 −4
Original line number Diff line number Diff line
@@ -128,7 +128,6 @@ module cpu(clk, latclk, run, nreset, addr, rd, wr, data,
        2'b10: jmp = { P[15:6], I[4:0], 1'b0 };
        2'b11: jmp = { T[15:1], 1'b0 };
      endcase // casez(state)
   
   wire `L res, toN, toR, N;
   wire carry, zero;

@@ -297,7 +296,6 @@ module cpu(clk, latclk, run, nreset, addr, rd, wr, data,
               if(nextstate != 2'b10) T <= incaddr;
               sp <= rd ? spdec : spinc;
            end

            5'b10010, 5'b10011, 5'b10110, 5'b10111:
               T <= dataw;  // @, lit, c@, litc
            5'b11000: sp <= spinc;               // nip
@@ -325,7 +323,6 @@ module cpu(clk, latclk, run, nreset, addr, rd, wr, data,
            3'h5: T <= din;
            3'h6: R <= din;
            3'h7: I <= din;

            default ;
         endcase
         if(dr) case(daddr)

cpu.v

0 → 100644
+277 −0
Original line number Diff line number Diff line
/*
 * b16 core: 16 bits, 
 * inspired by c18 core from Chuck Moore
 * (c) 2002-2011 by Bernd Paysan
 * 
 * This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License or any later.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   This is not the source code of the program, the source code is a LyX
   literate programming style article.
 */
/*
 * Instruction set:
 * 1, 5, 5, 5 bits
 *     0    1    2    3    4    5    6    7
 *  0: nop  call jmp  ret  jz   jnz  jc   jnc
 *  /3      exec goto ret  gz   gnz  gc   gnc
 *  8: xor  com  and  or   +    +c   *+   /-
 * 10: !+   @+   @    lit  c!+  c@+  c@   litc
 *  /1 !.   @.   @    lit  c!.  c@.  c@   litc
 * 18: nip  drop over dup  >r        r>
 */
`include "b16-defines.v"

module cpu(clk, latclk, run, nreset, addr, rd, wr, data, 
           dataout, gwrite
`ifdef DEBUGGING,
           dr, dw, daddr, din, dout, bp`endif);
   parameter rstaddr=16'h3FFE, show=0,
             l=16, sdep=4, rdep=4;
   input clk, latclk, run, nreset, gwrite;
   output `L addr;
   output rd;
   output [1:0] wr;
   input  `L data;
   output `L dataout;
   `ifdef DEBUGGING
      input [2:0] daddr;
      input dr, dw;
      input `L din, bp;
      output `L dout;

   `endif
   reg [sdep-1:0] sp;
   reg [rdep-1:0] rp;

   reg `L T, I, P, R;
   reg [1:0] state;
   reg c;
   // instruction and branch target selection   
   wire [4:0] inst, rwinst;
   reg `L jmp;

   assign inst = { 4'b0000, data[15], I[14:0] }
                 >> (5*(3-state[1:0]));
   assign rwinst = { 5'b00000, I[14:0] }
                   >> (5*(3-state[1:0]));

   always @(state or I or P or T or data)
      case(state[1:0])
        2'b00: jmp = { data[14:0], 1'b0 };
        2'b01: jmp = { P[15:11], I[9:0], 1'b0 };
        2'b10: jmp = { P[15:6], I[4:0], 1'b0 };
        2'b11: jmp = { T[15:1], 1'b0 };
      endcase // casez(state)
   wire `L res, toN, toR, N;
   wire carry, zero;

   alu #(l) alu16(.res(res), .carry(carry),
                  .zero(zero),
                  .T(T), .N(N), .c(c),
                  .inst(inst[2:0]));
   wire `L incaddr, dataw, datas;
   wire tos2r, tos2n;
   wire incby, bswap, addrsel, access, rd;
   wire [1:0] wr;

   assign incby = (rwinst[4:2] != 3'b101);
   assign access = (rwinst[4:3]==2'b10);
   assign addrsel = rd ? 
         (access & (rwinst[1:0] != 2'b11)) : |wr;
   assign rd = (state==2'b00) || 
               (access && (rwinst[1:0]!=2'b00));
   assign wr = (access && (rwinst[1:0]==2'b00)) ?
               { ~rwinst[2] | ~T[0], 
                 ~rwinst[2] | T[0] } : 2'b00;
   assign addr = addrsel ? T : P;
   assign incaddr = addr + incby + 1;
   assign tos2n = (!rd | (rwinst[1:0] == 2'b11));
   assign toN = tos2n ? T : dataw;
   assign bswap = ~incby ^ addr[0];
   assign datas = bswap ? { data[7:0], data[l-1:8] }
                        : data;
   assign dataw = incby ? datas
                        : { 8'h00, datas[7:0] }; 
   assign dataout = bswap ? { N[7:0], N[l-1:8] }
                          : N; 
   reg dpush, rpush;

   always @(state or inst or rd or run `ifdef DEBUGGING
                                       or run or dw or daddr
                                       `endif)
     begin
        rpush = 1'b0;
        dpush = (|state[1:0] & rd) |
                (inst[4] && inst[3] && inst[1]);
        case(inst)
           5'b00001: rpush = |state[1:0] | run;
           5'b11100: rpush = 1'b1;
           default ;
        endcase // case(inst)
        `ifdef DEBUGGING
        if(!run && dw) case(daddr)
           3'h0: dpush = 1;
           3'h1: rpush = 1;
           default ;
        endcase
        `endif
     end
   wire [sdep-1:0] spdec, spinc;
   wire [rdep-1:0] rpdec, rpinc;

   stack #(sdep,l) dstack(.clk(latclk),
                          .sp(sp),
                          .spdec(spdec),
                          .push(dpush),
                          .in(toN),
                          .out(N),
                          .gwrite(gwrite));
   stack #(rdep,l) rstack(.clk(latclk),
                          .sp(rp),
                          .spdec(rpdec),
                          .push(rpush),
                          .in(R),
                          .out(toR),
                          .gwrite(gwrite));

   assign spdec = sp-{{(sdep-1){1'b0}}, 1'b1};
   assign spinc = sp+{{(sdep-1){1'b0}}, 1'b1};
   assign rpdec = rp-{{(rdep-1){1'b0}}, 1'b1};
   assign rpinc = rp+{{(rdep-1){1'b0}}, 1'b1};
   wire [1:0] nextstate;

   assign nextstate = ((~|inst) || (|inst[4:3])) ?
                      state[1:0] + 2'b01 : 2'b00;
   `ifdef DEBUGGING
   reg `L dout;

   always @(daddr or dr or run or P or T or R or I or
            state or sp or rp or c or N or toR or bp)
   if(!dr || run) dout = 'h0;
   else case(daddr)
      3'h0: dout = N;
      3'h1: dout = toR;
      3'h2: dout = bp;
      3'h3: dout = { run, 4'h0, c, state,
                     {4-sdep{1'b0}}, sp,
                     {4-rdep{1'b0}}, rp };
      3'h4: dout = P;
      3'h5: dout = T;
      3'h6: dout = R;
      3'h7: dout = I;
   endcase
   `endif

   always @(posedge clk or negedge nreset)
      if(!nreset) begin
         state <= 2'b11;
         P <= rstaddr;
         T <= 16'h0000;
         I <= 16'h0000;
         R <= 16'h0000;
         c <= 1'b0;
         sp <= 0;
         rp <= 0;
      end else if(run) begin
      `ifdef REPORT_VERBOSE
         if(show) begin
            $write("%b[%b] T=%b%x:%x[%x], ",
                   inst, state, c, T, N, sp);
            $write("P=%x, I=%x, R=%x[%x], res=%b%x\n",
                   P, I, R, rp, carry, res);
         end
      `endif
         if(~|state || 
            ({ inst[4:3], inst[1:0] } == 4'b1011))
            P <= incaddr;
         if(|state[1:0]) begin 
            if(rd && { inst[4:3], inst[1:0] } != 4'b1010)
               sp <= spdec;
            if(|wr) sp <= spinc;
         end else begin 
            I <= data; 
            if(!data[15]) state[1:0] <= 2'b01;
         end
         state <= nextstate;
         case(inst)
            5'b00001: begin // call
               rp <= rpdec;
               R <= { ~|state ? incaddr[15:1] : P[15:1], c };
               P <= jmp;
               c <= 1'b0;
               if(state == 2'b11) `DROP;
            end // case: 5'b00001
            5'b00010: begin // jmp
               P <= jmp;
               if(state == 2'b11) `DROP;
            end
            5'b00011: // ret
                      { rp, c, P, R } <= 
                      { rpinc, R[0], R[l-1:1], 1'b0, toR };
            5'b00100, 5'b00101, 5'b00110, 5'b00111:
            begin // conditional jmps
               if((inst[1] ? c : zero) ^ inst[0]) 
                  P <= jmp;
               `DROP;
            end
            5'b01001: // com
               { c, T } <= { 1'b1, ~T };
            5'b01110: // *+
               { T, R, c } <=
               { c ? { carry, res } : { 1'b0, T }, R };
            5'b01111: // /-
               { c, T, R } <=
               { (c | carry) ? res : T, R, (c | carry) };
            5'b01000, 5'b01010, 5'b01011, 5'b01100, 5'b01101:
               // xor, and, or, +, +c
               { sp, c, T } <= { spinc, carry, res };
            5'b10000, 5'b10001, 5'b10100, 5'b10101:
            begin        // !+, @+, c!+, c@+
               if(nextstate != 2'b10) T <= incaddr;
               sp <= rd ? spdec : spinc;
            end
            5'b10010, 5'b10011, 5'b10110, 5'b10111:
               T <= dataw;  // @, lit, c@, litc
            5'b11000: sp <= spinc;               // nip
            5'b11001: `DROP;                     // drop
            5'b11010: { sp, T } <= { spdec, N }; // over
            5'b11011: sp <= spdec;               // dup
            5'b11100: begin                      // >r
               R <= T; rp <= rpdec; `DROP;
            end // case: 5'b11100
            5'b11110: begin                      // r>
               { sp, T, R } <= { spdec, R, toR };
               rp <= rpinc;
            end // case: 5'b11110
            default ;                            // noop
         endcase // case(inst)
      end else begin // debug
         `ifdef DEBUGGING
         if(dw) case(daddr)
            3'h0: { sp, T } <= { spdec, din };
            3'h1: { rp, R } <= { rpdec, din };
            3'h3: { c, state, sp, rp } <= 
                    { din[10:8],
                      din[sdep+3:4], din[rdep-1:0] };
            3'h4: P <= din;
            3'h5: T <= din;
            3'h6: R <= din;
            3'h7: I <= din;
            default ;
         endcase
         if(dr) case(daddr)
            3'h0: sp <= spinc;
            3'h1: rp <= rpinc;
            default ;
         endcase
         `endif
      end // else: !if(nreset)

endmodule // cpu
Loading