File:  [gforth] / gforth / arch / misc / misc.v
Revision 1.4: download - view: text, annotated - select for diffs
Mon Dec 31 18:40:25 2007 UTC (16 years, 3 months ago) by anton
Branches: MAIN
CVS tags: HEAD
updated copyright notices for GPL v3

// 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 3
// 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, see http://www.gnu.org/licenses/.

/* 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 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>