- A Logic Circuit Simulation Library in C++ |
The aim of this example is to implement a functional module for a positive edge triggered 4-bit counter. The block digram for the module is as shown below. It is a very simple module without a reset pin.
The code to implement and test the above module is as follows.
#include <iostream> #include <lcs/bus.h> #include <lcs/clock.h> #include <lcs/module.h> #include <lcs/simul.h> #include <lcs/changeMonitor.h> using namespace lcs; using namespace std; // Let the name of our counter module be Counter. // It has to be derived from the class lcs::Module. class Counter : public Module { public: // The constructor should take the output bus and the // clock input as the arguments. Counter(const Bus<4> &outbus, const InputBus<> &clk); // The virtual destructor. virtual ~Counter(); // Since our counter module will be triggered by the // positive edge of the clock, it has to override the // function lcs::Module::onPosEdge. virtual void onPosEdge(int portId); private: // Private members to store references to the output // bus and the clock input. Bus<4> outBus; InputBus<> clock; }; Counter::Counter(const Bus<4> &outbus, const InputBus<> &clk) : Module(), outBus(outbus), clock(clk) { // Register with the clock input to be notified of // a lcs::LINE_POS_EDGE event. clock.notify(this, LINE_POS_EDGE, 0); // Lock the outbus. Note that we are using the default // parameter of zero for the delay. See lcs::Bus::lock // for more information. outBus.lock(this); // Set the value on the output bus value to zero so that the // counter value is zero immediately after construction. Bus<4>::LineAccessor output = outBus.getLineAccessor(this); output = 0; } Counter::~Counter() { // De-register with the clock input so that it will stop // notifying line events to a non-existant module. clock.stopNotification(this, LINE_POS_EDGE, 0); // Unlock the output bus so as to make it available for // use by other modules. outBus.unLock(this); } void Counter::onPosEdge(int portId) { int val; outBus >> val; // We are making use of the over loaded operator>> // to write the bus contents into an integer variable. Bus<4>::LineAccessor output = outBus.getLineAccessor(this); if (val == 15) // If the bus holds a value of fifteen, then reset the value to zero. { output = 0; } else // If the bus holds a value other than 15, then increment it by 1. { output = val+1; } } int main(void) { Bus<4> output; Clock clk = Clock::getClock(); Counter counter(output, clk); ChangeMonitor<4> count(output, string("Count"), DUMP_ON); Simulation::setStopTime(4000); Simulation::start(); return 0; }
The output when the above program is compiled and run is as follows.
At time: 0, Count: 0000 At time: 100, Count: 0001 At time: 300, Count: 0010 At time: 500, Count: 0011 At time: 700, Count: 0100 At time: 900, Count: 0101 At time: 1100, Count: 0110 At time: 1300, Count: 0111 At time: 1500, Count: 1000 At time: 1700, Count: 1001 At time: 1900, Count: 1010 At time: 2100, Count: 1011 At time: 2300, Count: 1100 At time: 2500, Count: 1101 At time: 2700, Count: 1110 At time: 2900, Count: 1111 At time: 3100, Count: 0000 At time: 3300, Count: 0001 At time: 3500, Count: 0010 At time: 3700, Count: 0011 At time: 3900, Count: 0100
Below is the screenshot of the gtkwave plot of the generated VCD file.