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

Subversion Repositories mcs-4

[/] [mcs-4/] [trunk/] [rtl/] [verilog/] [i4004/] [instruction_decode.v] - Rev 6

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

`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" (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 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
 
    // Common 4-bit data bus
    inout  wire [3:0]   data,
 
    // 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)
 
    // 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
 
    // 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 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;
 
    // 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);
 
    // 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);
 
    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
 

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.