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

Subversion Repositories mcs-4

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /mcs-4/trunk/rtl/verilog/i4004
    from Rev 5 to Rev 6
    Reverse comparison

Rev 5 → Rev 6

/alu.v
1,18 → 1,18
`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, 2021 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.
//
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) 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.
20,222 → 20,222
////////////////////////////////////////////////////////////////////////
 
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,
input wire sysclk,
 
// Outputs to the Instruction Decode board
output wire acc_0,
output wire add_0,
output reg cy_1,
// Inputs from the Timing and I/O board
input wire a12,
input wire m12,
input wire x12,
input wire poc,
 
// 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
);
// Common 4-bit data bus
inout wire [3:0] data,
 
reg [3:0] acc;
reg cy;
// Outputs to the Instruction Decode board
output wire acc_0,
output wire add_0,
output reg cy_1,
 
// 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);
// 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,
 
// 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
// Outputs to external pins
output wire cmram0,
output wire cmram1,
output wire cmram2,
output wire cmram3,
output wire cmrom
);
 
// 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
reg [3:0] acc;
reg cy;
 
// 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;
// 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);
 
// 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;
// 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
 
// 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;
// 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
 
// 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);
// 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
 
// 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
// 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;
 
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);
// 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
/i4004.v
1,18 → 1,18
`timescale 1ns / 1ps
`default_nettype none
////////////////////////////////////////////////////////////////////////
//
//
// 4004 CPU Integration Module
//
//
// This file is part of the MCS-4 project hosted at OpenCores:
// http://www.opencores.org/cores/mcs-4/
//
 
//
//
// Copyright © 2012, 2021 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.
//
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) 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.
20,270 → 20,270
////////////////////////////////////////////////////////////////////////
 
module i4004(
input wire sysclk,
input wire clk1_pad,
input wire clk2_pad,
input wire poc_pad,
input wire test_pad,
inout wire [3:0] data_pad,
output wire cmrom_pad,
output wire cmram0_pad,
output wire cmram1_pad,
output wire cmram2_pad,
output wire cmram3_pad,
output wire sync_pad
input wire sysclk,
input wire clk1_pad,
input wire clk2_pad,
input wire poc_pad,
input wire test_pad,
inout wire [3:0] data_pad,
output wire cmrom_pad,
output wire cmram0_pad,
output wire cmram1_pad,
output wire cmram2_pad,
output wire cmram3_pad,
output wire sync_pad
);
 
// Common BiDir data bus
wire [3:0] data;
// Common BiDir data bus
wire [3:0] data;
 
// Timing and I/O Board Outputs
wire clk1;
wire clk2;
wire a12;
wire a22;
wire a32;
wire m12;
wire m22;
wire x12;
wire x22;
wire x32;
wire gate;
wire poc; // Clean POC_PAD
wire n0432; // Clean TEST_PAD
// Timing and I/O Board Outputs
wire clk1;
wire clk2;
wire a12;
wire a22;
wire a32;
wire m12;
wire m22;
wire x12;
wire x22;
wire x32;
wire gate;
wire poc; // Clean POC_PAD
wire n0432; // Clean TEST_PAD
 
// Outputs from the Instruction Decode board
wire jcn_isz;
wire jin_fin;
wire jun_jms;
wire cn_n;
wire bbl;
wire jms;
wire sc;
wire dc;
wire n0636;
wire sc_m22_clk2;
wire fin_fim_src_jin;
wire inc_isz_add_sub_xch_ld;
wire inc_isz_xch;
wire opa0_n;
wire cma;
wire write_acc_1;
wire write_carry_2;
wire read_acc_3;
wire add_group_4;
wire inc_group_5;
wire sub_group_6;
wire ior;
wire iow;
wire ral;
wire rar;
wire ope_n;
wire daa;
wire dcl;
wire inc_isz;
wire kbp;
wire o_ib;
wire tcs;
wire xch;
wire n0342;
wire x21_clk2;
wire x31_clk2;
wire com_n;
// Outputs from the Instruction Decode board
wire jcn_isz;
wire jin_fin;
wire jun_jms;
wire cn_n;
wire bbl;
wire jms;
wire sc;
wire dc;
wire n0636;
wire sc_m22_clk2;
wire fin_fim_src_jin;
wire inc_isz_add_sub_xch_ld;
wire inc_isz_xch;
wire opa0_n;
wire cma;
wire write_acc_1;
wire write_carry_2;
wire read_acc_3;
wire add_group_4;
wire inc_group_5;
wire sub_group_6;
wire ior;
wire iow;
wire ral;
wire rar;
wire ope_n;
wire daa;
wire dcl;
wire inc_isz;
wire kbp;
wire o_ib;
wire tcs;
wire xch;
wire n0342;
wire x21_clk2;
wire x31_clk2;
wire com_n;
 
// Outputs from the ALU board
wire acc_0;
wire add_0;
wire cy_1;
wire cmram0;
wire cmram1;
wire cmram2;
wire cmram3;
wire cmrom;
// Outputs from the ALU board
wire acc_0;
wire add_0;
wire cy_1;
wire cmram0;
wire cmram1;
wire cmram2;
wire cmram3;
wire cmrom;
 
// Instantiate the Timing and I/O board
timing_io tio_board (
.sysclk(sysclk),
.clk1_pad(clk1_pad),
.clk2_pad(clk2_pad),
.poc_pad(poc_pad),
.ior(ior),
.clk1(clk1),
.clk2(clk2),
.a12(a12),
.a22(a22),
.a32(a32),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.gate(gate),
.poc(poc),
.data(data),
.data_pad(data_pad),
.test_pad(test_pad),
.n0432(n0432),
.sync_pad(sync_pad),
.cmrom(cmrom),
.cmrom_pad(cmrom_pad),
.cmram0(cmram0),
.cmram0_pad(cmram0_pad),
.cmram1(cmram1),
.cmram1_pad(cmram1_pad),
.cmram2(cmram2),
.cmram2_pad(cmram2_pad),
.cmram3(cmram3),
.cmram3_pad(cmram3_pad)
);
// Instantiate the Timing and I/O board
timing_io tio_board (
.sysclk(sysclk),
.clk1_pad(clk1_pad),
.clk2_pad(clk2_pad),
.poc_pad(poc_pad),
.ior(ior),
.clk1(clk1),
.clk2(clk2),
.a12(a12),
.a22(a22),
.a32(a32),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.gate(gate),
.poc(poc),
.data(data),
.data_pad(data_pad),
.test_pad(test_pad),
.n0432(n0432),
.sync_pad(sync_pad),
.cmrom(cmrom),
.cmrom_pad(cmrom_pad),
.cmram0(cmram0),
.cmram0_pad(cmram0_pad),
.cmram1(cmram1),
.cmram1_pad(cmram1_pad),
.cmram2(cmram2),
.cmram2_pad(cmram2_pad),
.cmram3(cmram3),
.cmram3_pad(cmram3_pad)
);
 
// Instantiate the Instruction Decode board
instruction_decode id_board (
.sysclk(sysclk),
.clk1(clk1),
.clk2(clk2),
.a22(a22),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.poc(poc),
.n0432(n0432),
.data(data),
.jcn_isz(jcn_isz),
.jin_fin(jin_fin),
.jun_jms(jun_jms),
.cn_n(cn_n),
.bbl(bbl),
.jms(jms),
.sc(sc),
.dc(dc),
.n0636(n0636),
.sc_m22_clk2(sc_m22_clk2),
.fin_fim_src_jin(fin_fim_src_jin),
.inc_isz_add_sub_xch_ld(inc_isz_add_sub_xch_ld),
.inc_isz_xch(inc_isz_xch),
.opa0_n(opa0_n),
.acc_0(acc_0),
.add_0(add_0),
.cy_1(cy_1),
.cma(cma),
.write_acc_1(write_acc_1),
.write_carry_2(write_carry_2),
.read_acc_3(read_acc_3),
.add_group_4(add_group_4),
.inc_group_5(inc_group_5),
.sub_group_6(sub_group_6),
.ior(ior),
.iow(iow),
.ral(ral),
.rar(rar),
.ope_n(ope_n),
.daa(daa),
.dcl(dcl),
.inc_isz(inc_isz),
.kbp(kbp),
.o_ib(o_ib),
.tcs(tcs),
.xch(xch),
.n0342(n0342),
.x21_clk2(x21_clk2),
.x31_clk2(x31_clk2),
.com_n(com_n)
);
// Instantiate the Instruction Decode board
instruction_decode id_board (
.sysclk(sysclk),
.clk1(clk1),
.clk2(clk2),
.a22(a22),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.poc(poc),
.n0432(n0432),
.data(data),
.jcn_isz(jcn_isz),
.jin_fin(jin_fin),
.jun_jms(jun_jms),
.cn_n(cn_n),
.bbl(bbl),
.jms(jms),
.sc(sc),
.dc(dc),
.n0636(n0636),
.sc_m22_clk2(sc_m22_clk2),
.fin_fim_src_jin(fin_fim_src_jin),
.inc_isz_add_sub_xch_ld(inc_isz_add_sub_xch_ld),
.inc_isz_xch(inc_isz_xch),
.opa0_n(opa0_n),
.acc_0(acc_0),
.add_0(add_0),
.cy_1(cy_1),
.cma(cma),
.write_acc_1(write_acc_1),
.write_carry_2(write_carry_2),
.read_acc_3(read_acc_3),
.add_group_4(add_group_4),
.inc_group_5(inc_group_5),
.sub_group_6(sub_group_6),
.ior(ior),
.iow(iow),
.ral(ral),
.rar(rar),
.ope_n(ope_n),
.daa(daa),
.dcl(dcl),
.inc_isz(inc_isz),
.kbp(kbp),
.o_ib(o_ib),
.tcs(tcs),
.xch(xch),
.n0342(n0342),
.x21_clk2(x21_clk2),
.x31_clk2(x31_clk2),
.com_n(com_n)
);
 
// Instantiate the ALU board
alu alu_board (
.sysclk(sysclk),
.a12(a12),
.m12(m12),
.x12(x12),
.poc(poc),
.data(data),
.acc_0(acc_0),
.add_0(add_0),
.cy_1(cy_1),
.cma(cma),
.write_acc_1(write_acc_1),
.write_carry_2(write_carry_2),
.read_acc_3(read_acc_3),
.add_group_4(add_group_4),
.inc_group_5(inc_group_5),
.sub_group_6(sub_group_6),
.ior(ior),
.iow(iow),
.ral(ral),
.rar(rar),
.ope_n(ope_n),
.daa(daa),
.dcl(dcl),
.inc_isz(inc_isz),
.kbp(kbp),
.o_ib(o_ib),
.tcs(tcs),
.xch(xch),
.n0342(n0342),
.x21_clk2(x21_clk2),
.x31_clk2(x31_clk2),
.com_n(com_n),
.cmram0(cmram0),
.cmram1(cmram1),
.cmram2(cmram2),
.cmram3(cmram3),
.cmrom(cmrom)
);
// Instantiate the ALU board
alu alu_board (
.sysclk(sysclk),
.a12(a12),
.m12(m12),
.x12(x12),
.poc(poc),
.data(data),
.acc_0(acc_0),
.add_0(add_0),
.cy_1(cy_1),
.cma(cma),
.write_acc_1(write_acc_1),
.write_carry_2(write_carry_2),
.read_acc_3(read_acc_3),
.add_group_4(add_group_4),
.inc_group_5(inc_group_5),
.sub_group_6(sub_group_6),
.ior(ior),
.iow(iow),
.ral(ral),
.rar(rar),
.ope_n(ope_n),
.daa(daa),
.dcl(dcl),
.inc_isz(inc_isz),
.kbp(kbp),
.o_ib(o_ib),
.tcs(tcs),
.xch(xch),
.n0342(n0342),
.x21_clk2(x21_clk2),
.x31_clk2(x31_clk2),
.com_n(com_n),
.cmram0(cmram0),
.cmram1(cmram1),
.cmram2(cmram2),
.cmram3(cmram3),
.cmrom(cmrom)
);
 
// Instantiate the Instruction Pointer board
instruction_pointer ip_board (
.sysclk(sysclk),
.clk1(clk1),
.clk2(clk2),
.a12(a12),
.a22(a22),
.a32(a32),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.poc(poc),
.m12_m22_clk1_m11_m12(gate),
.data(data),
.jcn_isz(jcn_isz),
.jin_fin(jin_fin),
.jun_jms(jun_jms),
.cn_n(cn_n),
.bbl(bbl),
.jms(jms),
.sc(sc),
.dc(dc)
);
// Instantiate the Instruction Pointer board
instruction_pointer ip_board (
.sysclk(sysclk),
.clk1(clk1),
.clk2(clk2),
.a12(a12),
.a22(a22),
.a32(a32),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.poc(poc),
.m12_m22_clk1_m11_m12(gate),
.data(data),
.jcn_isz(jcn_isz),
.jin_fin(jin_fin),
.jun_jms(jun_jms),
.cn_n(cn_n),
.bbl(bbl),
.jms(jms),
.sc(sc),
.dc(dc)
);
 
// Instantiate the Scratchpad board
scratchpad sp_board (
.sysclk(sysclk),
.clk1(clk1),
.clk2(clk2),
.a12(a12),
.a22(a22),
.a32(a32),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.poc(poc),
.m12_m22_clk1_m11_m12(gate),
.data(data),
.n0636(n0636),
.sc_m22_clk2(sc_m22_clk2),
.fin_fim_src_jin(fin_fim_src_jin),
.inc_isz_add_sub_xch_ld(inc_isz_add_sub_xch_ld),
.inc_isz_xch(inc_isz_xch),
.opa0_n(opa0_n),
.sc(sc),
.dc(dc)
);
// Instantiate the Scratchpad board
scratchpad sp_board (
.sysclk(sysclk),
.clk1(clk1),
.clk2(clk2),
.a12(a12),
.a22(a22),
.a32(a32),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.poc(poc),
.m12_m22_clk1_m11_m12(gate),
.data(data),
.n0636(n0636),
.sc_m22_clk2(sc_m22_clk2),
.fin_fim_src_jin(fin_fim_src_jin),
.inc_isz_add_sub_xch_ld(inc_isz_add_sub_xch_ld),
.inc_isz_xch(inc_isz_xch),
.opa0_n(opa0_n),
.sc(sc),
.dc(dc)
);
 
endmodule
/i4004_tb.v
0,0 → 1,174
`timescale 1ns / 1ps
`default_nettype none
////////////////////////////////////////////////////////////////////////
//
// MCS-4 i4004 CPU testbench
//
// This module is a testbench for the i4004 and related modules.
//
// This testbench instantiates an i4004 CPU module, i4001 and
// i4001_rom ROM modules, and an i4002 RAM module, so that the
// simulation can be compared with that of Lagos Kintle's software
// emulator.
//
// This file is part of the MCS-4 project hosted at OpenCores:
// http://www.opencores.org/cores/mcs-4/
//
// Copyright © 2021 by Reece Pollack <rrpollack@opencores.org>
//
// These materials are provided under the Creative Commons
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) 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 i4004_tb;
 
localparam SYSCLK_TCY = 50; // 20 MHz Oscillator period in ns
// localparam SYSCLK_TCY = 20; // 50 MHz Oscillator period in ns
 
// Inputs
reg sysclk = 1'b0;
reg poc_pad = 1'b1;
reg test_pad = 1'b1;
reg clear_pad = 1'b0;
wire clk1_pad;
wire clk2_pad;
 
// Outputs
wire cmrom_pad;
wire cmram0_pad;
wire cmram1_pad;
wire cmram2_pad;
wire cmram3_pad;
wire sync_pad;
 
// Bidirs
wire [3:0] data_pad;
wire [3:0] io_pad;
 
// Generate a system clock
always begin
sysclk = 1'b0;
#(SYSCLK_TCY / 2);
sysclk = 1'b1;
#(SYSCLK_TCY / 2);
end
 
// Instantiate the 2-phase clock generator
clockgen #(
.SYSCLK_TCY (SYSCLK_TCY)
) clockgen (
.sysclk (sysclk),
.clk1 (clk1_pad),
.clk2 (clk2_pad)
);
 
// Instantiate a 4001 ROM chip
wire [11:0] rom_addr;
wire [ 7:0] rom_data;
i4001 #(
.ROM_NUMBER(4'd0),
.IO_OUTPUT(4'b1111)
) rom_0 (
.sysclk(sysclk),
.clk1_pad(clk1_pad),
.clk2_pad(clk2_pad),
.sync_pad(sync_pad),
.poc_pad(poc_pad),
.cmrom_pad(cmrom_pad),
.data_pad(data_pad),
.io_pad(io_pad),
.clear_pad(clear_pad),
.rom_addr(rom_addr),
.rom_data(rom_data)
);
 
i4001_rom #(
.ROM_NUMBER(4'd0)
) rom_store (
.sysclk(sysclk),
.rom_addr(rom_addr),
.rom_data(rom_data)
);
 
// Instantiate a 4002 RAM chip
wire [3:0] oport;
i4002 ram_0 (
.sysclk (sysclk),
.clk1 (clk1_pad),
.clk2 (clk2_pad),
.sync (sync_pad),
.reset (poc_pad),
.cm (cmram0_pad),
.data (data_pad),
.oport (oport),
.ram0_addr2 (5'h00),
.ram0_data2_out (),
.ram1_addr2 (5'h00),
.ram1_data2_out (),
.ram2_addr2 (5'h00),
.ram2_data2_out (),
.ram3_addr2 (5'h00),
.ram3_data2_out ()
);
 
// Instantiate the Unit Under Test (UUT)
i4004 i4004 (
.clk1_pad(clk1_pad),
.clk2_pad(clk2_pad),
.poc_pad(poc_pad),
.test_pad(test_pad),
.data_pad(data_pad),
.cmrom_pad(cmrom_pad),
.cmram0_pad(cmram0_pad),
.cmram1_pad(cmram1_pad),
.cmram2_pad(cmram2_pad),
.cmram3_pad(cmram3_pad),
.sync_pad(sync_pad)
);
 
// Simplify access to internal registers
wire [3:0] acc = i4004.alu_board.acc;
wire cy = i4004.alu_board.cy;
 
wire [7:0] r0r1 = i4004.sp_board.dram_array[0];
wire [7:0] r2r3 = i4004.sp_board.dram_array[1];
wire [7:0] r4r5 = i4004.sp_board.dram_array[2];
wire [7:0] r6r7 = i4004.sp_board.dram_array[3];
wire [7:0] r8r9 = i4004.sp_board.dram_array[4];
wire [7:0] rarb = i4004.sp_board.dram_array[5];
wire [7:0] rcrd = i4004.sp_board.dram_array[6];
wire [7:0] rerf = i4004.sp_board.dram_array[7];
 
wire [11:0] ip0 = i4004.ip_board.dram_array[0];
wire [11:0] ip1 = i4004.ip_board.dram_array[1];
wire [11:0] ip2 = i4004.ip_board.dram_array[2];
wire [11:0] ip3 = i4004.ip_board.dram_array[3];
wire [1:0] ptr = i4004.ip_board.addr_ptr;
 
// Count cycles to make it easier to sync with the analyzer
integer cycle = 1;
always @(posedge clk1_pad or negedge clk1_pad or
posedge clk2_pad or negedge clk2_pad) begin
cycle = cycle + 1;
if (cycle == 1100) begin
// Bring us out of reset
poc_pad = 1'b0;
end
end
 
// initial begin
// // Wait for 33 SYNCs to allow the i4002 RAMs to initialize
// repeat (33)
// @(posedge sync_pad);
 
// // Bring us out of reset
// poc_pad = 1'b0;
// end
 
endmodule
/instruction_decode.v
1,18 → 1,18
`timescale 1ns / 1ps
`default_nettype none
////////////////////////////////////////////////////////////////////////
//
//
// 4004 Instruction Decoder
//
//
// This file is part of the MCS-4 project hosted at OpenCores:
// http://www.opencores.org/cores/mcs-4/
//
 
//
//
// Copyright © 2012, 2021 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.
//
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) 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.
20,239 → 20,239
////////////////////////////////////////////////////////////////////////
 
module instruction_decode(
input wire sysclk, // 50 MHz FPGA clock
// Inputs from the Timing and I/O board
input wire clk1,
input wire clk2,
input wire a22,
input wire m12,
input wire m22,
input wire x12,
input wire x22,
input wire x32,
input wire poc, // Power-On Clear (reset)
input wire n0432, // Conditioned TEST_PAD
input wire sysclk, // 50 MHz FPGA clock
 
// Common 4-bit data bus
inout wire [3:0] data,
// Inputs from the Timing and I/O board
input wire clk1,
input wire clk2,
input wire a22,
input wire m12,
input wire m22,
input wire x12,
input wire x22,
input wire x32,
input wire poc, // Power-On Clear (reset)
input wire n0432, // Conditioned TEST_PAD
 
// These drive the Instruction Pointer (IP) board
output wire jcn_isz, // JCN+ISZ
output wire jin_fin, // JIN+FIN
output wire jun_jms, // JUN+JMS
output wire cn_n, // ~CN
output wire bbl, // BBL
output wire jms, // JMS
// Outputs to both the IP and SP boards
output wire sc, // SC (Single Cycle)
output wire dc, // DC (Double Cycle, ~SC)
// Common 4-bit data bus
inout wire [3:0] data,
 
// Outputs to the Scratch Pad (SP) board
output wire n0636, // JIN+FIN
output wire sc_m22_clk2, // SC&M22&CLK2
output wire fin_fim_src_jin, // FIN+FIM+SRC+JIN
output wire inc_isz_add_sub_xch_ld, // INC+ISZ+ADD+SUB+XCH+LD
output wire inc_isz_xch, // INC+ISZ+XCH
output wire opa0_n, // ~OPA.0
// These drive the Instruction Pointer (IP) board
output wire jcn_isz, // JCN+ISZ
output wire jin_fin, // JIN+FIN
output wire jun_jms, // JUN+JMS
output wire cn_n, // ~CN
output wire bbl, // BBL
output wire jms, // JMS
 
// Inputs from the ALU board (condition bits)
input wire acc_0, // ACC_0
input wire add_0, // ADD_0
input wire cy_1, // CY_1
// Outputs to both the IP and SP boards
output wire sc, // SC (Single Cycle)
output wire dc, // DC (Double Cycle, ~SC)
 
// Outputs to the Arithmetic Logic Unit (ALU) board
output wire cma,
output wire write_acc_1,
output wire write_carry_2,
output wire read_acc_3,
output wire add_group_4,
output wire inc_group_5,
output wire sub_group_6,
output wire ior,
output wire iow,
output wire ral,
output wire rar,
output wire ope_n,
output wire daa,
output wire dcl,
output wire inc_isz,
output wire kbp,
output wire o_ib,
output wire tcs,
output wire xch,
output wire n0342,
output wire x21_clk2,
output wire x31_clk2,
output wire com_n
);
wire sc_m12_clk2 = sc & m12 & clk2;
assign sc_m22_clk2 = sc & m22 & clk2;
// Outputs to the Scratch Pad (SP) board
output wire n0636, // JIN+FIN
output wire sc_m22_clk2, // SC&M22&CLK2
output wire fin_fim_src_jin, // FIN+FIM+SRC+JIN
output wire inc_isz_add_sub_xch_ld, // INC+ISZ+ADD+SUB+XCH+LD
output wire inc_isz_xch, // INC+ISZ+XCH
output wire opa0_n, // ~OPA.0
 
// Latch the first 4 bits of the opcode
reg [3:0] opr = 4'b0000;
always @(posedge sysclk) begin
if (sc_m12_clk2)
opr <= data;
end
// Latch the second 4 bits of the opcode
reg [3:0] opa = 4'b0000;
always @(posedge sysclk) begin
if (sc_m22_clk2)
opa <= data;
end
assign opa0_n = ~opa[0];
// Full OPR Decoding
wire nop = (opr == 4'b0000);
wire jcn = (opr == 4'b0001);
wire fim_src = (opr == 4'b0010);
assign jin_fin = (opr == 4'b0011);
wire jun = (opr == 4'b0100);
assign jms = (opr == 4'b0101);
wire inc = (opr == 4'b0110);
wire isz = (opr == 4'b0111);
wire add = (opr == 4'b1000);
wire sub = (opr == 4'b1001);
wire ld = (opr == 4'b1010);
assign xch = (opr == 4'b1011);
assign bbl = (opr == 4'b1100);
wire ldm = (opr == 4'b1101);
wire io = (opr == 4'b1110);
wire ope = (opr == 4'b1111);
assign ope_n = ~ope;
assign n0636 = jin_fin;
assign jcn_isz = jcn | isz;
assign jun_jms = jun | jms;
wire ldm_bbl = ldm | bbl;
assign inc_isz = (inc | isz) & sc;
assign inc_isz_xch = inc | isz | xch;
assign inc_isz_add_sub_xch_ld = inc | isz | add | sub | xch | ld;
assign fin_fim_src_jin = fim_src | jin_fin;
// OPE: OPA Decoding
assign o_ib = ope & (opa[3] == 1'b0);
wire clb = ope & (opa == 4'b0000);
wire clc = ope & (opa == 4'b0001);
wire iac = ope & (opa == 4'b0010);
wire cmc = ope & (opa == 4'b0011);
assign cma = ope & (opa == 4'b0100);
assign ral = ope & (opa == 4'b0101);
assign rar = ope & (opa == 4'b0110);
wire tcc = ope & (opa == 4'b0111);
wire dac = ope & (opa == 4'b1000);
assign tcs = ope & (opa == 4'b1001);
wire stc = ope & (opa == 4'b1010);
assign daa = ope & (opa == 4'b1011);
assign kbp = ope & (opa == 4'b1100);
assign dcl = ope & (opa == 4'b1101);
// Inputs from the ALU board (condition bits)
input wire acc_0, // ACC_0
input wire add_0, // ADD_0
input wire cy_1, // CY_1
 
// IO: OPA Decoding
assign iow = io & (opa[3] == 1'b0);
assign ior = io & (opa[3] == 1'b1);
wire adm = io & (opa == 4'b1011);
wire sbm = io & (opa == 4'b1000);
// Outputs to the Arithmetic Logic Unit (ALU) board
output wire cma,
output wire write_acc_1,
output wire write_carry_2,
output wire read_acc_3,
output wire add_group_4,
output wire inc_group_5,
output wire sub_group_6,
output wire ior,
output wire iow,
output wire ral,
output wire rar,
output wire ope_n,
output wire daa,
output wire dcl,
output wire inc_isz,
output wire kbp,
output wire o_ib,
output wire tcs,
output wire xch,
output wire n0342,
output wire x21_clk2,
output wire x31_clk2,
output wire com_n
);
 
wire fin_fim = fin_fim_src_jin & ~opa[0];
wire src = fim_src & opa[0];
assign write_acc_1 = ~(kbp | tcs | daa | xch | poc | cma | tcc | dac | iac |
clb | ior | ld | sub | add | ldm_bbl);
assign write_carry_2 = ~(tcs | poc | tcc | stc | cmc | dac | iac |
clc | clb | sbm | adm | sub | add);
assign read_acc_3 = ~(daa | rar | ral | dac | iac | sbm | adm | sub | add);
assign add_group_4 = ~(tcs | tcc | adm | add);
assign inc_group_5 = ~(inc_isz | stc | iac);
assign sub_group_6 = ~(cmc | sbm | sub | m12);
wire sc_m12_clk2 = sc & m12 & clk2;
assign sc_m22_clk2 = sc & m22 & clk2;
 
// The Condition Flip-Flop
reg n0397;
wire n0486 = ~((opa[2] & acc_0) | (opa[1] & cy_1) | (opa[0] & n0432));
wire n0419 = ~((add_0 | ~isz) & (~jcn | ((n0486 | opa[3]) & (~n0486 | ~opa[3]))));
wire n0413 = ~((sc & n0419 & x32) | (~x32 & n0397));
reg n0405;
always @(posedge sysclk) begin
if (clk2)
n0405 <= n0413;
end
always @(posedge sysclk) begin
if (clk1)
n0397 <= ~n0405;
end
assign cn_n = ~n0397;
// Latch the first 4 bits of the opcode
reg [3:0] opr = 4'b0000;
always @(posedge sysclk) begin
if (sc_m12_clk2)
opr <= data;
end
 
// The Single-Cycle Flip-Flop
reg n0343 = 1'b0;
wire n0368 = ~((sc & (fin_fim | jcn_isz | jun_jms) & x32) | (n0343 & ~x32));
reg n0362 = 1'b1;
always @(posedge sysclk) begin
if (clk2)
n0362 <= n0368;
if (clk1)
n0343 <= ~n0362;
end
assign sc = ~n0343;
assign dc = ~sc;
// Latch the second 4 bits of the opcode
reg [3:0] opa = 4'b0000;
always @(posedge sysclk) begin
if (sc_m22_clk2)
opa <= data;
end
assign opa0_n = ~opa[0];
 
// Generate ~(X21&~CLK2)
reg n0360;
always @(posedge sysclk) begin
if (clk2)
n0360 <= ~x12;
end
wire n0337 = ~(n0360 | clk2);
assign x21_clk2 = ~n0337;
// Full OPR Decoding
wire nop = (opr == 4'b0000);
wire jcn = (opr == 4'b0001);
wire fim_src = (opr == 4'b0010);
assign jin_fin = (opr == 4'b0011);
wire jun = (opr == 4'b0100);
assign jms = (opr == 4'b0101);
wire inc = (opr == 4'b0110);
wire isz = (opr == 4'b0111);
wire add = (opr == 4'b1000);
wire sub = (opr == 4'b1001);
wire ld = (opr == 4'b1010);
assign xch = (opr == 4'b1011);
assign bbl = (opr == 4'b1100);
wire ldm = (opr == 4'b1101);
wire io = (opr == 4'b1110);
wire ope = (opr == 4'b1111);
 
// Generate ~(X31&~CLK2)
reg n0380;
always @(posedge sysclk) begin
if (clk2)
n0380 <= ~x22;
end
wire n0375 = ~(n0380 | clk2);
assign x31_clk2 = ~n0375;
// Generate ~COM
wire n0329 = io;
assign ope_n = ~ope;
assign n0636 = jin_fin;
assign jcn_isz = jcn | isz;
assign jun_jms = jun | jms;
wire ldm_bbl = ldm | bbl;
assign inc_isz = (inc | isz) & sc;
assign inc_isz_xch = inc | isz | xch;
assign inc_isz_add_sub_xch_ld = inc | isz | add | sub | xch | ld;
assign fin_fim_src_jin = fim_src | jin_fin;
 
reg n0414, n0797;
always @(posedge sysclk) begin
if (clk2)
n0414 <= a22;
else
n0797 <= n0414;
end
// OPE: OPA Decoding
assign o_ib = ope & (opa[3] == 1'b0);
wire clb = ope & (opa == 4'b0000);
wire clc = ope & (opa == 4'b0001);
wire iac = ope & (opa == 4'b0010);
wire cmc = ope & (opa == 4'b0011);
assign cma = ope & (opa == 4'b0100);
assign ral = ope & (opa == 4'b0101);
assign rar = ope & (opa == 4'b0110);
wire tcc = ope & (opa == 4'b0111);
 
reg n0433, n0801;
always @(posedge sysclk) begin
if (clk2)
n0433 <= m12;
else
n0801 <= n0433;
end
reg n0425, n0805;
always @(posedge sysclk) begin
if (clk2)
n0425 <= x12;
else
n0805 <= n0425;
end
wire dac = ope & (opa == 4'b1000);
assign tcs = ope & (opa == 4'b1001);
wire stc = ope & (opa == 4'b1010);
assign daa = ope & (opa == 4'b1011);
assign kbp = ope & (opa == 4'b1100);
assign dcl = ope & (opa == 4'b1101);
 
wire n0782 = ~((n0801 & n0329) | (src & n0805) | n0797);
assign com_n = n0782;
// Generate N0342
wire n0332 = ~(((n0329 | poc) & x22 & clk2) | (~(n0329 | poc) & n0337 & clk1));
assign n0342 = n0332;
// IO: OPA Decoding
assign iow = io & (opa[3] == 1'b0);
assign ior = io & (opa[3] == 1'b1);
wire adm = io & (opa == 4'b1011);
wire sbm = io & (opa == 4'b1000);
 
// Output OPA onto the data bus
wire opa_ib = (ldm_bbl | jun_jms) & ~x21_clk2;
assign data = opa_ib ? opa : 4'bzzzz;
wire fin_fim = fin_fim_src_jin & ~opa[0];
wire src = fim_src & opa[0];
 
assign write_acc_1 = ~(kbp | tcs | daa | xch | poc | cma | tcc | dac | iac |
clb | ior | ld | sub | add | ldm_bbl);
assign write_carry_2 = ~(tcs | poc | tcc | stc | cmc | dac | iac |
clc | clb | sbm | adm | sub | add);
assign read_acc_3 = ~(daa | rar | ral | dac | iac | sbm | adm | sub | add);
assign add_group_4 = ~(tcs | tcc | adm | add);
assign inc_group_5 = ~(inc_isz | stc | iac);
assign sub_group_6 = ~(cmc | sbm | sub | m12);
 
// The Condition Flip-Flop
reg n0397;
wire n0486 = ~((opa[2] & acc_0) | (opa[1] & cy_1) | (opa[0] & n0432));
wire n0419 = ~((add_0 | ~isz) & (~jcn | ((n0486 | opa[3]) & (~n0486 | ~opa[3]))));
wire n0413 = ~((sc & n0419 & x32) | (~x32 & n0397));
reg n0405;
always @(posedge sysclk) begin
if (clk2)
n0405 <= n0413;
end
always @(*) begin
if (clk1)
n0397 <= ~n0405;
end
assign cn_n = ~n0397;
 
// The Single-Cycle Flip-Flop
reg n0343 = 1'b0;
wire n0368 = ~((sc & (fin_fim | jcn_isz | jun_jms) & x32) | (n0343 & ~x32));
reg n0362 = 1'b1;
always @(posedge sysclk) begin
if (clk2)
n0362 <= n0368;
if (clk1)
n0343 <= ~n0362;
end
assign sc = ~n0343;
assign dc = ~sc;
 
// Generate ~(X21&~CLK2)
reg n0360;
always @(posedge sysclk) begin
if (clk2)
n0360 <= ~x12;
end
wire n0337 = ~(n0360 | clk2);
assign x21_clk2 = ~n0337;
 
// Generate ~(X31&~CLK2)
reg n0380;
always @(posedge sysclk) begin
if (clk2)
n0380 <= ~x22;
end
wire n0375 = ~(n0380 | clk2);
assign x31_clk2 = ~n0375;
 
// Generate ~COM
wire n0329 = io;
 
reg n0414, n0797;
always @(posedge sysclk) begin
if (clk2)
n0414 <= a22;
else
n0797 <= n0414;
end
 
reg n0433, n0801;
always @(posedge sysclk) begin
if (clk2)
n0433 <= m12;
else
n0801 <= n0433;
end
 
reg n0425, n0805;
always @(posedge sysclk) begin
if (clk2)
n0425 <= x12;
else
n0805 <= n0425;
end
 
wire n0782 = ~((n0801 & n0329) | (src & n0805) | n0797);
assign com_n = n0782;
 
// Generate N0342
wire n0332 = ~(((n0329 | poc) & x22 & clk2) | (~(n0329 | poc) & n0337 & clk1));
assign n0342 = n0332;
 
// Output OPA onto the data bus
wire opa_ib = (ldm_bbl | jun_jms) & ~x21_clk2;
assign data = opa_ib ? opa : 4'bzzzz;
 
endmodule
/instruction_pointer.v
1,18 → 1,18
`timescale 1ns / 1ps
`default_nettype none
////////////////////////////////////////////////////////////////////////
//
//
// 4004 Instruction Pointer Array
//
//
// This file is part of the MCS-4 project hosted at OpenCores:
// http://www.opencores.org/cores/mcs-4/
//
 
//
//
// Copyright © 2012, 2021 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.
//
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) 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.
20,195 → 20,212
////////////////////////////////////////////////////////////////////////
 
module instruction_pointer (
input wire sysclk, // 50 MHz FPGA clock
input wire sysclk, // 50 MHz FPGA clock
 
// Inputs from the Timing and I/O board
input wire clk1,
input wire clk2,
input wire a12,
input wire a22,
input wire a32,
input wire m12,
input wire m22,
input wire x12,
input wire x22,
input wire x32,
input wire poc, // Power-On Clear (reset)
input wire m12_m22_clk1_m11_m12, // M12+M22+CLK1~(M11+M12)
// Inputs from the Timing and I/O board
input wire clk1,
input wire clk2,
input wire a12,
input wire a22,
input wire a32,
input wire m12,
input wire m22,
input wire x12,
input wire x22,
input wire x32,
input wire poc, // Power-On Clear (reset)
input wire m12_m22_clk1_m11_m12, // M12+M22+CLK1~(M11+M12)
 
// Common 4-bit data bus
inout wire [3:0] data,
// Common 4-bit data bus
inout wire [3:0] data,
 
// Inputs from the Instruction Decode board
input wire jcn_isz, // JCN+ISZ
input wire jin_fin, // JIN+FIN
input wire jun_jms, // JUN+JMS
input wire cn_n, // ~CN
input wire bbl, // BBL
input wire jms, // JMS
input wire sc, // SC (Single Cycle)
input wire dc // DC (Double Cycle, ~SC)
);
// Inputs from the Instruction Decode board
input wire jcn_isz, // JCN+ISZ
input wire jin_fin, // JIN+FIN
input wire jun_jms, // JUN+JMS
input wire cn_n, // ~CN
input wire bbl, // BBL
input wire jms, // JMS
input wire sc, // SC (Single Cycle)
input wire dc // DC (Double Cycle, ~SC)
);
 
reg [11:0] dram_array [0:3];
reg [11:0] dram_temp;
wire [3:0] din_n;
reg [11:0] dram_array [0:3];
reg [11:0] dram_temp;
wire [3:0] din_n;
 
wire inh = (jin_fin & sc) | ((jun_jms | (jcn_isz & ~cn_n)) & dc);
wire inh = (jin_fin & sc) | ((jun_jms | (jcn_isz & ~cn_n)) & dc);
 
// Row Counter stuff
wire [1:0] addr_ptr; // Effective Address counter
wire addr_ptr_step; // CLK2(JMS&DC&M22+BBL(M22+X12+X22))
assign addr_ptr_step = ~(~clk2 | ~(((m22 | x12 | x22) & bbl) |
(m22 & dc & jms)));
counter addr_ptr_0 (
.sysclk(sysclk),
.step_a(clk1),
.step_b(addr_ptr_step),
.q(addr_ptr[0])
);
counter addr_ptr_1 (
.sysclk(sysclk),
.step_a( addr_ptr[0]),
.step_b(~addr_ptr[0]),
.q(addr_ptr[1])
);
// Row Counter stuff
wire [1:0] addr_ptr; // Effective Address counter
wire addr_ptr_step; // CLK2(JMS&DC&M22+BBL(M22+X12+X22))
wire n0459;
wire n0466;
 
// Refresh counter stuff
wire [1:0] addr_rfsh; // Row Refresh counter
wire addr_rfsh_step; // (~INH)&X32&CLK2
assign addr_rfsh_step = ~inh & x32 & clk2;
counter addr_rfsh_0 (
.sysclk(sysclk),
.step_a(clk1),
.step_b(addr_rfsh_step),
.q(addr_rfsh[0])
);
counter addr_rfsh_1 (
.sysclk(sysclk),
.step_a( addr_rfsh[0]),
.step_b(~addr_rfsh[0]),
.q(addr_rfsh[1])
);
assign addr_ptr_step = ~(~clk2 | ~(((m22 | x12 | x22) & bbl) |
(m22 & dc & jms)));
counter addr_ptr_0 (
.sysclk(sysclk),
.step_a_in(clk1),
.step_b_in(addr_ptr_step),
.step_a_out(n0459),
.step_b_out(n0466),
.q(),
.qn(addr_ptr[0])
);
counter addr_ptr_1 (
.sysclk(sysclk),
.step_a_in(n0459),
.step_b_in(n0466),
.step_a_out(),
.step_b_out(),
.q(),
.qn(addr_ptr[1])
);
 
// Row selection mux
reg [1:0] row; // {N0409, N0420}
always @(posedge sysclk) begin
if (x12)
row <= addr_rfsh;
if (x32)
row <= addr_ptr;
end
// Refresh counter stuff
wire [1:0] addr_rfsh; // Row Refresh counter
wire addr_rfsh_step; // (~INH)&X32&CLK2
wire n0455;
wire n0463;
 
assign addr_rfsh_step = ~inh & x32 & clk2;
 
// Row Precharge/Read/Write stuff
wire precharge; // (~INH)(X11+X31)CLK1
wire row_read; // (~POC)CLK2(X12+X32)~INH
wire row_write; // ((~SC)(JIN+FIN))CLK1(M11+X21~INH)
counter addr_rfsh_0 (
.sysclk(sysclk),
.step_a_in(clk1),
.step_b_in(addr_rfsh_step),
.step_a_out(n0455),
.step_b_out(n0463),
.q(),
.qn(addr_rfsh[0])
);
counter addr_rfsh_1 (
.sysclk(sysclk),
.step_a_in(n0455),
.step_b_in(n0463),
.step_a_out(),
.step_b_out(),
.q(),
.qn(addr_rfsh[1])
);
 
reg n0517;
always @(posedge sysclk) begin
if (clk2)
n0517 <= ~(m22 | x22);
end
assign precharge = ~(n0517 | inh | ~clk1);
// Row selection mux
reg [1:0] row; // {N0409, N0420}
always @(posedge sysclk) begin
if (x12)
row <= addr_rfsh;
if (x32)
row <= addr_ptr;
end
 
assign row_read = ~poc & clk2 & (x12 | x32) & ~inh;
reg n0438;
always @(posedge sysclk) begin
if (clk2)
n0438 <= ~((x12 & ~inh) | a32);
end
assign row_write = ~(n0438 | (jin_fin & ~sc) | ~clk1);
 
// Row Precharge/Read/Write stuff
wire precharge; // (~INH)(X11+X31)CLK1
wire row_read; // (~POC)CLK2(X12+X32)~INH
wire row_write; // ((~SC)(JIN+FIN))CLK1(M11+X21~INH)
 
// Column Read selection stuff
reg n0416;
always @(posedge sysclk) begin
if (clk2)
n0416 <= ~x32;
end
wire radb0 = ~(n0416 | clk2);
reg n0517;
always @(posedge sysclk) begin
if (clk2)
n0517 <= ~(m22 | x22);
end
assign precharge = ~(n0517 | inh | ~clk1);
 
reg n0384;
always @(posedge sysclk) begin
if (clk2)
n0384 <= ~a12;
end
wire radb1 = ~(n0384 | clk2);
assign row_read = ~poc & clk2 & (x12 | x32) & ~inh;
 
reg n0374;
always @(posedge sysclk) begin
if (clk2)
n0374 <= ~a22;
end
wire radb2 = ~(n0374 | clk2);
reg n0438;
always @(posedge sysclk) begin
if (clk2)
n0438 <= ~((x12 & ~inh) | a32);
end
assign row_write = ~(n0438 | (jin_fin & ~sc) | ~clk1);
 
 
// Column Write selection stuff
wire n0322 = ~(sc | cn_n);
wire wadb0 = ~(~clk2 | ~(a12 | (sc & jin_fin & x32) |
(((jcn_isz & n0322) | (jun_jms & ~sc)) & m22)));
wire wadb1 = ~(~clk2 | ~(a22 | (sc & jin_fin & x22) |
(((jcn_isz & n0322) | (jun_jms & ~sc)) & m12)));
wire wadb2 = ~(~clk2 | ~(a32 | (jun_jms & ~sc & x22)));
// Column Read selection stuff
reg n0416;
always @(posedge sysclk) begin
if (clk2)
n0416 <= ~x32;
end
wire radb0 = ~(n0416 | clk2);
 
reg n0384;
always @(posedge sysclk) begin
if (clk2)
n0384 <= ~a12;
end
wire radb1 = ~(n0384 | clk2);
 
// Manage the row data buffer
always @(posedge sysclk) begin
if (precharge)
dram_temp <= 12'b0;
if (row_read)
dram_temp <= dram_array[row];
if (wadb0)
dram_temp[ 3:0] <= ~din_n;
if (wadb1)
dram_temp[ 7:4] <= ~din_n;
if (wadb2)
dram_temp[11:8] <= ~din_n;
end
reg n0374;
always @(posedge sysclk) begin
if (clk2)
n0374 <= ~a22;
end
wire radb2 = ~(n0374 | clk2);
 
// Handle row writes
always @(posedge sysclk) begin
if (row_write)
dram_array[row] <= dram_temp;
end
 
// Manage the data output mux
reg [3:0] dout;
always @* begin
(* PARALLEL_CASE *)
case (1'b1)
radb0: dout = dram_temp[ 3:0];
radb1: dout = dram_temp[ 7:4];
radb2: dout = dram_temp[11:8];
default: dout = 4'bzzzz;
endcase
end
assign data = dout;
// Data In mux and incrementer
reg [3:0] incr_in;
always @(posedge sysclk) begin
if (m12_m22_clk1_m11_m12)
incr_in <= data;
end
// Column Write selection stuff
wire n0322 = ~(sc | cn_n);
wire wadb0 = ~(~clk2 | ~(a12 | (sc & jin_fin & x32) |
(((jcn_isz & n0322) | (jun_jms & ~sc)) & m22)));
wire wadb1 = ~(~clk2 | ~(a22 | (sc & jin_fin & x22) |
(((jcn_isz & n0322) | (jun_jms & ~sc)) & m12)));
wire wadb2 = ~(~clk2 | ~(a32 | (jun_jms & ~sc & x22)));
 
reg carry_out, carry_in;
wire [4:0] incr_out = (a12 | ((a22 | a32) & carry_in)) ?
(incr_in + 4'b0001) : {1'b0, incr_in};
always @(posedge sysclk) begin
if (clk2)
carry_out <= incr_out[4];
if (clk1)
carry_in <= carry_out;
end
assign din_n = ~incr_out[3:0];
 
// Manage the row data buffer
wire [11:0] row_data = dram_array[row];
always @(posedge sysclk) begin
if (precharge)
dram_temp <= 12'b0;
 
if (row_read)
dram_temp <= row_data;
 
if (wadb0)
dram_temp[ 3:0] <= ~din_n;
if (wadb1)
dram_temp[ 7:4] <= ~din_n;
if (wadb2)
dram_temp[11:8] <= ~din_n;
end
 
// Handle row writes
always @(posedge sysclk) begin
if (row_write)
dram_array[row] <= dram_temp;
end
 
// Manage the data output mux
reg [3:0] dout;
always @(*) begin
(* PARALLEL_CASE *)
case (1'b1)
radb0: dout = dram_temp[ 3:0];
radb1: dout = dram_temp[ 7:4];
radb2: dout = dram_temp[11:8];
default: dout = 4'bzzzz;
endcase
end
assign data = dout;
 
// Data In mux and incrementer
reg [3:0] incr_in;
always @(posedge sysclk) begin
if (m12_m22_clk1_m11_m12)
incr_in <= data;
end
 
reg carry_out, carry_in;
wire [4:0] incr_out = (a12 | ((a22 | a32) & carry_in)) ?
(incr_in + 4'b0001) : {1'b0, incr_in};
always @(posedge sysclk) begin
if (clk2)
carry_out <= incr_out[4];
if (clk1)
carry_in <= carry_out;
end
assign din_n = ~incr_out[3:0];
 
endmodule
/scratchpad.v
1,18 → 1,18
`timescale 1ns / 1ps
`default_nettype none
////////////////////////////////////////////////////////////////////////
//
//
// 4004 Scratchpad Register Array
//
//
// This file is part of the MCS-4 project hosted at OpenCores:
// http://www.opencores.org/cores/mcs-4/
//
 
//
//
// Copyright © 2012, 2021 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.
//
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) 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.
20,149 → 20,163
////////////////////////////////////////////////////////////////////////
 
module scratchpad (
input wire sysclk, // 50 MHz FPGA clock
input wire sysclk, // 50 MHz FPGA clock
 
// Inputs from the Timing and I/O board
input wire clk1,
input wire clk2,
input wire a12,
input wire a22,
input wire a32,
input wire m12,
input wire m22,
input wire x12,
input wire x22,
input wire x32,
input wire poc, // Power-On Clear (reset)
input wire m12_m22_clk1_m11_m12, // M12+M22+CLK1~(M11+M12)
// Inputs from the Timing and I/O board
input wire clk1,
input wire clk2,
input wire a12,
input wire a22,
input wire a32,
input wire m12,
input wire m22,
input wire x12,
input wire x22,
input wire x32,
input wire poc, // Power-On Clear (reset)
input wire m12_m22_clk1_m11_m12, // M12+M22+CLK1~(M11+M12)
 
// Common 4-bit data bus
inout wire [3:0] data,
// Common 4-bit data bus
inout wire [3:0] data,
 
// Inputs from the Instruction Decode board
input wire n0636, // JIN+FIN
input wire sc_m22_clk2, // SC&M22&CLK2
input wire fin_fim_src_jin, // FIN+FIM+SRC+JIN
input wire inc_isz_add_sub_xch_ld, // INC+ISZ+ADD+SUB+XCH+LD
input wire inc_isz_xch, // INC+ISZ+XCH
input wire opa0_n, // ~OPA.0
input wire sc, // SC (Single Cycle)
input wire dc // DC (Double Cycle, ~SC)
);
// Inputs from the Instruction Decode board
input wire n0636, // JIN+FIN
input wire sc_m22_clk2, // SC&M22&CLK2
input wire fin_fim_src_jin, // FIN+FIM+SRC+JIN
input wire inc_isz_add_sub_xch_ld, // INC+ISZ+ADD+SUB+XCH+LD
input wire inc_isz_xch, // INC+ISZ+XCH
input wire opa0_n, // ~OPA.0
input wire sc, // SC (Single Cycle)
input wire dc // DC (Double Cycle, ~SC)
);
 
reg [7:0] dram_array [0:7];
reg [7:0] dram_temp;
reg [3:0] din_n;
reg [7:0] dram_array [0:7];
reg [7:0] dram_temp;
reg [3:0] din_n;
 
// Refresh counter stuff
wire [2:0] reg_rfsh; // Row Refresh counter
wire reg_rfsh_step; // SC&A12&CLK2
assign reg_rfsh_step = sc & a12 & clk2;
counter reg_rfsh_0 (
.sysclk(sysclk),
.step_a(clk1),
.step_b(reg_rfsh_step),
.q(reg_rfsh[0])
);
counter reg_rfsh_1 (
.sysclk(sysclk),
.step_a( reg_rfsh[0]),
.step_b(~reg_rfsh[0]),
.q(reg_rfsh[1])
);
counter reg_rfsh_2 (
.sysclk(sysclk),
.step_a( reg_rfsh[1]),
.step_b(~reg_rfsh[1]),
.q(reg_rfsh[2])
);
// Refresh counter stuff
wire [2:0] reg_rfsh; // Row Refresh counter
wire reg_rfsh_step; // SC&A12&CLK2
wire n0571;
wire n0574;
wire n0600;
wire n0610;
 
// Row selection mux
reg [2:0] row; // {N0646, N0617, N0582}
always @(posedge sysclk) begin
if (sc & a22)
row <= reg_rfsh;
if (sc_m22_clk2)
row <= data[3:1];
end
assign reg_rfsh_step = sc & a12 & clk2;
 
counter reg_rfsh_0 (
.sysclk(sysclk),
.step_a_in(clk1),
.step_b_in(reg_rfsh_step),
.step_a_out(n0571),
.step_b_out(n0574),
.q(reg_rfsh[0]),
.qn()
);
counter reg_rfsh_1 (
.sysclk(sysclk),
.step_a_in(n0571),
.step_b_in(n0574),
.step_a_out(n0600),
.step_b_out(n0610),
.q(reg_rfsh[1]),
.qn()
);
counter reg_rfsh_2 (
.sysclk(sysclk),
.step_a_in(n0600),
.step_b_in(n0610),
.step_a_out(),
.step_b_out(),
.q(reg_rfsh[2]),
.qn()
);
 
// Row Precharge/Read/Write stuff
wire precharge; // SC(A22+M22)CLK2
wire row_read; // (~POC)&CLK2&SC(A32+X12)
wire row_write; // CLK2&SC(A12+M12)
// Row selection mux
reg [2:0] row; // {N0646, N0617, N0582}
always @(posedge sysclk) begin
if (sc & a22)
row <= reg_rfsh;
if (sc_m22_clk2)
row <= data[3:1];
end
 
assign precharge = sc & (a22 | m22) & clk2;
assign row_read = ~(poc | ~(clk2 & sc & (a32 | x12)));
assign row_write = sc & (a12 | m12) & clk2;
 
// Row Precharge/Read/Write stuff
wire precharge; // SC(A22+M22)CLK2
wire row_read; // (~POC)&CLK2&SC(A32+X12)
wire row_write; // CLK2&SC(A12+M12)
 
// Column Read selection stuff
reg n0615;
always @(posedge sysclk) begin
if (clk2)
n0615 <= ~(x12 & (fin_fim_src_jin |
(opa0_n & inc_isz_add_sub_xch_ld)));
end
wire rrab0 = ~(dc | n0615 | clk2);
assign precharge = sc & (a22 | m22) & clk2;
assign row_read = ~(poc | ~(clk2 & sc & (a32 | x12)));
assign row_write = sc & (a12 | m12) & clk2;
 
reg n0592;
always @(posedge sysclk) begin
if (clk2)
n0592 <= ~((x22 & fin_fim_src_jin) |
(~opa0_n & x12 & inc_isz_add_sub_xch_ld));
end
wire rrab1 = ~(dc | n0592 | clk2);
 
// Column Read selection stuff
reg n0615;
always @(posedge sysclk) begin
if (clk2)
n0615 <= ~(x12 & (fin_fim_src_jin |
(opa0_n & inc_isz_add_sub_xch_ld)));
end
wire rrab0 = ~(dc | n0615 | clk2);
 
// Column Write selection stuff
wire n0564 = opa0_n & fin_fim_src_jin & dc;
wire n0568 = inc_isz_xch & x32 & sc;
wire wrab0 = clk2 & ((m12 & n0564) | ( opa0_n & n0568));
wire wrab1 = clk2 & ((m22 & n0564) | (~opa0_n & n0568));
reg n0592;
always @(posedge sysclk) begin
if (clk2)
n0592 <= ~((x22 & fin_fim_src_jin) |
(~opa0_n & x12 & inc_isz_add_sub_xch_ld));
end
wire rrab1 = ~(dc | n0592 | clk2);
 
 
// Force row 0 if FIN&X12
wire fin_x12 = (n0636 & opa0_n) & x12;
// Column Write selection stuff
wire n0564 = opa0_n & fin_fim_src_jin & dc;
wire n0568 = inc_isz_xch & x32 & sc;
wire wrab0 = clk2 & ((m12 & n0564) | ( opa0_n & n0568));
wire wrab1 = clk2 & ((m22 & n0564) | (~opa0_n & n0568));
 
// Manage the row data buffer
always @(posedge sysclk) begin
if (precharge)
dram_temp <= 8'b0;
if (row_read)
dram_temp <= dram_array[fin_x12 ? 3'b000 : row];
if (wrab0)
dram_temp[ 7:4] <= ~din_n;
if (wrab1)
dram_temp[ 3:0] <= ~din_n;
end
 
// Handle row writes
always @(posedge sysclk) begin
if (row_write)
dram_array[row] <= dram_temp;
end
// Force row 0 if FIN&X12
wire fin_x12 = (n0636 & opa0_n) & x12;
 
// Manage the data output mux
reg [3:0] dout;
always @* begin
(* PARALLEL_CASE *)
case (1'b1)
rrab0: dout = dram_temp[ 7:4];
rrab1: dout = dram_temp[ 3:0];
default: dout = 4'bzzzz;
endcase
end
assign data = dout;
// Data In latch
always @(posedge sysclk) begin
if (m12_m22_clk1_m11_m12)
din_n <= ~data;
end
// Manage the row data buffer
wire [7:0] row_data = dram_array[fin_x12 ? 3'b000 : row];
always @(posedge sysclk) begin
if (precharge)
dram_temp <= 8'b0;
 
if (row_read)
dram_temp <= row_data;
 
if (wrab0)
dram_temp[ 7:4] <= ~din_n;
if (wrab1)
dram_temp[ 3:0] <= ~din_n;
end
 
// Handle row writes
always @(posedge sysclk) begin
if (row_write)
dram_array[row] <= dram_temp;
end
 
// Manage the data output mux
reg [3:0] dout;
always @* begin
(* PARALLEL_CASE *)
case (1'b1)
rrab0: dout = dram_temp[ 7:4];
rrab1: dout = dram_temp[ 3:0];
default: dout = 4'bzzzz;
endcase
end
assign data = dout;
 
// Data In latch
always @(posedge sysclk) begin
if (m12_m22_clk1_m11_m12)
din_n <= ~data;
end
 
endmodule
/timing_io.v
1,18 → 1,18
`timescale 1ns / 1ps
`default_nettype none
////////////////////////////////////////////////////////////////////////
//
//
// 4004 Timing and I/O Interfaces
//
//
// This file is part of the MCS-4 project hosted at OpenCores:
// http://www.opencores.org/cores/mcs-4/
//
 
//
//
// Copyright © 2012, 2021 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.
//
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) 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.
20,140 → 20,132
////////////////////////////////////////////////////////////////////////
 
module timing_io(
input wire sysclk,
input wire clk1_pad,
input wire clk2_pad,
input wire poc_pad,
input wire ior,
// Timing and I/O Board Outputs
output wire clk1,
output wire clk2,
output wire a12,
output wire a22,
output wire a32,
output wire m12,
output wire m22,
output wire x12,
output wire x22,
output wire x32,
output wire gate,
output reg poc,
// External I/O Pad conditioning
inout wire [3:0] data,
inout wire [3:0] data_pad,
input wire test_pad,
output reg n0432,
output reg sync_pad,
input wire cmrom,
output wire cmrom_pad,
input wire cmram0,
output wire cmram0_pad,
input wire cmram1,
output wire cmram1_pad,
input wire cmram2,
output wire cmram2_pad,
input wire cmram3,
output wire cmram3_pad
input wire sysclk,
input wire clk1_pad,
input wire clk2_pad,
input wire poc_pad,
input wire ior,
 
// Timing and I/O Board Outputs
output wire clk1,
output wire clk2,
output wire a12,
output wire a22,
output wire a32,
output wire m12,
output wire m22,
output wire x12,
output wire x22,
output wire x32,
output wire gate,
output reg poc,
 
// External I/O Pad conditioning
inout wire [3:0] data,
inout wire [3:0] data_pad,
input wire test_pad,
output reg n0432,
output wire sync_pad,
input wire cmrom,
output wire cmrom_pad,
input wire cmram0,
output wire cmram0_pad,
input wire cmram1,
output wire cmram1_pad,
input wire cmram2,
output wire cmram2_pad,
input wire cmram3,
output wire cmram3_pad
);
 
// Simple pass-throughs
assign clk1 = clk1_pad;
assign clk2 = clk2_pad;
assign cmrom_pad = cmrom;
assign cmram0_pad = cmram0;
assign cmram1_pad = cmram1;
assign cmram2_pad = cmram2;
assign cmram3_pad = cmram3;
// Simple pass-throughs
assign clk1 = clk1_pad;
assign clk2 = clk2_pad;
assign cmrom_pad = cmrom;
assign cmram0_pad = cmram0;
assign cmram1_pad = cmram1;
assign cmram2_pad = cmram2;
assign cmram3_pad = cmram3;
 
 
// Generate the 8 execution phase indicators
reg [0:7] master = 8'h00;
reg [0:7] slave = 8'h00;
always @(posedge sysclk) begin
if (clk2)
master <= {~|slave[0:6], slave[0:6]};
else
sync_pad <= master[7];
// Generate the 8 execution phase indicators
timing_generator timing_generator (
.sysclk (sysclk),
.clk1 (clk1),
.clk2 (clk2),
.a12 (a12),
.a22 (a22),
.a32 (a32),
.m12 (m12),
.m22 (m22),
.x12 (x12),
.x22 (x22),
.x32 (x32),
.sync (sync_pad)
);
 
if (clk1)
slave <= master;
end
// Generate the DRAM Input Gate signal
// Properly called M12+M22+CLK1~(M11&M12)
wire n0279 = ~(a32 | m12);
reg n0278;
always @(posedge sysclk) begin
if (clk2)
n0278 <= n0279;
end
wire n0708 = ~((n0278 & clk1) | m12 | m22);
assign gate = ~n0708;
 
assign a12 = slave[0];
assign a22 = slave[1];
assign a32 = slave[2];
assign m12 = slave[3];
assign m22 = slave[4];
assign x12 = slave[5];
assign x22 = slave[6];
assign x32 = slave[7];
 
// Generate a clean POC signal
always @(posedge sysclk or posedge poc_pad) begin
if (poc_pad) poc <= 1'b1;
else if (a12) poc <= 1'b0;
end
 
// Generate the DRAM Input Gate signal
// Properly called M12+M22+CLK1~(M11&M12)
wire n0279 = ~(a32 | m12);
reg n0278;
always @(posedge sysclk) begin
if (clk2)
n0278 <= n0279;
end
wire n0708 = ~((n0278 & clk1) | m12 | m22);
assign gate = ~n0708;
// Generate a clean ~TEST signal (n0432)
always @(posedge sysclk) begin
n0432 <= ~test_pad;
end
 
// Generate a clean POC signal
always @(posedge sysclk) begin
if (poc_pad) poc <= 1'b1;
else if (a12) poc <= 1'b0;
else poc <= poc;
end
// Generate a clean ~TEST signal (n0432)
always @(posedge sysclk) begin
n0432 <= ~test_pad;
end
// Manage the Data I/O pads
reg L;
always @(posedge sysclk) begin
if (clk2)
L <= a32 | m12 | (x12 & (ior | poc));
end
 
// Manage the Data I/O pads
reg L;
always @(posedge sysclk) begin
if (clk2)
L <= a32 | m12 | (x12 & (ior | poc));
end
wire n0702 = ~clk2;
reg n0685;
reg n0699;
reg n0707;
always @(posedge sysclk) begin
if (clk1) begin
n0685 <= ~L;
n0707 <= L;
end
if (n0702)
n0699 <= ~L;
end
wire n0700 = n0707 | (L & n0702) | poc;
wire n0659 = (clk2 & n0685) | (clk1 & L);
wire n0676 = clk1 | n0685 | n0699;
 
wire n0702 = ~clk2;
reg n0685;
reg n0699;
reg n0707;
always @(posedge sysclk) begin
if (clk1) begin
n0685 <= ~L;
n0707 <= L;
end
if (n0702)
n0699 <= ~L;
end
wire n0700 = n0707 | (L & n0702) | poc;
wire n0659 = (clk2 & n0685) | (clk1 & L);
wire n0676 = clk1 | n0685 | n0699;
// Incoming data from the external pads
reg [3:0] data_in;
always @* begin
if (n0659) data_in = 4'b1111;
else if (n0676) data_in = 4'bzzzz;
else if (poc) data_in = 4'b0000;
else data_in = data_pad;
end
assign data = data_in;
// Incoming data from the external pads
reg [3:0] data_in;
always @* begin
if (n0659) data_in = 4'b1111;
else if (n0676) data_in = 4'bzzzz;
else if (poc) data_in = 4'b0000;
else data_in = data_pad;
end
assign data = data_in;
 
// Outgoing data to the external pads
reg [3:0] data_out;
always @(posedge sysclk) begin
if (n0702)
data_out <= data;
end
assign data_pad = poc ? 4'b0000 : (n0700 ? 4'bzzzz : data_out);
// Outgoing data to the external pads
reg [3:0] data_out;
always @(posedge sysclk) begin
if (n0702)
data_out <= data;
end
assign data_pad = poc ? 4'b0000 : (n0700 ? 4'bzzzz : data_out);
 
endmodule
/timing_io_tb.v
0,0 → 1,156
`timescale 1ns / 1ps
`default_nettype none
////////////////////////////////////////////////////////////////////////
//
// MCS-4 i4004 CPU Timing and I/O Interface testbench
//
// This testbench instantiates a timing_io module, and drives it
// with the basic 8-subcycle (A1, A2, A3, M1, M2, X1, X2, X3)
// instruction cycle to allow confirmation of the correct direction
// of transfer through the system bus interface.
//
// This file is part of the MCS-4 project hosted at OpenCores:
// http://www.opencores.org/cores/mcs-4/
//
// Copyright © 2021 by Reece Pollack <rrpollack@opencores.org>
//
// These materials are provided under the Creative Commons
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) 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 timing_io_tb;
 
localparam SYSCLK_TCY = 20; // sysclk period in nanoseconds
 
// Inputs
reg sysclk;
wire clk1_pad;
wire clk2_pad;
reg poc_pad = 1'b0;
reg test_pad = 1'b0;
reg ior = 1'b0;
reg cmrom = 1'b0;
reg cmram0 = 1'b0;
reg cmram1 = 1'b0;
reg cmram2 = 1'b0;
reg cmram3 = 1'b0;
 
// Outputs
wire clk1;
wire clk2;
wire a12;
wire a22;
wire a32;
wire m12;
wire m22;
wire x12;
wire x22;
wire x32;
wire sync;
wire gate;
wire poc;
wire n0432;
wire cmrom_pad;
wire cmram0_pad;
wire cmram1_pad;
wire cmram2_pad;
wire cmram3_pad;
 
// Bidirs
wire [3:0] data;
wire [3:0] data_pad;
 
// Instantiate the Unit Under Test (UUT)
timing_io uut (
.sysclk(sysclk),
.clk1_pad(clk1_pad),
.clk2_pad(clk2_pad),
.poc_pad(poc_pad),
.ior(ior),
.clk1(clk1),
.clk2(clk2),
.a12(a12),
.a22(a22),
.a32(a32),
.m12(m12),
.m22(m22),
.x12(x12),
.x22(x22),
.x32(x32),
.sync(sync),
.gate(gate),
.poc(poc),
.data(data),
.data_pad(data_pad),
.test_pad(test_pad),
.n0432(n0432),
.cmrom(cmrom),
.cmrom_pad(cmrom_pad),
.cmram0(cmram0),
.cmram0_pad(cmram0_pad),
.cmram1(cmram1),
.cmram1_pad(cmram1_pad),
.cmram2(cmram2),
.cmram2_pad(cmram2_pad),
.cmram3(cmram3),
.cmram3_pad(cmram3_pad)
);
 
// Instantiate the 2-phase clock generator
clockgen #(
.SYSCLK_TCY(SYSCLK_TCY)
) clockgen (
.sysclk(sysclk),
.clk1(clk1_pad),
.clk2(clk2_pad)
);
 
always begin
sysclk = 1'b0;
#(SYSCLK_TCY / 2);
sysclk = 1'b1;
#(SYSCLK_TCY / 2);
end
 
reg [3:0] data_out;
always @* begin
if (poc)
data_out = 4'bzzzz;
else begin
(* PARALLEL_CASE *)
case (1'b1)
a12: data_out = 4'b0001;
a22: data_out = 4'b0010;
a32: data_out = 4'b0011;
m12: data_out = 4'bzzzz;
m22: data_out = 4'bzzzz;
x12: data_out = 4'b0110;
x22: data_out = 4'b0111;
x32: data_out = 4'b1000;
default: data_out = 4'bxxxx;
endcase
end
end
assign data = data_out;
assign data_pad = 4'bzzzz;
 
initial begin
// Initialize Inputs
poc_pad = 1'b1;
 
// Wait 10000 ns for global reset to finish
#10000;
 
// Add stimulus here
@(posedge m12);
poc_pad = 1'b0;
end
 
endmodule
 

powered by: WebSVN 2.1.0

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