1 |
6 |
rrpollack |
`timescale 1ns / 1ps
|
2 |
|
|
`default_nettype none
|
3 |
|
|
////////////////////////////////////////////////////////////////////////
|
4 |
|
|
//
|
5 |
|
|
// MCS-4 common clock generator sub-module
|
6 |
|
|
//
|
7 |
|
|
// This module implements a two-phase clock generator suitable
|
8 |
|
|
// for use with the MCS-4 emulation.
|
9 |
|
|
//
|
10 |
|
|
// This file is part of the MCS-4 project hosted at OpenCores:
|
11 |
|
|
// http://www.opencores.org/cores/mcs-4/
|
12 |
|
|
//
|
13 |
|
|
// Copyright © 2012, 2021 by Reece Pollack <rrpollack@opencores.org>
|
14 |
|
|
//
|
15 |
|
|
// These materials are provided under the Creative Commons
|
16 |
|
|
// "Attribution-NonCommercial-ShareAlike" (CC BY-NC-SA) Public License.
|
17 |
|
|
// They are NOT "public domain", and are protected by copyright.
|
18 |
|
|
//
|
19 |
|
|
// This work based on materials provided by Intel Corporation and
|
20 |
|
|
// others under the same license. See the file doc/License for
|
21 |
|
|
// details of this license.
|
22 |
|
|
//
|
23 |
|
|
////////////////////////////////////////////////////////////////////////
|
24 |
|
|
|
25 |
|
|
module clockgen #(
|
26 |
|
|
parameter SYSCLK_TCY = 20, // System clock cycle time in nanoseconds
|
27 |
|
|
parameter EXT_CLK_PROP = 0 // External clock propagation delay in sysclk cycles
|
28 |
|
|
) (
|
29 |
|
|
input wire sysclk,
|
30 |
|
|
output reg clk1,
|
31 |
|
|
output reg clk2,
|
32 |
|
|
output reg clk1_ext,
|
33 |
|
|
output reg clk2_ext
|
34 |
|
|
);
|
35 |
|
|
|
36 |
|
|
//
|
37 |
|
|
// Instruction phase timing in nanoseconds
|
38 |
|
|
//
|
39 |
|
|
// These are chosen to be nicely divisible by the clock
|
40 |
|
|
// period from any of these three systems while giving
|
41 |
|
|
// timing that would be compatible with a real i4004:
|
42 |
|
|
// * 50ns (20 MHz) -- P170-DH replacement board
|
43 |
|
|
// * 20ns (50 MHz) -- Digilent Spartan-3e Starter board
|
44 |
|
|
// * 10ns (100 MHz) -- Digilent Atlys Spartan-6 board
|
45 |
|
|
//
|
46 |
|
|
localparam TPW = 400; // Clock high pulse width
|
47 |
|
|
localparam TD1 = 400; // Delay from clk1 to clk2
|
48 |
|
|
localparam TD2 = 200; // Delay from clk2 to clk1
|
49 |
|
|
|
50 |
|
|
// MCS-4 instruction phase cycle time
|
51 |
|
|
localparam TCY = TD1 + TPW + TD2 + TPW;
|
52 |
|
|
|
53 |
|
|
// Calculate counter maximum value and width
|
54 |
|
|
localparam CMAX = (TCY / SYSCLK_TCY) - 1;
|
55 |
|
|
localparam W = clog2(CMAX);
|
56 |
|
|
|
57 |
|
|
//
|
58 |
|
|
// Instruction phase timing in sysclk cycles
|
59 |
|
|
//
|
60 |
|
|
localparam SYSCLK_TPW = TPW / SYSCLK_TCY;
|
61 |
|
|
localparam SYSCLK_TD1 = TD1 / SYSCLK_TCY;
|
62 |
|
|
localparam SYSCLK_TD2 = TD2 / SYSCLK_TCY;
|
63 |
|
|
|
64 |
|
|
// Divide the system clock to produce basic machine cycle
|
65 |
|
|
localparam [W-1:0] CLOCKDIV_MAX = CMAX;
|
66 |
|
|
reg [W-1:0] clockdiv = 1'd0;
|
67 |
|
|
always @(posedge sysclk) begin
|
68 |
|
|
clockdiv <= (clockdiv == CLOCKDIV_MAX) ? 1'd0 : (clockdiv + 1'd1);
|
69 |
|
|
end
|
70 |
|
|
|
71 |
|
|
// Set the timing of the internal 2-phase clocks
|
72 |
|
|
localparam [W-1:0] CLK1_START = SYSCLK_TD2 - 1,
|
73 |
|
|
CLK1_END = CLK1_START + SYSCLK_TPW,
|
74 |
|
|
CLK2_START = CLK1_END + SYSCLK_TD1,
|
75 |
|
|
CLK2_END = CLK2_START + SYSCLK_TPW;
|
76 |
|
|
|
77 |
|
|
always @(posedge sysclk) begin
|
78 |
|
|
case (clockdiv)
|
79 |
|
|
CLK1_START: clk1 <= 1'b1;
|
80 |
|
|
CLK1_END: clk1 <= 1'b0;
|
81 |
|
|
endcase
|
82 |
|
|
end
|
83 |
|
|
|
84 |
|
|
always @(posedge sysclk) begin
|
85 |
|
|
case (clockdiv)
|
86 |
|
|
CLK2_START: clk2 <= 1'b1;
|
87 |
|
|
CLK2_END: clk2 <= 1'b0;
|
88 |
|
|
endcase
|
89 |
|
|
end
|
90 |
|
|
|
91 |
|
|
//
|
92 |
|
|
// Set the timing of the external 2-phase clocks
|
93 |
|
|
//
|
94 |
|
|
// It takes ~70ns for the clocks to propagate from the FPGA through the
|
95 |
|
|
// clock driver chip to the reconstructed i4004 CPU circuitry. To match
|
96 |
|
|
// the timings, this module also provides advanced clock outputs.
|
97 |
|
|
//
|
98 |
|
|
localparam [W-1:0] CLK1_EXT_START = CLK1_START - EXT_CLK_PROP,
|
99 |
|
|
CLK1_EXT_END = CLK1_END - EXT_CLK_PROP,
|
100 |
|
|
CLK2_EXT_START = CLK2_START - EXT_CLK_PROP,
|
101 |
|
|
CLK2_EXT_END = CLK2_END - EXT_CLK_PROP;
|
102 |
|
|
|
103 |
|
|
always @(posedge sysclk) begin
|
104 |
|
|
case (clockdiv)
|
105 |
|
|
CLK1_EXT_START: clk1_ext <= 1'b1;
|
106 |
|
|
CLK1_EXT_END: clk1_ext <= 1'b0;
|
107 |
|
|
endcase
|
108 |
|
|
end
|
109 |
|
|
|
110 |
|
|
always @(posedge sysclk) begin
|
111 |
|
|
case (clockdiv)
|
112 |
|
|
CLK2_EXT_START: clk2_ext <= 1'b1;
|
113 |
|
|
CLK2_EXT_END: clk2_ext <= 1'b0;
|
114 |
|
|
endcase
|
115 |
|
|
end
|
116 |
|
|
|
117 |
|
|
`include "functions.vh"
|
118 |
|
|
|
119 |
|
|
endmodule
|