| Examples: Counter | |
|
This example demonstrates how to create behavioral model of a bit counter. To make this example generic we create a template module of arbitrary bit length, as shown in the picture. To download the files for this design click the links below
project file: counters.gbl
|
Start a new project, and call it counters. Add a new module to the project, call it counter. To make module a template, enter
size_t N in the Template Parameters property line.
Open Module View and click input port button. Holding down Ctrl key, place 3 input ports somewhere
in the design plane. Select each of the newly created ports, and change their properties: name (C, R, En) and type (bool).
Click on action button, and holding down Ctrl key place two event handlers: OnClock and OnReset.
Change the Trigger properties of OnClock and OnReset event handlers to |
|
|
Module counter |
|
GBL Designer created C++ code for this module with stubs for the event handlers. Now we need to enter the actual code for event handlers.
Open the Header tab or the Source tab depending on whether the Inline Functions property
of the module was set to yes or no.
The full code is shown below: //--------------------------------------------------------------------------------
// GBL Designer generated module
// Module: counter
// 2006-2008(c) GB RESEARCH, LLC. ALL RIGHTS RESERVED
//--------------------------------------------------------------------------------
#ifndef counter_H9757
#define counter_H9757
#include "gbl.h"
namespace counters {
export template< size_t N >
class counter : public GBL::Module
{
GBL::InPort< bool > C;
GBL::InPort< bool > R;
GBL::InPort< bool > En;
GBL::OutPort< GBL::BitSet<N> > Q;
public:
GBL_CONNECTOR4(C, R, En, Q)
counter(const std::string& name = "") : GBL::Module(name)
{
Handler(&counter::OnReset) << R;
Handler(&counter::OnClock) << C;
}
//<GBL_user>
private:
//----------------------------------------
void OnReset()
{
if(R)
Q = 0;
}
//----------------------------------------
void OnClock()
{
if(C && En)
++Q;
}
//</GBL_user>
};
} // namespace counters
#endif
|
|
|
Now we will create a test module for this design. Click on New Module, call it testbench, set Test
property to yes, change Trace File and Log File properties to the desired file names.
We will create two counters in this testbench: one 8-bit and one 16-bit, and look at the differences in their output signals using Xor module.
Add the following modules from BasicModules package: ClockGen, StaticCast, and Xor2. Add two counter modules from
the current project. Connect them as shown in the picture below, and set the properties of the modules and connectors correctly. We need
StaticCast modules because Xor2 module expects the same signal type on its inputs, so we convert outputs from counters to
|
|
| |
To trace the signals add TraceAll function, set its type to trace and add all signals you want to trace to its
Triggers property.
Add two more event handlers OnReset and ResetCounters. Make OnReset event handler sensitive to
GBL::eReset() event, and OnReset sensitive to reset signal. Make changes in the auto-generated code
(inside <GBL_user>...</GBL_user>), as shown below.
| |
//--------------------------------------------------------------------------------
// GBL Designer generated module
// Module: testbench
// 2006-2008(c) GB RESEARCH, LLC. ALL RIGHTS RESERVED
//--------------------------------------------------------------------------------
#ifndef testbench_H9757
#define testbench_H9757
#include "gbl.h"
#include "counters.h"
#include "BasicModules.h"
namespace counters {
class testbench : public GBL::Module
{
BasicModules::ClockGen i1;
counter< 3 > i2;
counter< 4 > i4;
BasicModules::Xor2< size_t > i3;
BasicModules::StaticCast< GBL::BitSet<3>, size_t > i5;
BasicModules::StaticCast< GBL::BitSet<4>, size_t > i6;
GBL::Signal< bool > clock;
GBL::ConstSignal< unsigned > period;
GBL::Signal< bool > enable;
GBL::Signal< bool > en_count;
GBL::Signal< bool > reset;
GBL::Signal< GBL::BitSet<3> > q3;
GBL::Signal< GBL::BitSet<4> > q4;
GBL::Signal< size_t > out1;
GBL::Signal< size_t > out2;
GBL::Signal< size_t > out_xor;
void TraceAll() { GBL::AddTrace(GetName() + ".clock", clock);
GBL::AddTrace(GetName() + ".en_count", en_count);
GBL::AddTrace(GetName() + ".enable", enable);
GBL::AddTrace(GetName() + ".out1", out1);
GBL::AddTrace(GetName() + ".out2", out2);
GBL::AddTrace(GetName() + ".out_xor", out_xor);
GBL::AddTrace(GetName() + ".q3", q3);
GBL::AddTrace(GetName() + ".q4", q4);
GBL::AddTrace(GetName() + ".reset", reset); }
public:
testbench(const std::string& name = "") : GBL::Module(name)
, i1(name + ".i1"), i2(name + ".i2"), i4(name + ".i4"), i3(name + ".i3")
, i5(name + ".i5"), i6(name + ".i6")
, period(4)
{
i1 ( period, enable, clock, GBL::N_C );
i2 ( clock, reset, en_count, q3 );
i4 ( clock, reset, en_count, q4 );
i3 ( out1, out2, out_xor );
i5 ( q3, out1 );
i6 ( q4, out2 );
Handler(&testbench::OnReset) << GBL::eReset();
Handler(&testbench::ResetCounters) << reset;
Handler(&testbench::TraceAll) << clock << en_count << enable << out1 << out2 << out_xor << q3 << q4 << reset;
}
//<GBL_user>
private:
//----------------------------------------
void OnReset()
{
enable = true;
en_count(GBL::Tick * 10) = true;
reset = true;
}
private:
//----------------------------------------
void ResetCounters()
{
if(reset)
reset(GBL::Tick) = false;
else
reset(GBL::Tick * 175) = true;
}
//----------------------------------------
public:
void Run()
{
GBL::Run(GBL::Tick * 400);
}
//</GBL_user>
};
} // namespace counters
#endif
| |
| You can run your design either by pressing the Run button or simply by pressing F9.
After the run is successfully completed, select the testbench module tab and press on Tracer button. The Tracer will open the traces from the last run. They should look like in the picture below.
| |