Using Turbo Pascal as hardware simulator.
How to define simple components:
We would like to make a NAND component with two inputs and
one output. The inputs must be event driven.
First we define an object which contains three pointers to
signals and two event buffers for the inputs. It also
contains a constructor which maps the signals, a procedure
which describes the behavior of the component and a
destructor to remove the component. The behavior procedure
must be visible to the simulator why we need to define the
component as an object of the process class.
USES thdl6;
TYPE
nand2 = OBJECT(process)
input1,input2,output1: signalptr;
c1,c2: eventbuf;
CONSTRUCTOR map(var in1, in2, out1: signal);
PROCEDURE behavior; VIRTUAL;
DESTRUCTOR nomap;
END;
The constructor maps the signals to the component. It saves
pointers to the inputs and outputs and it enables the
eventbuffers.
CONSTRUCTOR nand2.map(VAR in1,in2,out1: signal);
BEGIN
input1:=@in1; input2:=@in2; output1:=@out1; (* Map signals *)
c1.enable(self,in1); (* Call nand2.behavior when in1 changes *)
c2.enable(self,in2); (* Call nand2.behavior when in2 changes *)
END;
The behavior procedure describes the function of the component.
PROCEDURE nand2.behavior;
CONST
cnand: ARRAY[low..zz,low..zz] OF word =
((high,high,high,high),(high,low,xx,xx),(high,xx,xx,xx),(high,xx,xx,xx));
BEGIN
after(output1^,cnand[input1^.val,input2^.val],0); (* Delay 0 ns *)
END;
The destructor disables the eventbuffers:
DESTRUCTOR nand2.nomap;
BEGIN
c1.disable; c2.disable;
END;
Events:
Some simulators have a function which detects when a signal
changes. This facility is obtained by saving an event pointer
to the event signal. By using this event pointer we can make
a function which detects change on signals:
FUNCTION event_on(VAR s: signal): boolean;
BEGIN
event_on:=(event=addr(s));
END;
The simulator also contains a stopflag. Assigning it to a
nonzero value causes the simulation to stop. By examine the
stopflag it is posible to find the triggering condition.
How to define complex components:
It is easy to combine simple components to more complex
components. As an example we can build a RS-flipflop of two
nand gates:
TYPE
rsff = OBJECT
u1,u2: nand2;
PROCEDURE map(VAR r,s,q1,q2: signal);
PROCEDURE nomap;
END;
PROCEDURE rsff.map(VAR r,s,q1,q2: signal);
BEGIN
u1.map(r,q2,q1);
u2.map(s,q1,q2);
END;
PROCEDURE rsff.nomap;
BEGIN
u1.nomap; u2.nomap;
END;
Showing the results:
The probe6 unit contains a probe component which stores the
values on the signal assigned to it.
VAR
p: probe;
s1: signal;
BEGIN
p.map('S1',s1);
END;
Showing the probes is done by the probescreen procedure in
the thdlsim6 unit.
Example
This example ilustrates the use of the thdlsim6 unit:
VAR
rs: rsff;
p1,p2,p3,p4: probe;
r,s,q1,q2: signal;
BEGIN
(* Define circuit *)
rs.map(r,s,q1,q2);
p1.map('Reset',r);
p2.map('Set',s);
p3.map('Q1',q1);
p4.map('Q2',q2);
(* Test *)
after(r,high,0);
after(s,high,0);
step(10);
after(r,low,0);
step(10);
after(r,high,0);
step(10);
after(s,low,0);
step(10);
after(s,high,0);
step(10);
after(r,low,0);
step(10);
after(s,low,0);
step(10);
after(s,high,0);
step(10);
after(r,high,0);
step(10);
probescreen;
END.
You may try the examples above by downloading the Turbo
Hardware Description Language, THDL6V15.ZIP (41K).
Try running example.pas and counter.pas.
It is possible to combine THDL and multitasking:
Create the new task in the component constructor, switch the task in the
component behavior and close it in the component destructor.
Remember to switch the main task in all wait-loops.
MULTIV11.ZIP (33K).
[Back]
E-Mail address:
Guestbook.