// Copyright (C) 1998,2000,2003,2004 Free Software Foundation, Inc. // This file is part of Gforth. // Gforth 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; either version 2 // of the License, or (at your option) any later version. // 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. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. /* Minimal Instruction Set Computer \ sources destinations $0 Constant PC $0 Constant JMP $1 Constant PC+2 $1 Constant JS $2 Constant PC+4 $2 Constant JZ $3 Constant PC+6 $4 Constant JC $8 Constant ACCU $8 Constant ACCU $9 Constant SF $9 Constant SUB $A Constant ZF $A Constant SUBR $B Constant ADD $C Constant CF $C Constant XOR $D Constant OR $E Constant AND $F Constant SHR */ `define L [0:l-1] module misc(clock, data, addr, csel, rw); parameter l=16, d=10; input clock; inout `L data; output `L addr; output csel; output rw; reg `L inst, dtr, accu, pc; reg [0:1] state; reg carry, zero; wire `L regs; wire alusel, cout, zout, pccond; wire `L alu1, alu2, aluout; wire [0:2] aluop; initial begin state = 0; pc = 'h10; inst = 0; dtr = 0; accu = 0; carry = 0; zero = 1; end assign rw=~&state, csel=~state[1] | |inst[0:l-5], addr = state[1] ? inst : pc, data = rw ? {l{1'bz}} : dtr; assign alusel= inst[l-4], pccond = ~|(inst[l-3:l-1] & ~{ carry, zero, accu[0] }), regs = inst[l-4] ? (|inst[l-3:l-1] ? { {(l-1){1'b0}}, pccond } : accu) : aluout; always @(posedge clock) begin casez(state) 2'bz0 : begin inst = data; pc = aluout; end 2'b01 : begin dtr = csel ? data : regs; // $fwrite(2, "PC: %x : %x -( %x )->", pc-1'b1, inst, dtr); end 2'b11 : begin if(~|inst[0:l-5]) if(alusel) { carry, zero, accu } = { cout, zout, aluout }; else if (pccond) pc=dtr; // $fwrite(2, " %x ACCU: %x\n", inst, accu); end endcase /* 2 */ state = state + 1; end assign alu1 = &state ? accu : pc, alu2 = ~state[1] ? {{l{1'b0}}, 1'b1 } : state[0] ? dtr : { inst[1:l-1], 1'b0 } - 1, aluop = &state ? inst[l-3:l-1] : 3'b011; alu #(l,d) alu0(aluop, alu1, alu2, carry, aluout, cout, zout); endmodule /* misc */ module alu(op, in1, in2, cin, out, cout, zout); parameter l=16, d=10; input [0:2] op; input `L in1, in2; input cin; output `L out; output cout, zout; reg `L out; reg cout; initial cout = 0; always @(in1 or in2 or op) #d case(op) 3'b000 : { cout, out } = { cin, in2 }; 3'b001 : { cout, out } = in1 - in2; 3'b010 : { cout, out } = in2 - in1; 3'b011 : { cout, out } = in1 + in2; 3'b100 : { cout, out } = { cin, in1 ^ in2 }; 3'b101 : { cout, out } = { cin, in1 | in2 }; 3'b110 : { cout, out } = { cin, in1 & in2 }; 3'b111 : { cout, out } = { in2[l-1], cin, in2[0:l-2] }; endcase /* 3 */ assign zout = ~|out; endmodule /* alu */