OpenCores
URL https://opencores.org/ocsvn/mcs-4/mcs-4/trunk

Subversion Repositories mcs-4

[/] [mcs-4/] [trunk/] [rtl/] [verilog/] [i4004/] [alu.v] - Rev 5

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

`timescale 1ns / 1ps
`default_nettype none
////////////////////////////////////////////////////////////////////////
// 
// 4004 Arithmetic Logic Unit
// 
// This file is part of the MCS-4 project hosted at OpenCores:
//      http://www.opencores.org/cores/mcs-4/
// 
// Copyright © 2012, 2020 by Reece Pollack <rrpollack@opencores.org>
// 
// These materials are provided under the Creative Commons
// "Attribution-NonCommercial-ShareAlike" Public License. They
// are NOT "public domain" and are protected by copyright.
// 
// This work based on materials provided by Intel Corporation and
// others under the same license. See the file doc/License for
// details of this license.
//
////////////////////////////////////////////////////////////////////////
 
module alu(
	input  wire			sysclk,
 
	// Inputs from the Timing and I/O board
	input  wire			a12,
	input  wire			m12,
	input  wire			x12,
	input  wire			poc,
 
	// Common 4-bit data bus
	inout  wire	[3:0]	data,
 
	// Outputs to the Instruction Decode board
	output wire			acc_0,
	output wire			add_0,
	output reg			cy_1,
 
	// Inputs from the Instruction Decode board
	input  wire			cma,
	input  wire			write_acc_1,
	input  wire			write_carry_2,
	input  wire			read_acc_3,
	input  wire			add_group_4,
	input  wire			inc_group_5,
	input  wire			sub_group_6,
	input  wire			ior,
	input  wire			iow,
	input  wire			ral,
	input  wire			rar,
	input  wire			ope_n,
	input  wire			daa,
	input  wire			dcl,
	input  wire			inc_isz,
	input  wire			kbp,
	input  wire			o_ib,
	input  wire			tcs,
	input  wire			xch,
	input  wire			n0342,
	input  wire			x21_clk2,
	input  wire			x31_clk2,
	input  wire			com_n,
 
	// Outputs to external pins
	output wire			cmram0,
	output wire			cmram1,
	output wire			cmram2,
	output wire			cmram3,
	output wire			cmrom
	);
 
	reg [3:0]	acc;
	reg 		cy;
 
	// Decode logic
	wire n0854		= ~(~x12);
	wire n0351		= ~(x21_clk2 | ~dcl);
	wire n0415		= ~(x21_clk2 | ope_n);
	wire add_ib		= ~(x31_clk2 | ~inc_isz);
	wire cy_ib		= ~(x31_clk2 | ~iow);
	wire acb_ib		= ~((x31_clk2 | ~xch) & (x21_clk2 | ~iow));
	wire n0477		= ~((~x31_clk2 & ~ior) | (a12 & ior));
	wire adc_cy		= ~(write_carry_2 | n0477);
	wire add_acc	= ~(write_acc_1 | n0477);
	wire adsr		= ~(x31_clk2 | ~rar);
	wire adsl		= ~(x31_clk2 | ~ral);
	wire acc_adac	= ~(~cma | n0342);
	wire acc_ada	= ~(read_acc_3 | n0342);
	wire cy_ada		= ~(add_group_4 | n0342);
	wire cy_adac	= ~(sub_group_6 | n0342);
 
	// Latch the incoming data bus
	reg [3:0] tmp;					// It's the name used in simulator!
	always @(posedge sysclk) begin
		if (~n0342)
			tmp <= data;
		if (m12)
			tmp <= 4'b1111;
	end
 
	// Invert some of the incoming data
	reg n0893, n0891, n0889, n0887;	// D3, D2, D1, D0
	always @(posedge sysclk) begin
		if (sub_group_6) begin
			n0887 <=  tmp[0];
			n0889 <= ~tmp[1];
			n0891 <=  tmp[2];
			n0893 <= ~tmp[3];
		end
		if (~(sub_group_6 | m12)) begin
			n0887 <= ~tmp[0];
			n0889 <=  tmp[1];
			n0891 <= ~tmp[2];
			n0893 <=  tmp[3];
		end
	end
 
	// Feedback from Accumulator
	reg n0873, n0872, n0871, n0870;
	always @(posedge sysclk) begin
		if (acc_ada)
			{n0873, n0872, n0871, n0870} <= acc ^ 4'b1010;
		if (acc_adac)
			{n0873, n0872, n0871, n0870} <= acc ^ 4'b0101;
		if (m12)
			{n0873, n0872, n0871, n0870} <= 4'b1010;
	end
 
	// Carry generator
	wire n0546 = ~(inc_group_5 | n0342);
	reg n0550;
	always @(posedge sysclk) begin
		if (m12)		n0550 <= 1'b0;
		if (n0546)		n0550 <= 1'b1;
		if (cy_adac)	n0550 <= ~cy;
		if (cy_ada)		n0550 <= cy;
	end
	wire n0911 = ~(n0550 ? (n0887 | n0870) : (n0887 & n0870));
	wire n0553 = n0911;
	wire n0912 = ~(n0553 ? (n0889 | n0871) : (n0889 & n0871));
	wire n0556 = n0912;
	wire n0913 = ~(n0556 ? (n0891 | n0872) : (n0891 & n0872));
	wire n0559 = n0913;
	wire n0914 = ~(n0559 ? (n0893 | n0873) : (n0893 & n0873));
	wire n0861 = n0914;
 
	// Adder
	wire n0878 = ~((n0887 & n0550 & n0870) | (n0553 & (n0887 | n0870 | n0550)));
	wire n0875 = ~((n0889 & n0553 & n0871) | (n0556 & (n0889 | n0871 | n0553)));
	wire n0879 = ~((n0891 & n0556 & n0872) | (n0559 & (n0891 | n0872 | n0556)));
	wire n0877 = ~((n0893 & n0559 & n0873) | (n0861 & (n0893 | n0873 | n0559)));
	wire n0846 = ~n0878;
	wire n0847 =  n0875;
	wire n0848 = ~n0879;
	wire n0514 =  n0877;
 
	// Shifter / Accumulator and Carry
	reg [3:0] acc_out;					// {n0356, n0348, n0347, n0346}
	wire n0803 = ~((acc_out[3] & (acc_out[2] | acc_out[1])) | cy_1);
	wire n0403 = ~(~daa | n0803);
	wire [3:0] acc_in = {n0514, n0848, n0847, n0846};
	always @(posedge sysclk) begin
		if (adsr)
			{acc, cy} <= {cy_1, acc_in};
		if (add_acc)
			acc <= acc_in;
		if (adsl)
			{cy, acc} <= {acc_in, cy_1};
		if (adc_cy)
			cy <= n0861;
		if (n0403 & n0415)
			cy <= 1'b1;
		// Dynamic refresh would occur during M12
	end
 
	// Accumulator output latch
	always @(posedge sysclk) begin
		if (n0854) begin
			cy_1 <= cy;
			acc_out <= acc;
		end
	end
	assign acc_0 = ~|acc_out;
	assign add_0 = ~|acc_in;
 
	// Keyboard Process logic
	wire n0378 = ~((daa & n0803) | o_ib);
	wire n0345 =  kbp & (acc_out == 4'b1000);
	wire n0354 =  kbp & (acc_out == 4'b0100);
	wire n0363 =  kbp & (acc_out == 4'b0010);
	wire n0370 =  kbp & (acc_out == 4'b0001);
	wire n0377 = (kbp & (acc_out == 4'b0000)) | ~n0378;
	wire n0358 = ~(n0345 | n0354 | n0363 | n0370 | n0377 |       n0403);
	wire n0366 = ~(        n0354 | n0363 | n0370 | n0377 | tcs        );
	wire n0359 = ~(n0345 |                 n0370 | n0377 | tcs        );
	wire n0357 = ~(n0345 |         n0363 |         n0377 |       n0403);
 
	// Data output mux
	reg [3:0] dout;
	always @(*) begin
		dout = 4'bzzzz;
		if (acb_ib)
			dout = acc_out;
		if (add_ib)
			dout = acc_in;
		if (cy_ib)
			dout = {3'bxxx, cy_1};
		if (n0415)
			dout = {n0358, n0366, n0359, n0357};
	end
	assign data = dout;
 
	// Generate CMROM / CMRAMn
	// This may get moved to the Timing & I/O board
	// Inputs: {n0355, n0364, n0371}, n0351, poc, com_n
	wire n0355 = ~acc_out[2];
	wire n0364 = ~acc_out[1];
	wire n0371 = ~acc_out[0];
	reg n0749, n0750, n0751;
	always @(posedge sysclk) begin
		if (poc) begin
			n0749 <= 1'b1;
			n0750 <= 1'b1;
			n0751 <= 1'b1;
		end
		else begin
			if (n0351) begin
				n0749 <= n0355;
				n0750 <= n0364;
				n0751 <= n0371;
			end
		end
	end
 
	assign cmram3 = ~(com_n | n0749);
	assign cmram2 = ~(com_n | n0750);
	assign cmram1 = ~(com_n | n0751);
	assign cmram0 = ~(com_n | ~n0749 | ~n0750 | ~n0751);
	assign cmrom  = ~(com_n | poc);
 
endmodule
 

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

powered by: WebSVN 2.1.0

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