Digital simulation of the AGC electrical design can provide
detailed insight into how the computer functions. Aside from
satisfying simple personal interest, this is very valuable if you
wish to create a simulation of the AGC, in the manner of Virtual
AGC Project's Block
II AGC software simulator or Block I
AGC software simulator, or John Pultorak's Block
I
AGC hardware simulator, and want to have some way of
verifying that your creation works properly.
Realize, though, that the purpose of such simulations can only be
accurate examination or verification of AGC behavior, and they are
not practical substitutes for software (such as our yaAGC
program) designed and dedicated solely to running AGC
software. While you can use digital electrical
simulations to run AGC software, these simulations are very much
slower than real time. One day, as computer speeds continue
to advance, I expect that digital electrical simulations will be
much faster than now! But "faster than now" not now.
Recognize too that while simulation of the AGC or DSKY's analog
circuitry is also possible, that's not what I'm talking about
here. It is simulation of the digital circuitry — i.e., the
collection of logic gates in the AGC — that will be of interest.
Here's an executive summary of the workflow of the
digital-simulation process as I envisage it, and which will be
used throughout the remainder of this page:
# |
Workflow Step |
Comment |
---|---|---|
1 |
The electrical schematics — in our case, the original schematics of the AGC — are transcribed for use with modern schematic-capture software. | The schematic-capture software in question
is called KiCad EDA.
The transcribed schematic files are here. |
2 |
Netlists — i.e., files that list every
electrical connection in a given electrical schematic — are
created. |
KiCad itself creates the netlist
files. There are many different formats of netlist
files, all containing roughly the same information.
For our workflow, the specific format known in KiCad
as ORCAD PCB 2 is required. |
3 |
The netlists+schematics+initial conditions are translated into Verilog source code. | Verilog
is a high-level hardware description language. The
translation into Verilog source code is performed by a
Python 3 script called dumbVerilog.py that we
provide, assisted by another such script that's called dumbInitialization.py.
Note: These scripts are specialized for AGC digital circuits ~1970, and will not produce anything useful when applied to non-AGC circuitry or to analog circuitry. |
4 |
A "test bench" — i.e., a description in Verilog source code of the external inputs into the emulated circuitry vs time — is written. | There's a helpful Python 3 script, dumbTestbench.py,
which can automate a little of this for you, but the script
can't read your mind (yet!), so you still have to make some
choices for yourself. |
5 |
A model of the Erasable/Fixed Memory — i.e., the executable form of the AGC software that the emulated AGC circuitry is going to run — is converted into Verilog source code. | This
has already been done, at least for an incomplete
selection of the AGC software versions available to us. |
6 |
The Verilog source code for the AGC circuitry, the test bench, and the erasable/fixed memory are compiled together into an executable form. | Our workflow specifically uses the Icarus
Verilog (iVerilog) compiler for this. |
7 |
The executable Verilog program is then run
in an emulator. |
Our workflow uses the iVerilog emulator for this. Typically, this creates a "dump file" of whichever of the AGC's signals were considered to be interesting when the test bench was written. |
8 |
The output data dumped by the emulation is viewed as waveforms, similar to an oscilloscope, or else is post-processed in some other manner. | Our workflow uses a program called GTKWave
for this visualization of the results. |
Aside: Regarding the choice of software used in the workflow — i.e., the holy trinity KiCad, iVerilog, and GTKWave —, disagreement as to whether these are the optimal choices is always possible, and indeed likely if you happen to be a person with expertise in this particular area. The programs were chosen because they are free of charge (and indeed are open source, like the Virtual AGC Project itself) and available for Linux, Windows, and Mac OS. If you can make it work with the fancier tools a professional may have at their disposal, then by all means do so and let me know. I won't change an open-source workflow into a non-open-source workflow no matter how terrific an alternate tool may be, but at least I'll be interested to hear the news and can parrot it back to the general public!
Although multiple types of simulation are possible, we'll
concentrate just on these particular configurations:
The Virtual AGC Project's
Electro-Mechanical page.
Apollo-era AGC/DSKY electrical-schematic diagrams:
Open-source software:
Mike Stewart's similar transcription + simulation effort:
Aside: It should be noted that the AGC simulations described on this page were not based on Mike Stewart's pre-existing project, other than in spirit. Mike's simulation was a very important resource in the sense that cross comparisons of the results output by Mike's implementation with those output by mine provided a way to detect errors in both implementations that would not have been easily discoverable otherwise. And I can honestly tell you that it would never even have occurred to me to try this if Mike hadn't already done what he did! It's very much a case of "me too!" on my part. With that said, there are some pros and cons that work in both directions. My schematics closely match the original AGC schematics, so closely that you can overlay them, while Mike's schematics are intended to be — and I believe, are! — functionally identical to the original schematics, but impossible to verify vs the original schematics without considerable intellectual effort. Mike's version is more efficient in the sense that his simulation runs significantly faster than mine ... but you can't compare his side-by-side with the original schematics to verify correctness as you can with mine. Which approach you prefer is a matter of taste. What I'll be discussing here is my own approach rather than Mike's.
If you are using Virtual AGC via the Virtual AGC 64-bit Virtual
Machine, then everything is already set up for you.
If not, you'll want to install the following software on your
computer:
On Ubuntu Linux or Debian Linux, or derivatives of either of them
like Linux Mint, installation of the three programs mentioned
above is as simple as using the command "sudo
apt install kicad iverilog gtkwave
"; with Red
Hat or Fedora, I believe but don't guarantee that you could use "sudo yum install kicad iverilog gtkwave
";
on other Linux platforms, Solaris, or FreeBSD there's likely to be
some easy way, but you'll have to research it yourself.
On Windows, install KiCad from the installer found at the
hyperlink given above; watch for an option to add the KiCad
command-line program (kicad-cli.exe) to your PATH, and if there is
such an option then be sure to take advantage of it. There's
also an installer providing both
Icarus Verilog and GTKWave, and I'd suggest using it rather
than the individual hyperlinks given above. But note that
you'll find some additional setup instructions at the end of this
section.
On Mac OS, the least-painful approach would seem to be installing
homebrew, if
you don't already have it, and then using brew to install
the three programs rather than doing anything recommended at the
links above.
brew install --cask kicad
brew install icarus-verilog
brew install --HEAD
randomplum/gtkwave/gtkwave
Aside: While the foregoing advice about Mac OS results in an easy installation, there are things about the process that are unpleasant and perhaps warrant a few words of warning so that you won't be blind-sided when you encounter them.
- KiCad: Expect that the first usage after installation of any of the programs in the KiCad suite (including kicad-cli) will take a very long time to load. Load times of the KiCad applications after that first load take a much more reasonable amount of time.
- Icarus Verilog: A pleasure!
- GTKWave: At some point in the installation, it will abort and insist that you change ownership and permissions of a couple of folders before retrying the installation. Whether this is good to do as a security matter, I'm not qualified to say; moreover, the installation will take a long time, measured in hours rather than minutes because of the many, many prerequisites it has to build. Supposedly there is a second possibility, "brew install --cask gtkwave", but this command has been deprecated and (I believe) does not actually result in a functional gtkwave.
On all operating systems, download the
"schematics" branch of the Virtual AGC repository from
GitHub. There are many different ways you might do this,
depending on your computer platform and personal tastes, and I
wouldn't presume to dictate to you. For the sake of
discussion, however, I'll assume that you've done this by creating
a folder called "virtualagc-schematics" in your home
directory. For example, if you have the git program
installed on your computer, you could do it with a command like:
git clone --depth=1 -b schematics https://github.com/virtualagc/virtualagc.git virtualagc-schematics
Install Python 3 if not already installed, and then install the
Python module TatSu:
pip install tatsu
or perhaps
pip3 install tatsu
or perhaps
pip[3] install --break-system-packages tatsu
Aside: This "
--break-system-packages
" option doesn't imply that there's anything wrong with the TatSu package. Rather, it relates to a wonderful new trend of using Python environments which are "externally managed", in which no new Python modules whatever can be installed in the default environment without this "--break-system-packages
" command-line option. Isn't that a lovely development in user-friendliness? Easily-extensible systems that can't be extended? Ubuntu has it; Mac OS has it; soon, everybody may have it. Oh brave new world that has such stuff in it!
Within the virtualagc-schematics folder (or whatever you chose to
call it) you've just created, you'll find a folder called
"Scripts". Add the path to this Scripts folder into your
PATH environment variable. Depending on your particular
computer platform, the way of doing that varies. But the
following should usually work:
export PATH=$PATH:
PathToScripts
"
to the file ~/.bashrc using a text editor.export PATH=$PATH:
PathToScripts
"
to both of the files ~/.bashrc and ~/.zprofile using a
text editor.PathToScripts
to it.Even More Environment Variables for Windows:
It's likely that the changes to the PATH or PYTYONPATH won't affect any existing command line terminals which are already open, so you'll probably have to open a new command-line terminal to get the benefit of the change(s).
The Virtual AGC software repository already contains some
fully-worked out examples of digital simulations. The simplest
example is something called "testVerilog",
which is actually a small circuit block extracted from the AGC's
circuit module A1, the "scaler" module. Per the installation
instructions in the preceding section, all of the workflow steps
will be carried out in the folder
virtualagc-schematics/Schematics/testVerilog/. The results
given below were generated using KiCad v6, but any later version
should work as well, I hope. If you have KiCad v5 or
earlier, the transcribed schematics are no longer present in the
current repository, and the module schematics (testVerilog/*.sch)
would have to be retrieved from the older
repository version tagged as "KiCad-5"; but I have not
tested, and other files might need retrieval as well.
Aside: My intent is to walk you through the steps of the simulation workflow. If you haven't the fortitude for that — I understand and forgive you! —, there's a script (simulateModuleII or simulateModuleII.bat) which can do all of the work for you and just present you with the visualization of the simulation data created by the workflow. If you feel strong enough, then take the high road and skip past simulateBlockII to the main narrative instead of running the script.
But if you must, here's how to take the low road and use the script. For KiCad 7 or later, you can do the following (with \ in place of / in Windows):
cd virtualagc-schematics/Schematics/testVerilog
simulateModuleII A1It's slightly more involved for KiCad 6:
After the simulation completes, you can just jump down to workflow step #8 to see the simulation data displayed in a visualization program.cd virtualagc-schematics/Schematics/testVerilog
# Edit module.kicad_sch in eeschema and generate netlist file module.net,
# via eeschema's File/Export/Netlist/OrcadPCB2/Export Netlist.
# Then exit eeschema.
eeschema module.kicad_sch
simulateModuleII A1 module.net
Workflow Step #1: We've actually transcribed this circuit
for you already as a file called module.kicad_sch, so you needn't
do anything. Still, just to give you an idea how it works,
here's very high-level summary.
Start with the original Apollo Program schematic-diagram drawing
for module A1, which is drawing 2005259A, two sheets (click to
enlarge):
Don't be confused by the fact that the inputs of NOR gates in the
circuit are decorated with little triangles that make the gates
look like rocket ships. (Was it intentional, I
wonder?) They're just regular NOR gates in spite of
that. The numbered oval pads are the inputs from or outputs
to the AGC backplane into which the various AGC circuitry modules
plug. Perhaps I should also point out that the NOR gates
used in the AGC were open-drain gates, in which you can directly
tie together outputs from different gates (effectively AND'ing
them without any literal AND gate).
Aside: I won't cover here how to actually transcribe paper drawings of electrical schematics into KiCad schematic files. It's a complicated affair. Just any old transcription won't do. And honestly, you may not have to understand how to make transcriptions anyway, since I've already transcribed all of the pre-existing AGC schematics for you. Nevertheless, in the Appendix there's a list of some of the rules you'd have to follow to get schematic files that are usable for our simulation workflow. There are also common-sense rules that aren't covered in the Appendix, such as "you have to use wires for electrical interconnections rather than just lines". One rule not in the Appendix that I've personally followed in order to make verification of correctness of the transcriptions much simpler is that the transcribed schematics should appear to be so visually identical to the originals that you can overlay them with nothing perceptibly out of place. There's no technical necessity for that particular rule. Mike Stewart's transcriptions, for example, are designed entirely for functional correctness and have no visual resemblance whatever to the originals. On the other hand, Mike's transcriptions don't follow the rules laid out in the Appendix either, so certain steps in our simulation workflow (which post-date Mike's transcriptions) will fail. In case you're wondering how to transcribe a circuit so as to make it visually identical to the original, KiCad's schematic capture program, eeschema, allows you to use a JPG image as the backdrop of your schematic. Thus if you use the scanned images (as seen above) for your backdrops in eeschema, you can almost-trivially insure that all of your components and wires are in exactly the right places, which also helps to insure that the nets in the transcription are as they should be.
Transcriptions which follow the rules in the Appendix (and my
additional criteria) look like this:
Now as I mentioned, AGC module A1 is the "scaler" circuit.
If you want to read about it in some detail, you can look at section
4-5.3.4
of document ND-1021042, which covers the theory of operation
of this module. The module's purpose is to take a clock
signal called FS01/ (a 51.2 KHz square wave), which you can see
coming into the module from the AGC's backplane near the upper
left on the first sheet of the schematic, and to run it through a
sequence of identical circuit blocks that successively cut the
frequency of that signal in half, as follows, outputting those
slower clocks back to the AGC's backplane:
ND-1021042 has a handy
table listing all of the values for FS01 through FS17, but
for whatever reason doesn't deign to list FS18 through FS33 for
us.
To simplify things, the testVerilog example cuts this all down so
that just the first of the many divide-by-two circuit
blocks. The abridged circuit produces the output signal FS02
from input signal FS01/ and implements what's known to electrical
engineers as a "flip-flop". Here is an image of that
circuit:
Workflow Step 2: One way to create the netlist is to load
the schematic file into eeschema, then from the main menu
select File/Export/Netlist/OrcadPCB2/ExportNetlist and create a
file called module.net. For this discussion, I did this from
using KiCad v6, and got the resulting file
Workflow Step #3: Conversion to Verilog source code.
( { EESchema Netlist Version 1.1 created Tue 14 Jan 2025 05:51:55 AM CST }
( /00000000-0000-0000-0000-00005d281baf $noname J2 ConnectorA1-200
( 202 Net-(J2-Pad202) )
( 204 Net-(J2-Pad204) )
( 205 Net-(J2-Pad205) )
( 206 Net-(J2-Pad206) )
( 208 Net-(J2-Pad208) )
( 209 Net-(J2-Pad209) )
( 212 0VDCA )
( 222 +4VDC )
( 236 0VDCA )
( 250 +4VDC )
( 260 0VDCA )
)
( /00000000-0000-0000-0000-00005d281ba1 $noname U129 D3NOR-+4VDC-0VDCA-ABC-E_F
( 1 Net-(U127-Pad8) )
( 2 Net-(J2-Pad202) )
( 3 Net-(J2-Pad205) )
( 4 Net-(U127-Pad2) )
( 5 0VDCA )
( 6 0VDCA )
( 7 Net-(U127-Pad8) )
( 8 Net-(J2-Pad204) )
( 9 Net-(J2-Pad202) )
( 10 +4VDC )
)
( /00000000-0000-0000-0000-00005d281b3e $noname U126 D3NOR-+4VDC-0VDCA-A_B-E_F
( 6 0VDCA )
( 7 Net-(U126-Pad7) )
( 8 Net-(J2-Pad206) )
( 9 Net-(J2-Pad208) )
)
( /00000000-0000-0000-0000-00005d281b94 $noname U127 D3NOR-+4VDC-0VDCA-B_C-E_F
( 1 Net-(U126-Pad7) )
( 2 Net-(U127-Pad2) )
( 3 Net-(J2-Pad204) )
( 4 0VDCA )
( 5 0VDCA )
( 6 0VDCA )
( 7 Net-(U126-Pad7) )
( 8 Net-(U127-Pad8) )
( 9 Net-(J2-Pad204) )
( 10 +4VDC )
)
( /00000000-0000-0000-0000-00005d281b45 $noname U128 D3NOR-+4VDC-0VDCA-ABC-E_F
( 1 Net-(U127-Pad2) )
( 2 Net-(U127-Pad8) )
( 3 Net-(J2-Pad205) )
( 4 Net-(J2-Pad209) )
( 5 0VDCA )
( 6 0VDCA )
( 7 Net-(U126-Pad7) )
( 8 Net-(U127-Pad2) )
( 9 Net-(J2-Pad209) )
( 10 +4VDC )
)
)
*
dumbVerilog.py A1 module.net pins.txt 20 ../empty.init module.kicad_sch >module.vIn Windows, it would instead be
dumbInitialization.py <module.v
dumbVerilog.py A1 module.net pins.txt 20 A1.init module.kicad_sch >module.v
python -m dumbVerilog A1 module.net pins.txt 20 ..\empty.init module.kicad_sch >module.vWhile in Mac OS, it would be
python -m dumbInitialization <module.v
python -m dumbVerilog A1 module.net pins.txt 20 A1.init module.kicad_sch >module.v
python3 -m dumbVerilog A1 module.net pins.txt 20 ..\empty.init module.kicad_sch >module.vThe details of this procedure are covered in the technical Appendix. In brief, pins.txt is a file describing backplane connections that's appropriate for AGC models 2003200 or 2003993, though it doesn't really serve any purpose here since the backplane is used only to interconnect multiple logic modules, and uses only a portion of a single logic module. 20 is the propagation delay of the NOR gates in nanoseconds. As I mentioned before, in this example circuit the various NOR gates form a flip-flop. The file A1.init is used to specify whether the flip-flop is initially "on" or "off" at the start of the digital simulation. It is a file that you can create manually — though generally with considerable inconvenience —, and the purpose of the first two steps of the process above is to heuristically create a version of A1.init that will probably be "good enough". In point of fact, the repository supplies a module.init for you that could have been used in place of A1.init in the third step above, so that the first two steps above could have been skipped. The A1.init generated above might look like
python3 -m dumbInitialization <module.v
python3 -m dumbVerilog A1 module.net pins.txt 20 A1.init module.kicad_sch >module.v
and is telling us that initially, we can choose output signal U127-J to be HIGH (1), U127-K to be LOW (0), U129-J to be HIGH, and U129-K to be LOW. I say it "might" look like that, because there are other consisten initial conditions that could be generated instead, such as:# Auto-generated for module A1 by dumbInitialization.py.
U127 1 0
U129 1 0
The Verilog source code (module.v) that you get after the final step is below, depending on which initial conditions were generated. Even if you don't know Verilog, I think you can get some sense of what's what. The bulk of the file, namely the# Auto-generated for module A1 by dumbInitialization.py.
U126 0 1
U127 0 1
U128 1 0
assign
statements, define how
the internal signals and output signals change at each timestep of
the simulation. The rst
signal is not present in the schematic, and is simply always added
by dumbVerilog.py. It's what allows the initial
conditions of memory — in this case, the flip-flop — to be set up,
but is normally active only at the very beginning of the
simulation. Verilog doesn't allow signal names like "FS01/",
because the character "/" isn't legal for signal names, so the
translator has automatically changed "FS01/" to "FS01_".Workflow Step #4: Creation of a test bench. This is the point in a simulation workflow where you would have to decide how you want the input signals supplied to the circuit to vary over time, as well as which output signals from the circuit you want to log for later viewing or analysis. Those decisions together comprise what's called the "test bench". The test bench could be yet another Verilog source-code file, though it turns out to be more-convenient for it to be a pair of files, one to hold your personal choices, and another to include anything that can be figured out via automation.// Verilog module auto-generated for AGC module A1 by dumbVerilog.py
module A1 (
rst, FS01_, F02A, F02B, FS02, FS02A
);
input wire rst, FS01_;
output wire F02A, F02B, FS02, FS02A;
parameter GATE_DELAY = 20; // This default may be overridden at compile time.
initial $display("Gate delay (A1) will be %f ns.", GATE_DELAY);
// Gate A1-U129A
pullup(g38205);
assign #GATE_DELAY g38205 = rst ? 1'bz : ((0|g38203|FS01_|F02B) ? 1'b0 : 1'bz);
// Gate A1-U129B
pullup(F02B);
assign #GATE_DELAY F02B = rst ? 0 : ((0|g38205|FS02) ? 1'b0 : 1'bz);
// Gate A1-U126B
pullup(FS02A);
assign #GATE_DELAY FS02A = rst ? 0 : ((0|g38204) ? 1'b0 : 1'bz);
// Gate A1-U127A
pullup(g38204);
assign #GATE_DELAY g38204 = rst ? 1'bz : ((0|FS02|g38203) ? 1'b0 : 1'bz);
// Gate A1-U127B
pullup(FS02);
assign #GATE_DELAY FS02 = rst ? 0 : ((0|g38204|g38205) ? 1'b0 : 1'bz);
// Gate A1-U128A
pullup(g38203);
assign #GATE_DELAY g38203 = rst ? 0 : ((0|F02A|FS01_|g38205) ? 1'b0 : 1'bz);
// Gate A1-U128B
pullup(F02A);
assign #GATE_DELAY F02A = rst ? 0 : ((0|g38204|g38203) ? 1'b0 : 1'bz);
// End of NOR gates
endmodule
which gives you the following:# In Linux:
dumbTestbench.py <module.v >module_tb.v
# Or in Windows:
python -m dumbTestbench <module.v >module_tb.v
# Or in Mac OS:
python3 -m dumbTestbench <module.v >module_tb.v
You needn't worry (I hope!) about what any of that means. I'll just point out that it tells the emulator that the basic time scale of the simulation is 1 nanosecond (with a precision of 1 picosecond), the propagation delay through the NOR gates is by default 20 nanoseconds, and that the file tb.v, which is where the "personal choices" mentioned above are stored, is automatically imported.// Verilog testbench created by dumbTestbench.py
`timescale 1ns / 1ps
module agc;
parameter GATE_DELAY = 20;
`include "tb.v"
wire F02A, F02B, FS02, FS02A;
A1 iA1 (
rst, FS01_, F02A, F02B, FS02, FS02A
);
defparam iA1.GATE_DELAY = GATE_DELAY;
endmodule
The "// Include-file used by module_tb.py for automating testbench generation.
reg rst = 1;
initial begin
// Assumes compilation with the -fst option.
$dumpfile("module.fst");
$dumpvars(0, agc);
# 2000 rst = 0;
# 500000 $finish;
end
reg FS01_ = 0;
always #9765.625 FS01_ = !FS01_;
initial
$timeformat(-6, 0, " us", 10);
initial
$monitor("At time %t, rst=%d, FS01_=%d, F02B=%d, FS02=%d, FS02A=%d, FS02A=%d", $time, rst, FS01_, F02B, FS02, F02A, FS02A);
reg rst =1
" means
that the rst
signal is
going to be an input signal into the circuit we're testing, but here
within the test bench it's going to be a "register" that remembers
it's own settings, as opposed to a "wire" (which cannot remember
anything). Thus, we set rst
to 1 and it will stay that way until we say otherwise. A few
lines later we will see "# 2000 rst = 0
",
which means that 2000 nanoseconds (2 μs) after startup, the test
bench is going to reset the rst
signal to 0, and leave it there. The "#
500000 $finish
" that you will also see there says
that the simulation itself will actually end after 500 μs. The
intervening "$dumpfile
"
and "$dumpvars
" statements
say that an output log-file called testVerilog.lxt is going to be
opened, and that the values of all of the input and output variables
are going to be dumped into it on a cycle-by-cycle basis, for later
analysis. reg FS01_ = 0
" means
that FS01_
(FS01/) is
also an input to the circuit being tested, and that it starts out at
0. But "always #9765.625 FS01_ =
!FS01_
" means that FS01_
is going to be toggled every 9.765625 μs during the
simulation. Recall that FS01/ is a 51.2 KHz square wave in the
AGC, and therefore it toggles from low-to-high or high-to-low at a
rate of 102.4 KHz, or (surprise!) every 9.765625 μs.initial
"
statements at the very end describe the status messages which the
simulation is going to print out whilst running. These
messages are just informative, and have nothing to do with the data
being dumped out on the module.fst. You don't even need to
print out any status messages if you don't want to.I can't show you the contents of module.vvp — I bet you're relieved! —, since it's a binary file rather than a human-readable one.iverilog -o module.vvp module_tb.v module.v
I get messages something like this when I do that:vvp module.vvp -fst
Gate delay (A1) will be 20.000000 ns.Thus as promised,
FST info: dumpfile module.fst opened for output.
Gate delay (A1) will be 20.000000 ns.
FST info: dumpfile module.fst opened for output.
At time 0 us, rst=1, FS01_=0, F02B=x, FS02=x, FS02A=x, FS02A=x
At time 0 us, rst=1, FS01_=0, F02B=0, FS02=0, FS02A=0, FS02A=0
At time 2 us, rst=0, FS01_=0, F02B=0, FS02=0, FS02A=0, FS02A=0
At time 9 us, rst=0, FS01_=1, F02B=0, FS02=0, FS02A=0, FS02A=0
At time 9 us, rst=0, FS01_=1, F02B=1, FS02=0, FS02A=0, FS02A=0
At time 19 us, rst=0, FS01_=0, F02B=1, FS02=0, FS02A=0, FS02A=0
At time 19 us, rst=0, FS01_=0, F02B=1, FS02=1, FS02A=0, FS02A=1
At time 19 us, rst=0, FS01_=0, F02B=0, FS02=1, FS02A=0, FS02A=1
At time 29 us, rst=0, FS01_=1, F02B=0, FS02=1, FS02A=0, FS02A=1
At time 29 us, rst=0, FS01_=1, F02B=0, FS02=1, FS02A=1, FS02A=1
At time 39 us, rst=0, FS01_=0, F02B=0, FS02=1, FS02A=1, FS02A=1
At time 39 us, rst=0, FS01_=0, F02B=0, FS02=0, FS02A=1, FS02A=1
At time 39 us, rst=0, FS01_=0, F02B=0, FS02=0, FS02A=0, FS02A=0
At time 48 us, rst=0, FS01_=1, F02B=0, FS02=0, FS02A=0, FS02A=0
At time 48 us, rst=0, FS01_=1, F02B=1, FS02=0, FS02A=0, FS02A=0
...
At time 468 us, rst=0, FS01_=0, F02B=0, FS02=0, FS02A=0, FS02A=0
At time 478 us, rst=0, FS01_=1, F02B=0, FS02=0, FS02A=0, FS02A=0
At time 478 us, rst=0, FS01_=1, F02B=1, FS02=0, FS02A=0, FS02A=0
At time 488 us, rst=0, FS01_=0, F02B=1, FS02=0, FS02A=0, FS02A=0
At time 488 us, rst=0, FS01_=0, F02B=1, FS02=1, FS02A=0, FS02A=1
At time 488 us, rst=0, FS01_=0, F02B=0, FS02=1, FS02A=0, FS02A=1
At time 498 us, rst=0, FS01_=1, F02B=0, FS02=1, FS02A=0, FS02A=1
At time 498 us, rst=0, FS01_=1, F02B=0, FS02=1, FS02A=1, FS02A=1
FS01_
(FS01/) toggles about every 10 microseconds, while FS02
toggles about every 20
microseconds, though it's a bit of a pain to extract that conclusion
from the messages.Workflow Step #8: Visualization. Pull the dump-file created by running the simulation, namely module.fst, into the GTKWave visualization program,
In Mac OS, I think it would just be easier to open GTKWave from the desktop (rather than figuring out how to do it from a command line), and use its File menu to navigate to virtualagc-schematics/Schematics/testVerilog/module.fst.# In Linux or Windows:
gtkwave module.fst
Note: While the waveforms shown in the two graphs are the same, there is nevertheless a significant difference: Figure 4-121 purports to display the signal FS01, whereas our data visualization displays signal FS01/, which is inverted from FS01. Then too, the position of the final pulse of F02B doesn't match. One of us must be wrong! Which one could it be? Could it be ... me? Could it be ... them? The suspense is terrible! I hope it'll last. Check it out yourself.
Cheat sheet: I've made most of this line white-on-white, to make it harder to read accidentally. If you highlight this entire line, I expect it will be enlightening. To figure out who's wrong, it's relatively easy to work backward from the condition F02A HIGH to see what conditions it requires for the inputs of the various NOR gates, then to work backward to the NOR gates feeding those inputs, and so on. You'll quickly find that F02A HIGH implies that FS01/ is HIGH as well, which means that Figure 4-121 is wrong in asserting that F02A is HIGH at the same time as FS01 is HIGH. Identical reasoning applies to determining the conditions for F02B being HIGH, demonstrating that Figure 4-121 is incorrect about the positioning of the final pulse.
Generic AGC Model |
Block |
Mission |
Spacecraft |
Specific Dash Number |
---|---|---|---|---|
1003565 |
I |
AS-202 |
CM |
1003565-011 |
1003700 |
I |
Apollo 4 |
CM |
1003700-051 |
Apollo 6 |
CM |
1003700-071 |
||
2003100 |
II |
2TV-1 |
CM |
2003100-061 |
II |
LTA-8 |
LM |
2003100-071 |
|
2003200 |
II |
(None) |
CM |
2003200-031 |
(None) |
LM |
2003200-041 |
||
2003993 |
II |
Apollo 5 |
LM |
2003993-011 |
Apollo 7 | CM | 2003993-031 | ||
etc. |
Aside: Model 2003993, in differing specific dash numbers, was used for almost all missions, so I hope you'll forgive me for running out of steam at the end of the table and just covering all of the remaining missions with a bland "etc." rather than giving you 20+ more rows of model 2003993! The way to get the information for the missing entries is by drilling down into the GN&C mission hierarchy table. That is also the place to go in order to match a particular AGC model to a specific set of electrical schematics.
But there are really less choices than it appears at first
glance. There's a table in the Technical Appendix that lists all
of the logic modules appearing in the different AGC models, in
terms of the assocated schematic-diagram drawing numbers, and we
can summarize what we learn from that table as follows:
Or in other words, the only essentially-different cases are that
we can simulate either AGC model 1003700 (Block I) or model
2003993 (Block II).
The executive summary of all that is that as of right now, any simulating we'll be doing will be for AGC model 2003993.Aside: And of those two choices, only the simulation workflow for Block II has been debugged so far and can be considered mature enough to be "working", so the choice reduces to AGC model 2003993 ... which coincidentally, is the one that is likely most desired by people.
Regarding the test bench: Well, this is really no different
than what was discussed in the preceding section, except that we
need a test bench for the entire AGC, rather than test benches for
individual logic modules. I have created some test-bench
files that can be used as starting points. The are named
tb-2003993.v, tb-2003200.v, etc.
Aside: As in the case of simulating a single module, I've provided a script which can perform the entire sequence of steps needed to carry out the simulation, assuming that the choices described in the preceding section have been made. At the moment, the script only works for Linux or Mac OS, or something similar enough, but I haven't yet created the equivalent batch file for Windows. The script is run from the Schematics directory, and its calling sequence from the command line isWhat makes whole-AGC simulations trickier than single module simulations is that while the same basic workflow holds, some of the steps of the workflow are carried for each logic module comprising the circuit, while other steps combine the logic-module-specific large into single large files pertaining to the whole AGC, and yet other steps operate on those whole-AGC files.
wheresimulateAGC AGCMODEL SOFTWARE VERILOGPARMSAGCMODEL
defaults to "2003993",SOFTWARE
defaults to "Validation-hardware-simulation", andVERILOGPARMS
(a quoted list of command-line parameters for the Verilog compiler that alter values in the test bench) is empty (""). By default, every signal is logged by the simulation. To run the simulation while accepting all of the defaults, you could use the simple command.
This will perform the entire workflow and jump you right to the visualization of the data output by the simulation, thus avoiding the possibility of having to learn anything in the meantime.simulateAGC
Combining those ideas, what Step #5 of the workflow does is to
copy the appropriate file Schematics/roms/SOFTWAREVERSION.v to
Schematics/roms/rom.v, and then appends the holy trinity of RAM.v,
ROM.v, and BUFFER.v to the end of the BFVF.
Workflow Step #6 (compilation of the Verilog). The BFVF and the
testbench file generated by dumbTestbench.py in Step #4
above are the input files to the compiler.
But the full AGC has a lot
of signal nets in it — about 8500 of them —, so there's a lot more
flexibility in choosing which of those you want to look at in the
data visualization than there is in any single logic module.
In case it hasn't been clear already, any or all of the signals
logged when the simulation was performed can be displayed, in any
order, with or without various kinds of decorations. Which
ones of them to display, and how, is typically a matter on which
you'd consult the schematic diagrams and/or the
theory-of-operation documents a lot in order to figure out which
signals were helpful and which were merely clutter. What
I've done for pedagogical purposes in the screenshot below is to
select the signals corresponding to the upper portion of Figure
4-121 of the theory-of-operations document ND-1021042, of
which you may recall that in the preceding section I used only the
lower portion of that figure. One comforting feature of this
simulation is that when we saw this same data in the preceding
section, the test bench had supplied the input signal
FS01/ at the proper clock rate, whereas in our full-AGC simulation
here, signal FS01/ is instead generated by the upstream
portions of the circuitry. And yet the simulation still
generates an FS01/ signal at the same correct frequency as before.
There! That neatly explains, I think, why I'm right, and
everyone else is to blame for any apparent errors, and how my
simulation is beautiful and perfect. And they said it could
not be done! My next trick will to be to run for public
office of some kind. On the other hand, alternate
explanations concluding that I and my simulations are idiotic are
welcome too. Anything that advances the dialog! Let me
know if you come up with one.
Unmodified AGC software may not be 100% suitable for the purposes
of digitally simulating the AGC electronics, and may require some
modifications in order to be suitable. At this writing, the
only example of this is in the Validation
program, which is a small suite of test routines for the AGC CPU
that I wrote, based on the original documentation. However,
Validation is an interactive program, and dependence on a DSKY may
not be very desirable in the context of simulating the digital
electronics of the AGC. One approach to this problem would
be simply to clone the AGC program one wishes to run, and then
make whatever changes were desired directly to the cloned source
code.
Another approach is to embed directives in the original AGC
program that act like conditional compilation, so that sections of
the source code can be modified at assembly time without
maintaining two copies of the source code. The assembler (yaYUL)
supports this approach via a command-line switch, --simulation
, and embedded
directives -SIMULATION
or +SIMULATION
within end-of-line
comments in the AGC source code. Lines of AGC source
code without either of these embedded directives, or with those
directives embedded in full-line comments, are processed normally
by yaYUL whether or not the --simulation
command-line switch is present. However, if --simulation
is in effect, yaYUL
comments out any lines with an embedded -SIMULATION
directive. Conversely, if --simulation
is not in effect, yaYUL comments out any lines
with an embedded +SIMULATION
directive.
The AGC Validation program has such directives embedded in it,
and when assembled with --simulation
produces a version of the program more-suitable for simulating the
AGC electronics. This alternate version of Validation is
known as Validation-hardware-simulation, and thus is the program
run by default when simulating the AGC electronics.
More-sophisticated AGC test programs (such as Borealis) and the
original test programs (like Aurora and Sundial) are available as
well, but they have not received the treatment mentioned above.
This is too detailed a topic for me to give much helpful advice
about in a limited space. Plus, I consider it unlikely that
you'll find yourself needing to transcribe an AGC-related
schematic diagram. I will simply point out the following:
There are two methods.
Method 1: While viewing the top-level page of a schematic
diagram in eeschema, select File/Export/Netlist from the
main menu. In the "Export Netlist" window which pops up,
select the tab labeled "OrcadPCB2" and click the button labeled
"Export Netlist". In the "Save Netlist File" dialog which
appears, which should have pre-chosen the folder containing the
top-level schematic file itself, save the netlist as "module.net".
Method 2: For KiCad v.7 or later, the netlist can be
created from a command line without even running eeschema.
The command would be
kicad-cli sch export netlist --output module.net --format orcadpcb2 module.kicad_sch
Aside: To be completely honest, I'm no longer entirely sure how many of these rules the supplied tools actually depend upon, as opposed to these rules just being the ones obeyed by the original developers. Most of them are relied upon.To convert a single schematic to Verilog source code, the Python 3 script dumbVerilog.py is used:
dumbVerilog.py MODULE module.net pins.txt DELAY module.init module.kicad_sch [WIRETYPE] >module.vThe files called pins.txt and module.init are covered in the succeeding sections. The file pins.txt will be searched for if not found; it may be either in the current directory, the directory containing dumbVerilog.py itself (the usual case), or else specified with an explicit path. The parameters "module.net", "module.kicad_sch" (or just "module.sch" for KiCad v.5), and "module.v" are generally literal. As for the remaining command-line parameters:
MODULE
would be something like "A1", "A2",
etc. It's the designation of the specific logic module to
which the schematic belongs. The tool doesn't actually use
this for anything except as a unique identifier when multiple
logic modules are interconnected, so if you're working with a
circuit other than the official AGC modules, it doesn't really
matter what you use here, though I would recommend that it still
be of the form Ann.DELAY
, roughly speaking, is the
propagation delay of signals from the input of a NOR gate to its
output. The unit in which DELAY
is
expressed ultimately depends upon the time-scale that will be
set in the test bench, but that's conventionally 100 ns.
The nominal gate delay of AGC NOR gates was 20 ns, so that means
a reasonable DELAY
might be 0.2.WIRETYPE
is an optional parameter having
the value either "wire
" or "wand
".
It shouldn't matter which is chosen, so this parameter should
probably be omitted.Abstractly, the AGC circuitry consists of a number of "modules"
(each represented by an electrical schematic), plugged into a
"backplane". The backplane, again abstractly, consists of a
set of connectors whose pins are interconnected by wires.
However, there is no schematic diagram as such for the backplane,
so to incorporate the backplane into our simulation the
interconnections in the backplane must be specified in some other
form. That alternate form of description is the pins.txt
file, which is just a text file having a separate line in it for
each pin of each connector on the backplane.
Each line of the file has four fields, delimited by space
characters. Those fields are:
Aside: Technically, there are actually two separate backplanes, designated "A" and "B", into which the AGC modules Ann and Bnn respectively plug, with some interconnections between the two backplanes. The pins.txt file describes both, so we may as well think of it simply as one big backplane.
Regarding the module-to-backplane connectors, for the logic
modules that interest us for simulation purposes, each module had
a physical 284-pin connector consisting of 4 rows of 71 pins
each. (The 21st pin from either end of a row was missing, so
you could equally-well consider it physically to be a 276-pin
connector consisting of 4 rows of 69 pins each. But the pin
numbering pretends that the missing pins were present.) On
the other hand, on the electrical schematics for the logic
modules, each of the 71-pin rows was considered a separate
connector, and thus the schematics show 4 separate connectors
each, designated as J1, J2, J3, and J4.
Just to emphasize this point, in case the message was lost in the
details: In pins.txt each backplane connector for a logic
module has 284 pins, while on the logic module's electrical
schematics there are instead 4 connectors of 71 pins each.
In principle, a separate pins.txt file should be used for each
different AGC model. In practice, there's little difference
between AGC models 2003200 and 2003993, and so there is presently
a single pins.txt file used for those two models. As far as
other AGC models is concerned, there is presently no available
pins.txt for them.
Aside: Strictly speaking, this isn't quite true. The existing pins.txt was derived from Mike Stewart's digital simulation of the AGC. Mike's backplane pin data was derived in turn by a script that analyzed his Verilog files. Thus if we indeed wanted to generate a separate pins.txt file for each Block II AGC model we'd have an awkward chicken-and-egg problem, since dumbVerilog.py needs pins.txt before generating our Verilog files, whereas the only automated way of generating pins.txt does so after creating the Verilog files. On the other hand, for Block I AGC's I've created a similar file, pinsBlockI.txt, by processing Block I schematics (rather than Verilog files) using an AWK script, so perhaps the same technique could be used for Block II as well. However, the pinsBlockI.txt file is in a somewhat different format than pins.txt, and dumbVerilog.py isn't presently able to support that particular format. Although I don't recall for certain, I suppose this means that I had only done preliminary work on Block I AGC simulation, without having taken it to the point of the simulation actually functioning.
The only digital components
present in AGC logic-module schematics are dual triple-input
open-drain NOR gates (as in the figure to the left), which in
themselves are stateless; i.e., the output signal of a NOR gate is
directly determined by the current state of its input
signals. Or at least, the output is determined by the state
of the input signals after however long it takes the signals to
propagate through the gate, which is nominally 20
nanoseconds. Nevertheless, it is possible to interconnect
NOR gates in such a way that a block of NOR gates has an output
signal that does not necessarily depend on the current state of
the inputs. In other words, the block of NOR gates has
"memory". The most-common such circuit block in the AGC uses
several NOR gates to form what's known as a "flip-flop"; i.e., a
memory element capable of indefinitely storing a single bit
indefinitely. Or rather, of storing a bit until the power is
cycled, at which point the value of the bit is lost. The
testVerilog circuit used in examples above is such a
flip-flop.
This has an implication on the initial conditions for a digital
simulation, since we need to specify not only the levels of the
input signals to the circuit being simulated, but the initial
states of these implicit flip-flops as well. After
power-up is no issue, since if we know the states of the
flip-flops at power up, the simulation itself takes care of
computing their states at later times. But we first have to
have some way of knowing what the states were at power-up in order
to do that.
In the design of the physical AGC, almost no effort was
given to putting these implicit flip-flops into any given
state. (And in those cases where an effort had been made,
the mechanisms used would put the simulated flip-flops into a
known state too.) Rather, the developers just seemed to feel
that the flip-flops would generally settle down into some
stable state, and that happy thought proved to be adequate for
their purposes. For our purposes, namely digital
simulation, it's not enough! In simulation, it's
perfectly possible for a such a flip-flop to oscillate
indefinitely without ever settling down into some stable state,
which means that the Verilog emulator could get stuck in an
infinite loop or timeout while trying to compute the initial state
of the circuit. No good!
To specify the initial states of flip-flops, module.init allows
you to state the initial output signal of any or all of the NOR
gates. As we say in the figure above, a dual NOR-gate
component used in the AGC has two outputs, which are designated as
pin J for one of the NOR gates and K for the other of the NOR
gates. The way these are specified in module.init is that
there is a line in the file for each dual NOR component that you
want to specify, and that line has the format
Unnn OutputJ [ OutputK [ DelayJ [ DelayK ] ] ]where Unnn is the reference designator of the dual-NOR component and OutputJ and OutputK are the output signal levels (0 or 1, default 0) at pins J and K of the dual-NOR component. DelayJ and DelayK are the respective propagation delays for the two NOR gates, in units as described for the DELAY parameter of dumbVerilog.py as discussed earlier, which is also the default for any omitted DelayJ or DelayK.
U127 1 0
U129 1 0
In other words, U127's J output is 1 ("on") and K output is 0
("off"); and the same for U129. I've illustrated that in the
image to the right by coloring NOR-gate outputs specified
initially as 1 in green, and those
specified initially as 0 in red.
You don't need to specify the output for every NOR gate, and thus
the outputs of U126 and U128 are left unspecified. But if
you manually create the module.init file, it's entirely up to you
to determine which ones you want to specify; and since not all
possible combinations of signals are logically consistent, you
must insure the consistency, which can be quite tiresome if done
manually. Because of the way NOR gates work, specifying that
U129's OutputJ is 1 forces U127 OutputK, U128 OutputJ, and
U129 OutputK all to be 0. So if you specified any of those
latter outputs to be 1, you'd be creating an inconsistent set of
inital conditions.
dumbInitialization.py <TheVerilogSourceCode.v
where TheVerilogSourceCode.v
is
(surprise!) the Verilog source-code for which you wish to generate
some initialization information. There are actually two
basically-different scenarios in terms of acquiring the TheVerilogSourceCode.v
file:
Actually, these are just the two extreme cases of the unified
scenario "concatenate all of the module.v files comprising the
circuit in which you're interested". But there's a practical
difference between cases #1 and #2, in that if you decide you want
to simulate (say) AGC model 2003993, you probably don't actually know
without considerable research which particular logic modules
comprise it, thus increasing the difficulty level. Another
tricky aspect is that some logic-module drawing numbers are
repeated in an AGC. For example for the Block I AGC,
schematic 1006540A is used not only for module A1, but also for A2
through A16 as well, and thus there is no single "module.v"
associated with schematic 1006540A, but rather a module.v generated
for module A1, one generated for module A2, and so on.
The table below is a handy cheat sheet of the logic
modules vs schematic numbers relevant to various AGC models.
I suppose I should warn you that the revision levels shown for the
schematic drawings are simply the revisions we have,
rather than necessarily the ones originally used. AGC model
2003100, alas!, is highlighted mostly in red
to indicate schematics that haven't survived or to which we have
no access.
Logic Module |
Drawing
Number |
Module
Description |
|||||
---|---|---|---|---|---|---|---|
AGC 1003565 |
AGC 1003700 |
AGC 2003100 |
AGC 2003200 |
AGC 2003993 |
Block I |
Block II |
|
A1 |
1006540A | 1006540A |
2005059E |
2005259A |
2005259A |
Logic Flow, Bit | Scaler Module |
A2 |
1006540A | 1006540A |
2005060D |
2005260A |
2005260A |
Logic Flow, Bit | Scaler Module |
A3 |
1006540A | 1006540A |
2005051D |
2005251A |
2005251A |
Logic Flow, Bit | S Q Register and Decoding |
A4 |
1006540A | 1006540A |
2005062C |
2005262A |
2005262A |
Logic Flow, Bit | Stage Branch Decoding Module |
A5 |
1006540A | 1006540A |
2005061D |
2005261A |
2005261A |
Logic Flow, Bit | Cross Point Generator No. I |
A6 |
1006540A | 1006540A |
2005063F |
2005263A |
2005263A |
Logic Flow, Bit | Cross Point Generator II |
A7 |
1006540A | 1006540A |
2005052D |
2005252A |
2005252A |
Logic Flow, Bit | Service Gates |
A8 |
1006540A | 1006540A |
2005055D |
2005255- |
2005255- |
Logic Flow, Bit | 4 Bit Module |
A9 |
1006540A | 1006540A |
2005056C |
2005256A |
2005256A |
Logic Flow, Bit | 4 Bit Module |
A10 |
1006540A | 1006540A |
2005057E |
2005257A |
2005257A |
Logic Flow, Bit | 4 Bit Module |
A11 |
1006540A | 1006540A |
2005058D |
2005258A |
2005258A |
Logic Flow, Bit | 4 Bit Module |
A12 |
1006540A | 1006540A |
2005053F |
2005253A |
2005253A |
Logic Flow, Bit | Parity and S Register |
A13 |
1006540A | 1006540A |
2005069E |
2005269- |
2005269- |
Logic Flow, Bit | Alarms |
A14 |
1006540A | 1006540A |
2005064F |
2005264A |
2005264B |
Logic Flow, Bit | Memory Timing & Addressing |
A15 |
1006540A | 1006540A |
2005065D |
2005265A |
2005265A |
Logic Flow, Bit |
RUPT Service |
A16 |
1006540A | 1006540A |
2005066D |
2005266- |
2005266- |
Logic Flow, Bit |
INOUT I |
A17 |
1006543D |
1006543D |
2005067B |
2005267A |
2005267A |
Logic Flow "C" |
INOUT II |
A18 |
1006542- |
1006542- |
2005068C |
2005268A |
2005268A |
Logic Flow "B" |
INOUT III |
A19 |
2005070E |
2005270- |
2005270- |
INOUT IV |
|||
A20 |
2005054C |
2005254- |
2005254- |
Counter Cell I |
|||
A21 |
1006556A |
1006556A |
2005050J |
2005250- |
2005250- |
Logic Flow "S" |
Counter Cell II |
A22 |
1006553E |
1006553E |
2005071B |
2005271- |
2005271- |
Logic Flow "P" |
INOUT V |
A23 |
1006545- |
1006545- |
2005072C |
2005272A |
2005272A |
Logic Flow "E" |
INOUT VI |
A24 |
1006555A |
1006555A |
2005073A |
2005273A |
2005273A |
Logic Flow "R" |
INOUT VII |
A25 |
1006554- |
1006554- |
Logic Flow Q |
||||
A26 |
1006549B |
1006549B |
Logic Flow "J" |
||||
A27 |
1006544B |
1006544B |
Logic Flow D |
||||
A28 |
1006552A |
1006552A |
Logic Flow "N" |
||||
A29 |
1006559D |
1006559D |
Logic Flow "V" |
||||
A30 |
1006548- |
1006548- |
Logic Flow "H" |
||||
A31 |
1006548- | 1006548- |
Logic Flow "H" |
||||
A32 |
1006546A | 1006546A |
Logic Flow "F" |
||||
A33 |
1006547G |
1006547G |
Logic Flow "G" |
||||
A34 |
1006547G |
1006547G |
Logic Flow "G" |
||||
A35 |
1006541B |
1006541B |
Logic Flow "A" |
||||
A36 |
1006557D |
1006557D |
Logic Flow "T" |
||||
A37 |
1006550F |
1006550F |
Logic Flow "L" |
||||
A38 |
1006551- | 1006551- |
Logic Flow "M" |
||||
Fixed and Erasable Memory |
fixed_erasable_memory |
fixed_erasable_memory |
fixed_erasable_memory |
Because dumbInitialization.py expects to be dealing with
a collection of modules rather than necessarily an individual
module, it does not output any file specifically called
"module.init". Rather, it expects to be operating on an
entire AGC circuit, so it outputs separate initialization files
for each of the AGC's logic modules: A1.init, A2.init, and
so on. As you may recall, the testVerilog circuit is a
snippet from the circuit for logic module A1, so we'd have to
rename A1.init as module.init after running dumbInitializion.py.
Still, the operation seems pretty simple.
This supposed simplicity hides a nasty chicken-and-egg truth,
namely that we need to have module.init for dumbVerilog.py
to produce module.v, and we need module.v for dumbInitialization.py
to produce module.init. Catch 22!
Fortunately, this circle is not as vicious as it appears, since
all you really have to do is follow this 3-step procedure:
And indeed, this process works for us, giving us
# Auto-generated for module A1 by dumbInitialization.py.
U127 1 0
U129 1 0
dumbTestbench.py <TheVerilogSourceCode.v >TestBench.vThe Verilog source-code created by dumbTestbench.py is not quite the complete test bench, because dumbTestbench.py isn't aware of any personalized choices which needs to be made by you rather than by a computer. The file it creates, TestBench.v, itself imports another Verilog source-code file called "tb.v" to contain these personalized changes, and it's this file tb.v that you must create. The kinds of customizations covered by tb.v include such things as:
and here's the tb.v file it includes, as created by me:// Verilog testbench created by dumbTestbench.py
`timescale 1ns / 1ps
module agc;
parameter GATE_DELAY = 20;
`include "tb.v"
wire F02A, F02B, FS02, FS02A;
A1 iA1 (
rst, FS01_, F02A, F02B, FS02, FS02A
);
defparam iA1.GATE_DELAY = GATE_DELAY;
endmodule
Some of the features of this file were already explained earlier, at least somewhat, though the testbench discussed there was a somewhat earlier version than the one shown above.// Include-file used by dumbTestbench.py for automating testbench generation.
reg rst = 1;
initial begin
// Assume compilation with -fst switch.
$dumpfile("testVerilog.fst");
$dumpvars(0, agc);
# 2000 rst = 0;
# 500000 $finish;
end
reg FS01_ = 0;
always #4882.8125 FS01_ = !FS01_;
initial
$timeformat(-6, 0, " us", 10);
initial
$monitor("At time %t, rst=%d, FS01_=%d, F02B=%d, FS02=%d, FS02A=%d, FS02A=%d", $time, rst, FS01_, F02B, FS02, F02A, FS02A);
iverilog -o OUTPUT.vvp ListOfVerilogSourceCodeModulesIncludingTheTestBench
For a single logic module or other standalone schematic, that's
typically just
iverilog -o module.vvp module_tb.v module.v
For a collection of modules, such as an entire AGC, the basic command is still the same, but it's a bit more complicated since the list of Verilog source-code files is much larger and includes:
This is the easiest thing of all, since the command is simply
vvp module.vvp -fst
The -fst
option
perhaps requires some explanation. It selects the file
format to be used for logging simulation data. Because our
intention is to use gtkwave to visualize the logged data
(see the next section), it's necessary to choose a file format
supported both by vvp and by gtkwave, or at least
can be inter-converted. At the present writing (vvp
v11 and gtkwave v3.3.x), that would appear to be a
wide and confusing range of formats:
The bad news or good news (depending on your point of view) is
that gtkwave documentation makes it clear that all of the
formats I've italicized are scheduled to be deleted in gtkwave
v4, in addition to which GHW is a format used only for VHDL and
therefore is unlikely ever to be supported by Verilog
systems. That leaves only VCD and FST likely to be
common to iverilog and gtkwave in the
future. Of these two remaining formats, VCD (from gtkwave
documentation) "is the industry standard file format generated by
most Verilog simulators and is specified in IEEE-1364. This is the
slowest of the formats for the viewer to process and
requires the most memory. However, this format is ubiquitous, and
almost all tools support it". Whereas FST "is designed for
very fast sequential and random access". Which to choose is,
of course, a matter of personal preference.
It's probably best to review the gtkwave
documentation if you have questions, rather than relying on
anything I have to say about it. The command to do it is
simply
gtkwave NameOfTheSimulationLogFile
simulateBlockII A1 [NETLIST.net]
Of course, the parameter A1 is specific to the testVerilog example, and probably would be something else for you. The module.net parameter is optional, in the sense that simulateBlockII will try to generate a file called module.net itself if the parameter is missing, but NETLIST.net must already exist if the parameter is present. KiCad v7 or later is required if you're going to omit the NETLIST.net parameter.
Any of the command-line parameters can be omitted (from the end of the line) or replaced by "" (if in the middle of the line) to use default values for them.simulateAGC AGC_MODEL AGC_SOFTWARE "LIST_OF_OPTIONS"
AGC_MODEL
: One of 1003565, 1003700,
2003100, 2003200, or 2003993 (the default). However,
1003565 and 1003700 are in fact equivalent, as are 2003200 and
2003993. But at present, the simulation isn't yet expected
to work for Block I AGC's, and we do not yet have any of the
schematic diagrams for Block II model 2003100. So in
reality, the only presently-viable choice is essentially
2003993.AGC_SOFTWARE
: Any of the software
versions present in Schematics/roms/, such as Comanche055,
Luminary099, or Borealis. The default is
Validation-hardware-simulation."LIST_OF_OPTIONS"
: A quoted list of
space-separated options used to override hard-coded values in
the testbench files tb-AGC_MODEL
.v.
The default is "-DDUMP_ALL"
. Here are some
of the individual options which can appear in the list:-Pagc.GATE_DELAY=N
— Specify the
NOR-gate propagation delay in nanoseconds. Default is
20.-DSPOOF_SC
— Provides a Verilog
model for certain signals from the spacecraft. It is
primarily useful in attempting to match simulation results
versus simulation results from Mike Stewart's Verilog-based
simulation of the AGC.-DDUMP_ALL
— Dump all AGC
signals to the simulation's output dataset. Note:
The various DUMP_xxx
options are mutually
exclusive.-DUMP_DECODER
— Dump signals
pertaining to the CPU's instruction decoder to the
simulation's output dataset. -DUMP_HELPFUL
— Dump only those
signals I've designated as "helpful" to the simulation's
output dataset, which is the same as -DDUMP_DECODER
plus a few others.-DUMP_BACKPLANE
— Dump signals
from the AGC's backplane to the simulation's output dataset.cd Schematics
make
vvp 2003200.vvp -fst
gtkwave agc.fst