`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
`default_nettype none
|
`default_nettype none
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// 4004 Instruction Decoder
|
// 4004 Instruction Decoder
|
//
|
//
|
// This file is part of the MCS-4 project hosted at OpenCores:
|
// This file is part of the MCS-4 project hosted at OpenCores:
|
// http://www.opencores.org/cores/mcs-4/
|
// http://www.opencores.org/cores/mcs-4/
|
//
|
//
|
// Copyright © 2012, 2021 by Reece Pollack <rrpollack@opencores.org>
|
// Copyright © 2012, 2021 by Reece Pollack <rrpollack@opencores.org>
|
//
|
//
|
// These materials are provided under the Creative Commons
|
// These materials are provided under the Creative Commons
|
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) Public License.
|
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) Public License.
|
// They are NOT "public domain", and are protected by copyright.
|
// They are NOT "public domain", and are protected by copyright.
|
//
|
//
|
// This work based on materials provided by Intel Corporation and
|
// This work based on materials provided by Intel Corporation and
|
// others under the same license. See the file doc/License for
|
// others under the same license. See the file doc/License for
|
// details of this license.
|
// details of this license.
|
//
|
//
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
|
|
module instruction_decode(
|
module instruction_decode(
|
input wire sysclk, // 50 MHz FPGA clock
|
input wire sysclk, // 50 MHz FPGA clock
|
|
|
// Inputs from the Timing and I/O board
|
// Inputs from the Timing and I/O board
|
input wire clk1,
|
input wire clk1,
|
input wire clk2,
|
input wire clk2,
|
input wire a22,
|
input wire a22,
|
input wire m12,
|
input wire m12,
|
input wire m22,
|
input wire m22,
|
input wire x12,
|
input wire x12,
|
input wire x22,
|
input wire x22,
|
input wire x32,
|
input wire x32,
|
input wire poc, // Power-On Clear (reset)
|
input wire poc, // Power-On Clear (reset)
|
input wire n0432, // Conditioned TEST_PAD
|
input wire n0432, // Conditioned TEST_PAD
|
|
|
// Common 4-bit data bus
|
// Common 4-bit data bus
|
inout wire [3:0] data,
|
inout wire [3:0] data,
|
|
|
// These drive the Instruction Pointer (IP) board
|
// These drive the Instruction Pointer (IP) board
|
output wire jcn_isz, // JCN+ISZ
|
output wire jcn_isz, // JCN+ISZ
|
output wire jin_fin, // JIN+FIN
|
output wire jin_fin, // JIN+FIN
|
output wire jun_jms, // JUN+JMS
|
output wire jun_jms, // JUN+JMS
|
output wire cn_n, // ~CN
|
output wire cn_n, // ~CN
|
output wire bbl, // BBL
|
output wire bbl, // BBL
|
output wire jms, // JMS
|
output wire jms, // JMS
|
|
|
// Outputs to both the IP and SP boards
|
// Outputs to both the IP and SP boards
|
output wire sc, // SC (Single Cycle)
|
output wire sc, // SC (Single Cycle)
|
output wire dc, // DC (Double Cycle, ~SC)
|
output wire dc, // DC (Double Cycle, ~SC)
|
|
|
// Outputs to the Scratch Pad (SP) board
|
// Outputs to the Scratch Pad (SP) board
|
output wire n0636, // JIN+FIN
|
output wire n0636, // JIN+FIN
|
output wire sc_m22_clk2, // SC&M22&CLK2
|
output wire sc_m22_clk2, // SC&M22&CLK2
|
output wire fin_fim_src_jin, // FIN+FIM+SRC+JIN
|
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_add_sub_xch_ld, // INC+ISZ+ADD+SUB+XCH+LD
|
output wire inc_isz_xch, // INC+ISZ+XCH
|
output wire inc_isz_xch, // INC+ISZ+XCH
|
output wire opa0_n, // ~OPA.0
|
output wire opa0_n, // ~OPA.0
|
|
|
// Inputs from the ALU board (condition bits)
|
// Inputs from the ALU board (condition bits)
|
input wire acc_0, // ACC_0
|
input wire acc_0, // ACC_0
|
input wire add_0, // ADD_0
|
input wire add_0, // ADD_0
|
input wire cy_1, // CY_1
|
input wire cy_1, // CY_1
|
|
|
// Outputs to the Arithmetic Logic Unit (ALU) board
|
// Outputs to the Arithmetic Logic Unit (ALU) board
|
output wire cma,
|
output wire cma,
|
output wire write_acc_1,
|
output wire write_acc_1,
|
output wire write_carry_2,
|
output wire write_carry_2,
|
output wire read_acc_3,
|
output wire read_acc_3,
|
output wire add_group_4,
|
output wire add_group_4,
|
output wire inc_group_5,
|
output wire inc_group_5,
|
output wire sub_group_6,
|
output wire sub_group_6,
|
output wire ior,
|
output wire ior,
|
output wire iow,
|
output wire iow,
|
output wire ral,
|
output wire ral,
|
output wire rar,
|
output wire rar,
|
output wire ope_n,
|
output wire ope_n,
|
output wire daa,
|
output wire daa,
|
output wire dcl,
|
output wire dcl,
|
output wire inc_isz,
|
output wire inc_isz,
|
output wire kbp,
|
output wire kbp,
|
output wire o_ib,
|
output wire o_ib,
|
output wire tcs,
|
output wire tcs,
|
output wire xch,
|
output wire xch,
|
output wire n0342,
|
output wire n0342,
|
output wire x21_clk2,
|
output wire x21_clk2,
|
output wire x31_clk2,
|
output wire x31_clk2,
|
output wire com_n
|
output wire com_n
|
);
|
);
|
|
|
wire sc_m12_clk2 = sc & m12 & clk2;
|
wire sc_m12_clk2 = sc & m12 & clk2;
|
assign sc_m22_clk2 = sc & m22 & clk2;
|
assign sc_m22_clk2 = sc & m22 & clk2;
|
|
|
// Latch the first 4 bits of the opcode
|
// Latch the first 4 bits of the opcode
|
reg [3:0] opr = 4'b0000;
|
reg [3:0] opr = 4'b0000;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (sc_m12_clk2)
|
if (sc_m12_clk2)
|
opr <= data;
|
opr <= data;
|
end
|
end
|
|
|
// Latch the second 4 bits of the opcode
|
// Latch the second 4 bits of the opcode
|
reg [3:0] opa = 4'b0000;
|
reg [3:0] opa = 4'b0000;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (sc_m22_clk2)
|
if (sc_m22_clk2)
|
opa <= data;
|
opa <= data;
|
end
|
end
|
assign opa0_n = ~opa[0];
|
assign opa0_n = ~opa[0];
|
|
|
// Full OPR Decoding
|
// Full OPR Decoding
|
wire nop = (opr == 4'b0000);
|
wire nop = (opr == 4'b0000);
|
wire jcn = (opr == 4'b0001);
|
wire jcn = (opr == 4'b0001);
|
wire fim_src = (opr == 4'b0010);
|
wire fim_src = (opr == 4'b0010);
|
assign jin_fin = (opr == 4'b0011);
|
assign jin_fin = (opr == 4'b0011);
|
wire jun = (opr == 4'b0100);
|
wire jun = (opr == 4'b0100);
|
assign jms = (opr == 4'b0101);
|
assign jms = (opr == 4'b0101);
|
wire inc = (opr == 4'b0110);
|
wire inc = (opr == 4'b0110);
|
wire isz = (opr == 4'b0111);
|
wire isz = (opr == 4'b0111);
|
wire add = (opr == 4'b1000);
|
wire add = (opr == 4'b1000);
|
wire sub = (opr == 4'b1001);
|
wire sub = (opr == 4'b1001);
|
wire ld = (opr == 4'b1010);
|
wire ld = (opr == 4'b1010);
|
assign xch = (opr == 4'b1011);
|
assign xch = (opr == 4'b1011);
|
assign bbl = (opr == 4'b1100);
|
assign bbl = (opr == 4'b1100);
|
wire ldm = (opr == 4'b1101);
|
wire ldm = (opr == 4'b1101);
|
wire io = (opr == 4'b1110);
|
wire io = (opr == 4'b1110);
|
wire ope = (opr == 4'b1111);
|
wire ope = (opr == 4'b1111);
|
|
|
assign ope_n = ~ope;
|
assign ope_n = ~ope;
|
assign n0636 = jin_fin;
|
assign n0636 = jin_fin;
|
assign jcn_isz = jcn | isz;
|
assign jcn_isz = jcn | isz;
|
assign jun_jms = jun | jms;
|
assign jun_jms = jun | jms;
|
wire ldm_bbl = ldm | bbl;
|
wire ldm_bbl = ldm | bbl;
|
assign inc_isz = (inc | isz) & sc;
|
assign inc_isz = (inc | isz) & sc;
|
assign inc_isz_xch = inc | isz | xch;
|
assign inc_isz_xch = inc | isz | xch;
|
assign inc_isz_add_sub_xch_ld = inc | isz | add | sub | xch | ld;
|
assign inc_isz_add_sub_xch_ld = inc | isz | add | sub | xch | ld;
|
assign fin_fim_src_jin = fim_src | jin_fin;
|
assign fin_fim_src_jin = fim_src | jin_fin;
|
|
|
// OPE: OPA Decoding
|
// OPE: OPA Decoding
|
assign o_ib = ope & (opa[3] == 1'b0);
|
assign o_ib = ope & (opa[3] == 1'b0);
|
wire clb = ope & (opa == 4'b0000);
|
wire clb = ope & (opa == 4'b0000);
|
wire clc = ope & (opa == 4'b0001);
|
wire clc = ope & (opa == 4'b0001);
|
wire iac = ope & (opa == 4'b0010);
|
wire iac = ope & (opa == 4'b0010);
|
wire cmc = ope & (opa == 4'b0011);
|
wire cmc = ope & (opa == 4'b0011);
|
assign cma = ope & (opa == 4'b0100);
|
assign cma = ope & (opa == 4'b0100);
|
assign ral = ope & (opa == 4'b0101);
|
assign ral = ope & (opa == 4'b0101);
|
assign rar = ope & (opa == 4'b0110);
|
assign rar = ope & (opa == 4'b0110);
|
wire tcc = ope & (opa == 4'b0111);
|
wire tcc = ope & (opa == 4'b0111);
|
|
|
wire dac = ope & (opa == 4'b1000);
|
wire dac = ope & (opa == 4'b1000);
|
assign tcs = ope & (opa == 4'b1001);
|
assign tcs = ope & (opa == 4'b1001);
|
wire stc = ope & (opa == 4'b1010);
|
wire stc = ope & (opa == 4'b1010);
|
assign daa = ope & (opa == 4'b1011);
|
assign daa = ope & (opa == 4'b1011);
|
assign kbp = ope & (opa == 4'b1100);
|
assign kbp = ope & (opa == 4'b1100);
|
assign dcl = ope & (opa == 4'b1101);
|
assign dcl = ope & (opa == 4'b1101);
|
|
|
// IO: OPA Decoding
|
// IO: OPA Decoding
|
assign iow = io & (opa[3] == 1'b0);
|
assign iow = io & (opa[3] == 1'b0);
|
assign ior = io & (opa[3] == 1'b1);
|
assign ior = io & (opa[3] == 1'b1);
|
wire adm = io & (opa == 4'b1011);
|
wire adm = io & (opa == 4'b1011);
|
wire sbm = io & (opa == 4'b1000);
|
wire sbm = io & (opa == 4'b1000);
|
|
|
wire fin_fim = fin_fim_src_jin & ~opa[0];
|
wire fin_fim = fin_fim_src_jin & ~opa[0];
|
wire src = fim_src & opa[0];
|
wire src = fim_src & opa[0];
|
|
|
assign write_acc_1 = ~(kbp | tcs | daa | xch | poc | cma | tcc | dac | iac |
|
assign write_acc_1 = ~(kbp | tcs | daa | xch | poc | cma | tcc | dac | iac |
|
clb | ior | ld | sub | add | ldm_bbl);
|
clb | ior | ld | sub | add | ldm_bbl);
|
assign write_carry_2 = ~(tcs | poc | tcc | stc | cmc | dac | iac |
|
assign write_carry_2 = ~(tcs | poc | tcc | stc | cmc | dac | iac |
|
clc | clb | sbm | adm | sub | add);
|
clc | clb | sbm | adm | sub | add);
|
assign read_acc_3 = ~(daa | rar | ral | dac | iac | 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 add_group_4 = ~(tcs | tcc | adm | add);
|
assign inc_group_5 = ~(inc_isz | stc | iac);
|
assign inc_group_5 = ~(inc_isz | stc | iac);
|
assign sub_group_6 = ~(cmc | sbm | sub | m12);
|
assign sub_group_6 = ~(cmc | sbm | sub | m12);
|
|
|
// The Condition Flip-Flop
|
// The Condition Flip-Flop
|
reg n0397;
|
reg n0397;
|
wire n0486 = ~((opa[2] & acc_0) | (opa[1] & cy_1) | (opa[0] & n0432));
|
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 n0419 = ~((add_0 | ~isz) & (~jcn | ((n0486 | opa[3]) & (~n0486 | ~opa[3]))));
|
wire n0413 = ~((sc & n0419 & x32) | (~x32 & n0397));
|
wire n0413 = ~((sc & n0419 & x32) | (~x32 & n0397));
|
reg n0405;
|
reg n0405;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (clk2)
|
if (clk2)
|
n0405 <= n0413;
|
n0405 <= n0413;
|
end
|
end
|
always @(*) begin
|
always @(posedge sysclk) begin
|
if (clk1)
|
if (clk1)
|
n0397 <= ~n0405;
|
n0397 <= ~n0405;
|
end
|
end
|
assign cn_n = ~n0397;
|
assign cn_n = ~n0397;
|
|
|
// The Single-Cycle Flip-Flop
|
// The Single-Cycle Flip-Flop
|
reg n0343 = 1'b0;
|
reg n0343 = 1'b0;
|
wire n0368 = ~((sc & (fin_fim | jcn_isz | jun_jms) & x32) | (n0343 & ~x32));
|
wire n0368 = ~((sc & (fin_fim | jcn_isz | jun_jms) & x32) | (n0343 & ~x32));
|
reg n0362 = 1'b1;
|
reg n0362 = 1'b1;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (clk2)
|
if (clk2)
|
n0362 <= n0368;
|
n0362 <= n0368;
|
if (clk1)
|
if (clk1)
|
n0343 <= ~n0362;
|
n0343 <= ~n0362;
|
end
|
end
|
assign sc = ~n0343;
|
assign sc = ~n0343;
|
assign dc = ~sc;
|
assign dc = ~sc;
|
|
|
// Generate ~(X21&~CLK2)
|
// Generate ~(X21&~CLK2)
|
reg n0360;
|
reg n0360;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (clk2)
|
if (clk2)
|
n0360 <= ~x12;
|
n0360 <= ~x12;
|
end
|
end
|
wire n0337 = ~(n0360 | clk2);
|
wire n0337 = ~(n0360 | clk2);
|
assign x21_clk2 = ~n0337;
|
assign x21_clk2 = ~n0337;
|
|
|
// Generate ~(X31&~CLK2)
|
// Generate ~(X31&~CLK2)
|
reg n0380;
|
reg n0380;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (clk2)
|
if (clk2)
|
n0380 <= ~x22;
|
n0380 <= ~x22;
|
end
|
end
|
wire n0375 = ~(n0380 | clk2);
|
wire n0375 = ~(n0380 | clk2);
|
assign x31_clk2 = ~n0375;
|
assign x31_clk2 = ~n0375;
|
|
|
// Generate ~COM
|
// Generate ~COM
|
wire n0329 = io;
|
wire n0329 = io;
|
|
|
reg n0414, n0797;
|
reg n0414, n0797;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (clk2)
|
if (clk2)
|
n0414 <= a22;
|
n0414 <= a22;
|
else
|
else
|
n0797 <= n0414;
|
n0797 <= n0414;
|
end
|
end
|
|
|
reg n0433, n0801;
|
reg n0433, n0801;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (clk2)
|
if (clk2)
|
n0433 <= m12;
|
n0433 <= m12;
|
else
|
else
|
n0801 <= n0433;
|
n0801 <= n0433;
|
end
|
end
|
|
|
reg n0425, n0805;
|
reg n0425, n0805;
|
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
if (clk2)
|
if (clk2)
|
n0425 <= x12;
|
n0425 <= x12;
|
else
|
else
|
n0805 <= n0425;
|
n0805 <= n0425;
|
end
|
end
|
|
|
wire n0782 = ~((n0801 & n0329) | (src & n0805) | n0797);
|
wire n0782 = ~((n0801 & n0329) | (src & n0805) | n0797);
|
assign com_n = n0782;
|
assign com_n = n0782;
|
|
|
// Generate N0342
|
// Generate N0342
|
wire n0332 = ~(((n0329 | poc) & x22 & clk2) | (~(n0329 | poc) & n0337 & clk1));
|
wire n0332 = ~(((n0329 | poc) & x22 & clk2) | (~(n0329 | poc) & n0337 & clk1));
|
assign n0342 = n0332;
|
assign n0342 = n0332;
|
|
|
// Output OPA onto the data bus
|
// Output OPA onto the data bus
|
wire opa_ib = (ldm_bbl | jun_jms) & ~x21_clk2;
|
wire opa_ib = (ldm_bbl | jun_jms) & ~x21_clk2;
|
assign data = opa_ib ? opa : 4'bzzzz;
|
assign data = opa_ib ? opa : 4'bzzzz;
|
|
|
endmodule
|
endmodule
|
|
|