aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiodrag Milanović <mmicko@gmail.com>2022-02-21 17:57:44 +0100
committerGitHub <noreply@github.com>2022-02-21 17:57:44 +0100
commitd0b72e75d95828743b38184ee977c3c56f259b38 (patch)
treed4cdb702831ad471a26c4f96f70900f701166a05
parentd0f4d0b153572ddee5f19831f40b9c40eb480db0 (diff)
parentfd3f08753a2c577bb87ad332329213c58d4a9326 (diff)
downloadyosys-d0b72e75d95828743b38184ee977c3c56f259b38.tar.gz
yosys-d0b72e75d95828743b38184ee977c3c56f259b38.tar.bz2
yosys-d0b72e75d95828743b38184ee977c3c56f259b38.zip
Merge pull request #3203 from YosysHQ/micko/sim_ff
Simulation for various FF types
-rw-r--r--Makefile1
-rw-r--r--kernel/fstdata.cc141
-rw-r--r--kernel/fstdata.h22
-rw-r--r--passes/sat/sim.cc192
-rw-r--r--tests/sim/.gitignore6
-rw-r--r--tests/sim/adff.v7
-rw-r--r--tests/sim/adffe.v8
-rw-r--r--tests/sim/adlatch.v8
-rw-r--r--tests/sim/aldff.v7
-rw-r--r--tests/sim/aldffe.v8
-rw-r--r--tests/sim/dff.v4
-rw-r--r--tests/sim/dffe.v5
-rw-r--r--tests/sim/dffsr.v9
-rw-r--r--tests/sim/dlatch.v6
-rw-r--r--tests/sim/dlatchsr.v11
-rwxr-xr-xtests/sim/run-test.sh12
-rw-r--r--tests/sim/sdff.v7
-rw-r--r--tests/sim/sdffce.v8
-rw-r--r--tests/sim/sdffe.v8
-rw-r--r--tests/sim/sim_adff.ys6
-rw-r--r--tests/sim/sim_adffe.ys6
-rw-r--r--tests/sim/sim_adlatch.ys10
-rw-r--r--tests/sim/sim_aldff.ys6
-rw-r--r--tests/sim/sim_aldffe.ys6
-rw-r--r--tests/sim/sim_dff.ys6
-rw-r--r--tests/sim/sim_dffe.ys6
-rw-r--r--tests/sim/sim_dffsr.ys6
-rw-r--r--tests/sim/sim_dlatch.ys6
-rw-r--r--tests/sim/sim_dlatchsr.ys10
-rw-r--r--tests/sim/sim_sdff.ys6
-rw-r--r--tests/sim/sim_sdffce.ys6
-rw-r--r--tests/sim/sim_sdffe.ys6
-rwxr-xr-xtests/sim/tb/tb_adff.v40
-rwxr-xr-xtests/sim/tb/tb_adffe.v58
-rwxr-xr-xtests/sim/tb/tb_adlatch.v70
-rwxr-xr-xtests/sim/tb/tb_aldff.v73
-rwxr-xr-xtests/sim/tb/tb_aldffe.v75
-rwxr-xr-xtests/sim/tb/tb_dff.v47
-rwxr-xr-xtests/sim/tb/tb_dffe.v42
-rwxr-xr-xtests/sim/tb/tb_dffsr.v69
-rwxr-xr-xtests/sim/tb/tb_dlatch.v50
-rwxr-xr-xtests/sim/tb/tb_dlatchsr.v65
-rwxr-xr-xtests/sim/tb/tb_sdff.v48
-rwxr-xr-xtests/sim/tb/tb_sdffce.v79
-rwxr-xr-xtests/sim/tb/tb_sdffe.v70
45 files changed, 1170 insertions, 172 deletions
diff --git a/Makefile b/Makefile
index eb2213898..c10a33803 100644
--- a/Makefile
+++ b/Makefile
@@ -803,6 +803,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/various && bash run-test.sh
+cd tests/select && bash run-test.sh
+cd tests/sat && bash run-test.sh
+ +cd tests/sim && bash run-test.sh
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
+cd tests/svtypes && bash run-test.sh $(SEEDOPT)
+cd tests/proc && bash run-test.sh
diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc
index 330c4d189..1386a3300 100644
--- a/kernel/fstdata.cc
+++ b/kernel/fstdata.cc
@@ -109,8 +109,7 @@ void FstData::extractVarNames()
}
if (clean_name[0]=='\\')
clean_name = clean_name.substr(1);
- //log("adding %s.%s\n",var.scope.c_str(), clean_name.c_str());
-
+
name_to_handle[var.scope+"."+clean_name] = h->u.var.handle;
break;
}
@@ -118,48 +117,6 @@ void FstData::extractVarNames()
}
}
-static void reconstruct_edges_varlen(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen)
-{
- FstData *ptr = (FstData*)user_data;
- ptr->reconstruct_edges_callback(pnt_time, pnt_facidx, pnt_value, plen);
-}
-
-static void reconstruct_edges(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value)
-{
- FstData *ptr = (FstData*)user_data;
- uint32_t plen = (pnt_value) ? strlen((const char *)pnt_value) : 0;
- ptr->reconstruct_edges_callback(pnt_time, pnt_facidx, pnt_value, plen);
-}
-
-void FstData::reconstruct_edges_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */)
-{
- std::string val = std::string((const char *)pnt_value);
- std::string prev = last_data[pnt_facidx];
- if (pnt_time>=start_time) {
- if (prev!="1" && val=="1")
- edges.push_back(pnt_time);
- if (prev!="0" && val=="0")
- edges.push_back(pnt_time);
- }
- last_data[pnt_facidx] = val;
-}
-
-std::vector<uint64_t> FstData::getAllEdges(std::vector<fstHandle> &signal, uint64_t start, uint64_t end)
-{
- start_time = start;
- end_time = end;
- last_data.clear();
- for(auto &s : signal) {
- last_data[s] = "x";
- }
- edges.clear();
- fstReaderSetLimitTimeRange(ctx, start_time, end_time);
- fstReaderClrFacProcessMaskAll(ctx);
- for(const auto sig : signal)
- fstReaderSetFacProcessMask(ctx,sig);
- fstReaderIterBlocks2(ctx, reconstruct_edges, reconstruct_edges_varlen, this, nullptr);
- return edges;
-}
static void reconstruct_clb_varlen_attimes(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen)
{
@@ -176,77 +133,65 @@ static void reconstruct_clb_attimes(void *user_data, uint64_t pnt_time, fstHandl
void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */)
{
- if (sample_times_ndx >= sample_times.size()) return;
-
- uint64_t time = sample_times[sample_times_ndx];
+ if (pnt_time > end_time) return;
// if we are past the timestamp
- if (pnt_time > time) {
- for (auto const& c : last_data)
- {
- handle_to_data[c.first].push_back(std::make_pair(time,c.second));
- size_t index = handle_to_data[c.first].size() - 1;
- time_to_index[c.first][time] = index;
+ bool is_clock = false;
+ if (!all_samples) {
+ for(auto &s : clk_signals) {
+ if (s==pnt_facidx) {
+ is_clock=true;
+ break;
+ }
}
- sample_times_ndx++;
}
- // always update last_data
- last_data[pnt_facidx] = std::string((const char *)pnt_value);
-}
-void FstData::reconstructAtTimes(std::vector<fstHandle> &signal, std::vector<uint64_t> time)
-{
- handle_to_data.clear();
- time_to_index.clear();
- last_data.clear();
- sample_times_ndx = 0;
- sample_times = time;
- fstReaderSetUnlimitedTimeRange(ctx);
- fstReaderClrFacProcessMaskAll(ctx);
- for(const auto sig : signal)
- fstReaderSetFacProcessMask(ctx,sig);
- fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr);
+ if (pnt_time > past_time) {
+ past_data = last_data;
+ past_time = pnt_time;
+ }
- if (time_to_index[signal.back()].count(time.back())==0) {
- for (auto const& c : last_data)
- {
- handle_to_data[c.first].push_back(std::make_pair(time.back(),c.second));
- size_t index = handle_to_data[c.first].size() - 1;
- time_to_index[c.first][time.back()] = index;
+ if (pnt_time > last_time) {
+ if (all_samples) {
+ callback(last_time);
+ last_time = pnt_time;
+ } else {
+ if (is_clock) {
+ std::string val = std::string((const char *)pnt_value);
+ std::string prev = past_data[pnt_facidx];
+ if ((prev!="1" && val=="1") || (prev!="0" && val=="0")) {
+ callback(last_time);
+ last_time = pnt_time;
+ }
+ }
}
}
+ // always update last_data
+ last_data[pnt_facidx] = std::string((const char *)pnt_value);
}
-void FstData::reconstructAllAtTimes(std::vector<uint64_t> time)
+void FstData::reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t start, uint64_t end, CallbackFunction cb)
{
- handle_to_data.clear();
- time_to_index.clear();
+ clk_signals = signal;
+ callback = cb;
+ start_time = start;
+ end_time = end;
last_data.clear();
- sample_times_ndx = 0;
- sample_times = time;
+ last_time = start_time;
+ past_data.clear();
+ past_time = start_time;
+ all_samples = clk_signals.empty();
fstReaderSetUnlimitedTimeRange(ctx);
fstReaderSetFacProcessMaskAll(ctx);
fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr);
-
- if (time_to_index[1].count(time.back())==0) {
- for (auto const& c : last_data)
- {
- handle_to_data[c.first].push_back(std::make_pair(time.back(),c.second));
- size_t index = handle_to_data[c.first].size() - 1;
- time_to_index[c.first][time.back()] = index;
- }
- }
+ callback(last_time);
+ if (last_time!=end_time)
+ callback(end_time);
}
-std::string FstData::valueAt(fstHandle signal, uint64_t time)
+std::string FstData::valueOf(fstHandle signal)
{
- if (handle_to_data.find(signal) == handle_to_data.end())
+ if (past_data.find(signal) == past_data.end())
log_error("Signal id %d not found\n", (int)signal);
- auto &data = handle_to_data[signal];
- if (time_to_index[signal].count(time)!=0) {
- size_t index = time_to_index[signal][time];
- return data.at(index).second;
- } else {
- log_error("No data for signal %d at time %d\n", (int)signal, (int)time);
- }
+ return past_data[signal];
}
diff --git a/kernel/fstdata.h b/kernel/fstdata.h
index c069ff5e5..707d1b64e 100644
--- a/kernel/fstdata.h
+++ b/kernel/fstdata.h
@@ -25,6 +25,9 @@
YOSYS_NAMESPACE_BEGIN
+typedef std::function<void(uint64_t)> CallbackFunction;
+struct fst_end_of_data_exception { };
+
struct FstVar
{
fstHandle id;
@@ -45,14 +48,10 @@ class FstData
std::vector<FstVar>& getVars() { return vars; };
- void reconstruct_edges_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen);
- std::vector<uint64_t> getAllEdges(std::vector<fstHandle> &signal, uint64_t start_time, uint64_t end_time);
-
void reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen);
- void reconstructAtTimes(std::vector<fstHandle> &signal,std::vector<uint64_t> time);
- void reconstructAllAtTimes(std::vector<uint64_t> time);
+ void reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t start_time, uint64_t end_time, CallbackFunction cb);
- std::string valueAt(fstHandle signal, uint64_t time);
+ std::string valueOf(fstHandle signal);
fstHandle getHandle(std::string name);
double getTimescale() { return timescale; }
const char *getTimescaleString() { return timescale_str.c_str(); }
@@ -64,16 +63,17 @@ private:
std::vector<FstVar> vars;
std::map<fstHandle, FstVar> handle_to_var;
std::map<std::string, fstHandle> name_to_handle;
- std::map<fstHandle, std::vector<std::pair<uint64_t, std::string>>> handle_to_data;
std::map<fstHandle, std::string> last_data;
- std::map<fstHandle, std::map<uint64_t, size_t>> time_to_index;
- std::vector<uint64_t> sample_times;
- size_t sample_times_ndx;
+ uint64_t last_time;
+ std::map<fstHandle, std::string> past_data;
+ uint64_t past_time;
double timescale;
std::string timescale_str;
uint64_t start_time;
uint64_t end_time;
- std::vector<uint64_t> edges;
+ CallbackFunction callback;
+ std::vector<fstHandle> clk_signals;
+ bool all_samples;
};
YOSYS_NAMESPACE_END
diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc
index a7c109374..3b8114fa9 100644
--- a/passes/sat/sim.cc
+++ b/passes/sat/sim.cc
@@ -22,6 +22,7 @@
#include "kernel/celltypes.h"
#include "kernel/mem.h"
#include "kernel/fstdata.h"
+#include "kernel/ff.h"
#include <ctime>
@@ -113,8 +114,13 @@ struct SimInstance
struct ff_state_t
{
- State past_clock;
Const past_d;
+ Const past_ad;
+ State past_clk;
+ State past_ce;
+ State past_srst;
+
+ FfData data;
};
struct mem_state_t
@@ -209,10 +215,15 @@ struct SimInstance
}
}
- if (cell->type.in(ID($dff))) {
+ if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
+ FfData ff_data(nullptr, cell);
ff_state_t ff;
- ff.past_clock = State::Sx;
- ff.past_d = Const(State::Sx, cell->getParam(ID::WIDTH).as_int());
+ ff.past_d = Const(State::Sx, ff_data.width);
+ ff.past_ad = Const(State::Sx, ff_data.width);
+ ff.past_clk = State::Sx;
+ ff.past_ce = State::Sx;
+ ff.past_srst = State::Sx;
+ ff.data = ff_data;
ff_database[cell] = ff;
}
@@ -229,11 +240,10 @@ struct SimInstance
{
for (auto &it : ff_database)
{
- Cell *cell = it.first;
ff_state_t &ff = it.second;
zinit(ff.past_d);
- SigSpec qsig = cell->getPort(ID::Q);
+ SigSpec qsig = it.second.data.sig_q;
Const qdata = get_state(qsig);
zinit(qdata);
set_state(qsig, qdata);
@@ -466,21 +476,62 @@ struct SimInstance
for (auto &it : ff_database)
{
- Cell *cell = it.first;
ff_state_t &ff = it.second;
-
- if (cell->type.in(ID($dff)))
- {
- bool clkpol = cell->getParam(ID::CLK_POLARITY).as_bool();
- State current_clock = get_state(cell->getPort(ID::CLK))[0];
-
- if (clkpol ? (ff.past_clock == State::S1 || current_clock != State::S1) :
- (ff.past_clock == State::S0 || current_clock != State::S0))
- continue;
-
- if (set_state(cell->getPort(ID::Q), ff.past_d))
- did_something = true;
+ FfData &ff_data = ff.data;
+
+ Const current_q = get_state(ff.data.sig_q);
+
+ if (ff_data.has_clk) {
+ // flip-flops
+ State current_clk = get_state(ff_data.sig_clk)[0];
+ if (ff_data.pol_clk ? (ff.past_clk == State::S0 && current_clk != State::S0) :
+ (ff.past_clk == State::S1 && current_clk != State::S1)) {
+ bool ce = ff.past_ce == (ff_data.pol_ce ? State::S1 : State::S0);
+ // set if no ce, or ce is enabled
+ if (!ff_data.has_ce || (ff_data.has_ce && ce)) {
+ current_q = ff.past_d;
+ }
+ // override if sync reset
+ if ((ff_data.has_srst) && (ff.past_srst == (ff_data.pol_srst ? State::S1 : State::S0)) &&
+ ((!ff_data.ce_over_srst) || (ff_data.ce_over_srst && ce))) {
+ current_q = ff_data.val_srst;
+ }
+ }
+ }
+ // async load
+ if (ff_data.has_aload) {
+ State current_aload = get_state(ff_data.sig_aload)[0];
+ if (current_aload == (ff_data.pol_aload ? State::S1 : State::S0)) {
+ current_q = ff_data.has_clk ? ff.past_ad : get_state(ff.data.sig_ad);
+ }
+ }
+ // async reset
+ if (ff_data.has_arst) {
+ State current_arst = get_state(ff_data.sig_arst)[0];
+ if (current_arst == (ff_data.pol_arst ? State::S1 : State::S0)) {
+ current_q = ff_data.val_arst;
+ }
+ }
+ // handle set/reset
+ if (ff.data.has_sr) {
+ Const current_clr = get_state(ff.data.sig_clr);
+ Const current_set = get_state(ff.data.sig_set);
+
+ for(int i=0;i<ff.past_d.size();i++) {
+ if (current_clr[i] == (ff_data.pol_clr ? State::S1 : State::S0)) {
+ current_q[i] = State::S0;
+ }
+ else if (current_set[i] == (ff_data.pol_set ? State::S1 : State::S0)) {
+ current_q[i] = State::S1;
+ }
+ }
+ }
+ if (ff_data.has_gclk) {
+ // $ff
+ current_q = ff.past_d;
}
+ if (set_state(ff_data.sig_q, current_q))
+ did_something = true;
}
for (auto &it : mem_database)
@@ -538,13 +589,22 @@ struct SimInstance
{
for (auto &it : ff_database)
{
- Cell *cell = it.first;
ff_state_t &ff = it.second;
- if (cell->type.in(ID($dff))) {
- ff.past_clock = get_state(cell->getPort(ID::CLK))[0];
- ff.past_d = get_state(cell->getPort(ID::D));
- }
+ if (ff.data.has_aload)
+ ff.past_ad = get_state(ff.data.sig_ad);
+
+ if (ff.data.has_clk || ff.data.has_gclk)
+ ff.past_d = get_state(ff.data.sig_d);
+
+ if (ff.data.has_clk)
+ ff.past_clk = get_state(ff.data.sig_clk)[0];
+
+ if (ff.data.has_ce)
+ ff.past_ce = get_state(ff.data.sig_ce)[0];
+
+ if (ff.data.has_srst)
+ ff.past_srst = get_state(ff.data.sig_srst)[0];
}
for (auto &it : mem_database)
@@ -595,8 +655,7 @@ struct SimInstance
for (auto &it : ff_database)
{
- Cell *cell = it.first;
- SigSpec sig_q = cell->getPort(ID::Q);
+ SigSpec sig_q = it.second.data.sig_q;
Const initval = get_state(sig_q);
for (int i = 0; i < GetSize(sig_q); i++)
@@ -722,34 +781,32 @@ struct SimInstance
child.second->write_fst_step(f);
}
- void setInitState(uint64_t time)
+ void setInitState()
{
for (auto &it : ff_database)
{
- Cell *cell = it.first;
-
- SigSpec qsig = cell->getPort(ID::Q);
+ SigSpec qsig = it.second.data.sig_q;
if (qsig.is_wire()) {
IdString name = qsig.as_wire()->name;
fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(name));
if (id==0 && name.isPublic())
log_warning("Unable to found wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(name)).c_str());
if (id!=0) {
- Const fst_val = Const::from_string(shared->fst->valueAt(id, time));
+ Const fst_val = Const::from_string(shared->fst->valueOf(id));
set_state(qsig, fst_val);
}
}
}
for (auto child : children)
- child.second->setInitState(time);
+ child.second->setInitState();
}
- bool checkSignals(uint64_t time)
+ bool checkSignals()
{
bool retVal = false;
for(auto &item : fst_handles) {
if (item.second==0) continue; // Ignore signals not found
- Const fst_val = Const::from_string(shared->fst->valueAt(item.second, time));
+ Const fst_val = Const::from_string(shared->fst->valueOf(item.second));
Const sim_val = get_state(item.first);
if (sim_val.size()!=fst_val.size())
log_error("Signal '%s' size is different in gold and gate.\n", log_id(item.first));
@@ -779,7 +836,7 @@ struct SimInstance
}
}
for (auto child : children)
- retVal |= child.second->checkSignals(time);
+ retVal |= child.second->checkSignals();
return retVal;
}
};
@@ -998,8 +1055,6 @@ struct SimWorker : SimShared
log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
fst_clock.push_back(id);
}
- if (fst_clock.size()==0)
- log_error("No clock signals defined for input file\n");
SigMap sigmap(topmod);
std::map<Wire*,fstHandle> inputs;
@@ -1044,37 +1099,48 @@ struct SimWorker : SimShared
if (stopCount<startCount) {
log_error("Stop time is before start time\n");
}
- auto samples = fst->getAllEdges(fst_clock, startCount, stopCount);
-
- // Limit to number of cycles if provided
- if (cycles_set && ((size_t)(numcycles *2) < samples.size()))
- samples.erase(samples.begin() + (numcycles*2), samples.end());
-
- // Add setup time (start time)
- if (samples.empty() || samples.front()!=startCount)
- samples.insert(samples.begin(), startCount);
- fst->reconstructAllAtTimes(samples);
bool initial = true;
int cycle = 0;
- log("Co-simulation from %lu%s to %lu%s\n", (unsigned long)startCount, fst->getTimescaleString(), (unsigned long)stopCount, fst->getTimescaleString());
- for(auto &time : samples) {
- log("Co-simulating cycle %d [%lu%s].\n", cycle, (unsigned long)time, fst->getTimescaleString());
- for(auto &item : inputs) {
- std::string v = fst->valueAt(item.second, time);
- top->set_state(item.first, Const::from_string(v));
- }
- if (initial) {
- top->setInitState(time);
- initial = false;
- }
- update();
+ log("Co-simulation from %lu%s to %lu%s", (unsigned long)startCount, fst->getTimescaleString(), (unsigned long)stopCount, fst->getTimescaleString());
+ if (cycles_set)
+ log(" for %d clock cycle(s)",numcycles);
+ log("\n");
+ bool all_samples = fst_clock.empty();
+
+ try {
+ fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) {
+ log("Co-simulating %s %d [%lu%s].\n", (all_samples ? "sample" : "cycle"), cycle, (unsigned long)time, fst->getTimescaleString());
+ for(auto &item : inputs) {
+ std::string v = fst->valueOf(item.second);
+ top->set_state(item.first, Const::from_string(v));
+ }
- bool status = top->checkSignals(time);
- if (status)
- log_error("Signal difference\n");
- cycle++;
+ if (initial) {
+ top->setInitState();
+ write_output_header();
+ initial = false;
+ }
+ update();
+ write_output_step(5*cycle);
+
+ bool status = top->checkSignals();
+ if (status)
+ log_error("Signal difference\n");
+ cycle++;
+
+ // Limit to number of cycles if provided
+ if (cycles_set && cycle > numcycles *2)
+ throw fst_end_of_data_exception();
+ if (time==stopCount)
+ throw fst_end_of_data_exception();
+ });
+ } catch(fst_end_of_data_exception) {
+ // end of data detected
}
+ write_output_step(5*(cycle-1)+2);
+ write_output_end();
+
if (writeback) {
pool<Module*> wbmods;
top->writeback(wbmods);
diff --git a/tests/sim/.gitignore b/tests/sim/.gitignore
new file mode 100644
index 000000000..2c96b65f8
--- /dev/null
+++ b/tests/sim/.gitignore
@@ -0,0 +1,6 @@
+*.log
+/run-test.mk
++*_synth.v
++*_testbench
+*.out
+*.fst
diff --git a/tests/sim/adff.v b/tests/sim/adff.v
new file mode 100644
index 000000000..8c8fb0acf
--- /dev/null
+++ b/tests/sim/adff.v
@@ -0,0 +1,7 @@
+module adff( input d, clk, rst, output reg q );
+ always @( posedge clk, posedge rst )
+ if (rst)
+ q <= 0;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/adffe.v b/tests/sim/adffe.v
new file mode 100644
index 000000000..55c7d8d4e
--- /dev/null
+++ b/tests/sim/adffe.v
@@ -0,0 +1,8 @@
+module adffe( input d, clk, rst, en, output reg q );
+ always @( posedge clk, posedge rst )
+ if (rst)
+ q <= 0;
+ else
+ if (en)
+ q <= d;
+endmodule
diff --git a/tests/sim/adlatch.v b/tests/sim/adlatch.v
new file mode 100644
index 000000000..5e8f48e49
--- /dev/null
+++ b/tests/sim/adlatch.v
@@ -0,0 +1,8 @@
+module adlatch( input d, rst, en, output reg q );
+ always @* begin
+ if (rst)
+ q = 0;
+ else if (en)
+ q = d;
+ end
+endmodule
diff --git a/tests/sim/aldff.v b/tests/sim/aldff.v
new file mode 100644
index 000000000..eeb0f0673
--- /dev/null
+++ b/tests/sim/aldff.v
@@ -0,0 +1,7 @@
+module aldff( input [0:3] d, input [0:3] ad, input clk, aload, output reg [0:3] q );
+ always @( posedge clk, posedge aload)
+ if (aload)
+ q <= ad;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/aldffe.v b/tests/sim/aldffe.v
new file mode 100644
index 000000000..79c65afc4
--- /dev/null
+++ b/tests/sim/aldffe.v
@@ -0,0 +1,8 @@
+module aldffe( input [0:3] d, input [0:3] ad, input clk, aload, en, output reg [0:3] q );
+ always @( posedge clk, posedge aload)
+ if (aload)
+ q <= ad;
+ else
+ if (en)
+ q <= d;
+endmodule
diff --git a/tests/sim/dff.v b/tests/sim/dff.v
new file mode 100644
index 000000000..ce792b59a
--- /dev/null
+++ b/tests/sim/dff.v
@@ -0,0 +1,4 @@
+module dff( input d, clk, output reg q );
+ always @( posedge clk )
+ q <= d;
+endmodule
diff --git a/tests/sim/dffe.v b/tests/sim/dffe.v
new file mode 100644
index 000000000..853fcf66a
--- /dev/null
+++ b/tests/sim/dffe.v
@@ -0,0 +1,5 @@
+module dffe( input clk, en, d, output reg q );
+ always @( posedge clk )
+ if ( en )
+ q <= d;
+endmodule
diff --git a/tests/sim/dffsr.v b/tests/sim/dffsr.v
new file mode 100644
index 000000000..2158708f1
--- /dev/null
+++ b/tests/sim/dffsr.v
@@ -0,0 +1,9 @@
+module dffsr( input clk, d, clr, set, output reg q );
+ always @( posedge clk, posedge set, posedge clr)
+ if ( clr )
+ q <= 0;
+ else if (set)
+ q <= 1;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/dlatch.v b/tests/sim/dlatch.v
new file mode 100644
index 000000000..315b43216
--- /dev/null
+++ b/tests/sim/dlatch.v
@@ -0,0 +1,6 @@
+module dlatch( input d, en, output reg q );
+ always @* begin
+ if ( en )
+ q = d;
+ end
+endmodule
diff --git a/tests/sim/dlatchsr.v b/tests/sim/dlatchsr.v
new file mode 100644
index 000000000..1d13ac2ad
--- /dev/null
+++ b/tests/sim/dlatchsr.v
@@ -0,0 +1,11 @@
+module dlatchsr( input d, set, clr, en, output reg q );
+ always @* begin
+ if ( clr )
+ q = 0;
+ else if (set)
+ q = 1;
+ else
+ if (en)
+ q = d;
+ end
+endmodule
diff --git a/tests/sim/run-test.sh b/tests/sim/run-test.sh
new file mode 100755
index 000000000..d34d1f3c9
--- /dev/null
+++ b/tests/sim/run-test.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+set -eu
+source ../gen-tests-makefile.sh
+echo "Generate FST for sim models"
+find tb/* -name tb*.v | while read name; do
+ test_name=$(basename -s .v $name)
+ echo "Test $test_name"
+ verilog_name=${test_name:3}.v
+ iverilog -o tb/$test_name.out $name $verilog_name
+ ./tb/$test_name.out -fst
+done
+run_tests --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'"
diff --git a/tests/sim/sdff.v b/tests/sim/sdff.v
new file mode 100644
index 000000000..6b25516e1
--- /dev/null
+++ b/tests/sim/sdff.v
@@ -0,0 +1,7 @@
+module sdff( input d, clk, rst, output reg q );
+ always @( posedge clk)
+ if (rst)
+ q <= 0;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/sdffce.v b/tests/sim/sdffce.v
new file mode 100644
index 000000000..7d27d5741
--- /dev/null
+++ b/tests/sim/sdffce.v
@@ -0,0 +1,8 @@
+module sdffce( input d, clk, rst, en, output reg q );
+ always @( posedge clk)
+ if(en)
+ if (rst)
+ q <= 0;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/sdffe.v b/tests/sim/sdffe.v
new file mode 100644
index 000000000..0a96693e1
--- /dev/null
+++ b/tests/sim/sdffe.v
@@ -0,0 +1,8 @@
+module sdffe( input d, clk, rst, en, output reg q );
+ always @( posedge clk)
+ if (rst)
+ q <= 0;
+ else
+ if (en)
+ q <= d;
+endmodule
diff --git a/tests/sim/sim_adff.ys b/tests/sim/sim_adff.ys
new file mode 100644
index 000000000..6efd804a9
--- /dev/null
+++ b/tests/sim/sim_adff.ys
@@ -0,0 +1,6 @@
+read_verilog adff.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$adff
+sim -clock clk -r tb_adff.fst -scope tb_adff.uut -sim-cmp adff
diff --git a/tests/sim/sim_adffe.ys b/tests/sim/sim_adffe.ys
new file mode 100644
index 000000000..47a51ebce
--- /dev/null
+++ b/tests/sim/sim_adffe.ys
@@ -0,0 +1,6 @@
+read_verilog adffe.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$adffe
+sim -clock clk -r tb_adffe.fst -scope tb_adffe.uut -sim-cmp adffe
diff --git a/tests/sim/sim_adlatch.ys b/tests/sim/sim_adlatch.ys
new file mode 100644
index 000000000..eece7dc0d
--- /dev/null
+++ b/tests/sim/sim_adlatch.ys
@@ -0,0 +1,10 @@
+read_verilog -icells <<EOT
+module adlatch(input d, rst, en, output reg q);
+$adlatch #(.EN_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(1'b0), .WIDTH(1)) uut (.EN(en), .ARST(rst), .D(d), .Q(q));
+endmodule
+EOT
+proc
+opt_dff
+stat
+select -assert-count 1 t:$adlatch
+sim -r tb_adlatch.fst -scope tb_adlatch.uut -sim-cmp adlatch
diff --git a/tests/sim/sim_aldff.ys b/tests/sim/sim_aldff.ys
new file mode 100644
index 000000000..9c8b3bdfc
--- /dev/null
+++ b/tests/sim/sim_aldff.ys
@@ -0,0 +1,6 @@
+read_verilog aldff.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$aldff
+sim -clock clk -r tb_aldff.fst -scope tb_aldff.uut -sim-cmp aldff
diff --git a/tests/sim/sim_aldffe.ys b/tests/sim/sim_aldffe.ys
new file mode 100644
index 000000000..b191cf877
--- /dev/null
+++ b/tests/sim/sim_aldffe.ys
@@ -0,0 +1,6 @@
+read_verilog aldffe.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$aldffe
+sim -clock clk -r tb_aldffe.fst -scope tb_aldffe.uut -sim-cmp aldffe
diff --git a/tests/sim/sim_dff.ys b/tests/sim/sim_dff.ys
new file mode 100644
index 000000000..12f402443
--- /dev/null
+++ b/tests/sim/sim_dff.ys
@@ -0,0 +1,6 @@
+read_verilog dff.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dff
+sim -clock clk -r tb_dff.fst -scope tb_dff.uut -sim-cmp dff
diff --git a/tests/sim/sim_dffe.ys b/tests/sim/sim_dffe.ys
new file mode 100644
index 000000000..f9b9e4767
--- /dev/null
+++ b/tests/sim/sim_dffe.ys
@@ -0,0 +1,6 @@
+read_verilog dffe.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dffe
+sim -clock clk -r tb_dffe.fst -scope tb_dffe.uut -sim-cmp dffe
diff --git a/tests/sim/sim_dffsr.ys b/tests/sim/sim_dffsr.ys
new file mode 100644
index 000000000..e99ee860d
--- /dev/null
+++ b/tests/sim/sim_dffsr.ys
@@ -0,0 +1,6 @@
+read_verilog dffsr.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dffsr
+sim -clock clk -r tb_dffsr.fst -scope tb_dffsr.uut -sim-cmp dffsr
diff --git a/tests/sim/sim_dlatch.ys b/tests/sim/sim_dlatch.ys
new file mode 100644
index 000000000..79e4601e3
--- /dev/null
+++ b/tests/sim/sim_dlatch.ys
@@ -0,0 +1,6 @@
+read_verilog dlatch.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dlatch
+sim -r tb_dlatch.fst -scope tb_dlatch.uut -sim-cmp dlatch
diff --git a/tests/sim/sim_dlatchsr.ys b/tests/sim/sim_dlatchsr.ys
new file mode 100644
index 000000000..c83051c8b
--- /dev/null
+++ b/tests/sim/sim_dlatchsr.ys
@@ -0,0 +1,10 @@
+read_verilog -icells <<EOT
+module dlatchsr(input d, set, clr, en, output reg q);
+$dlatchsr #(.EN_POLARITY(1'b1), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b1), .WIDTH(1)) uut (.EN(en), .SET(set), .CLR(clr), .D(d), .Q(q));
+endmodule
+EOT
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dlatchsr
+sim -r tb_dlatchsr.fst -scope tb_dlatchsr.uut -sim-cmp dlatchsr
diff --git a/tests/sim/sim_sdff.ys b/tests/sim/sim_sdff.ys
new file mode 100644
index 000000000..a812c5d80
--- /dev/null
+++ b/tests/sim/sim_sdff.ys
@@ -0,0 +1,6 @@
+read_verilog sdff.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$sdff
+sim -clock clk -r tb_sdff.fst -scope tb_sdff.uut -sim-cmp sdff
diff --git a/tests/sim/sim_sdffce.ys b/tests/sim/sim_sdffce.ys
new file mode 100644
index 000000000..b28acb83d
--- /dev/null
+++ b/tests/sim/sim_sdffce.ys
@@ -0,0 +1,6 @@
+read_verilog sdffce.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$sdffce
+sim -clock clk -r tb_sdffce.fst -scope tb_sdffce.uut -sim-cmp sdffce
diff --git a/tests/sim/sim_sdffe.ys b/tests/sim/sim_sdffe.ys
new file mode 100644
index 000000000..044f78eb3
--- /dev/null
+++ b/tests/sim/sim_sdffe.ys
@@ -0,0 +1,6 @@
+read_verilog sdffe.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$sdffe
+sim -clock clk -r tb_sdffe.fst -scope tb_sdffe.uut -sim-cmp sdffe
diff --git a/tests/sim/tb/tb_adff.v b/tests/sim/tb/tb_adff.v
new file mode 100755
index 000000000..f1bc3547e
--- /dev/null
+++ b/tests/sim/tb/tb_adff.v
@@ -0,0 +1,40 @@
+`timescale 1ns/1ns
+module tb_adff();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ wire q;
+
+ adff uut(.clk(clk),.d(d),.rst(rst),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_adff");
+ $dumpvars(0,tb_adff);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_adffe.v b/tests/sim/tb/tb_adffe.v
new file mode 100755
index 000000000..bb23f963d
--- /dev/null
+++ b/tests/sim/tb/tb_adffe.v
@@ -0,0 +1,58 @@
+`timescale 1ns/1ns
+module tb_adffe();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ reg en = 0;
+ wire q;
+
+ adffe uut(.clk(clk),.d(d),.rst(rst),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_adffe");
+ $dumpvars(0,tb_adffe);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_adlatch.v b/tests/sim/tb/tb_adlatch.v
new file mode 100755
index 000000000..59dd498d2
--- /dev/null
+++ b/tests/sim/tb/tb_adlatch.v
@@ -0,0 +1,70 @@
+`timescale 1ns/1ns
+module tb_adlatch();
+ reg clk = 0;
+ reg rst = 0;
+ reg en = 0;
+ reg d = 0;
+ wire q;
+
+ adlatch uut(.d(d),.rst(rst),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_adlatch");
+ $dumpvars(0,tb_adlatch);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_aldff.v b/tests/sim/tb/tb_aldff.v
new file mode 100755
index 000000000..0591c8b3c
--- /dev/null
+++ b/tests/sim/tb/tb_aldff.v
@@ -0,0 +1,73 @@
+`timescale 1ns/1ns
+module tb_aldff();
+ reg clk = 0;
+ reg aload = 0;
+ reg [0:3] d = 4'b0000;
+ reg [0:3] ad = 4'b1010;
+ wire [0:3] q;
+
+ aldff uut(.clk(clk),.d(d),.ad(ad),.aload(aload),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_aldff");
+ $dumpvars(0,tb_aldff);
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 1;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 0;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 1;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 0;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_aldffe.v b/tests/sim/tb/tb_aldffe.v
new file mode 100755
index 000000000..c3cb57f4e
--- /dev/null
+++ b/tests/sim/tb/tb_aldffe.v
@@ -0,0 +1,75 @@
+`timescale 1ns/1ns
+module tb_aldffe();
+ reg clk = 0;
+ reg aload = 0;
+ reg [0:3] d = 4'b0000;
+ reg [0:3] ad = 4'b1010;
+ reg en = 0;
+ wire [0:3] q;
+
+ aldffe uut(.clk(clk),.d(d),.ad(ad),.aload(aload),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_aldffe");
+ $dumpvars(0,tb_aldffe);
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 1;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 0;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ en = 1;
+ aload = 1;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 0;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dff.v b/tests/sim/tb/tb_dff.v
new file mode 100755
index 000000000..aa41d1c6c
--- /dev/null
+++ b/tests/sim/tb/tb_dff.v
@@ -0,0 +1,47 @@
+`timescale 1ns/1ns
+module tb_dff();
+ reg clk = 0;
+ reg d = 0;
+ wire q;
+
+ dff uut(.clk(clk),.d(d),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_dff");
+ $dumpvars(0,tb_dff);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dffe.v b/tests/sim/tb/tb_dffe.v
new file mode 100755
index 000000000..4e262b928
--- /dev/null
+++ b/tests/sim/tb/tb_dffe.v
@@ -0,0 +1,42 @@
+`timescale 1ns/1ns
+module tb_dffe();
+ reg clk = 0;
+ reg en = 0;
+ reg d = 0;
+ wire q;
+
+ dffe uut(.clk(clk),.d(d),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_dffe");
+ $dumpvars(0,tb_dffe);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dffsr.v b/tests/sim/tb/tb_dffsr.v
new file mode 100755
index 000000000..6ecb85d67
--- /dev/null
+++ b/tests/sim/tb/tb_dffsr.v
@@ -0,0 +1,69 @@
+`timescale 1ns/1ns
+module tb_dffsr();
+ reg clk = 0;
+ reg d = 0;
+ reg set = 0;
+ reg clr = 0;
+ wire q;
+
+ dffsr uut(.d(d),.clk(clk),.set(set),.clr(clr),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_dffsr");
+ $dumpvars(0,tb_dffsr);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ clr = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ clr = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ set = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ set = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dlatch.v b/tests/sim/tb/tb_dlatch.v
new file mode 100755
index 000000000..aea6cb0a3
--- /dev/null
+++ b/tests/sim/tb/tb_dlatch.v
@@ -0,0 +1,50 @@
+`timescale 1ns/1ns
+module tb_dlatch();
+ reg clk = 0;
+ reg en = 0;
+ reg d = 0;
+ wire q;
+
+ dlatch uut(.d(d),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_dlatch");
+ $dumpvars(0,tb_dlatch);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dlatchsr.v b/tests/sim/tb/tb_dlatchsr.v
new file mode 100755
index 000000000..0105d3288
--- /dev/null
+++ b/tests/sim/tb/tb_dlatchsr.v
@@ -0,0 +1,65 @@
+`timescale 1ns/1ns
+module tb_dlatchsr();
+ reg d = 0;
+ reg set = 0;
+ reg clr = 0;
+ wire q;
+
+ dlatchsr uut(.d(d),.set(set),.clr(clr),.q(q));
+
+ initial
+ begin
+ $dumpfile("tb_dlatchsr");
+ $dumpvars(0,tb_dlatchsr);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ clr = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ clr = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ set = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ set = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_sdff.v b/tests/sim/tb/tb_sdff.v
new file mode 100755
index 000000000..f8e2a1c9d
--- /dev/null
+++ b/tests/sim/tb/tb_sdff.v
@@ -0,0 +1,48 @@
+`timescale 1ns/1ns
+module tb_sdff();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ wire q;
+
+ sdff uut(.clk(clk),.d(d),.rst(rst),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_sdff");
+ $dumpvars(0,tb_sdff);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_sdffce.v b/tests/sim/tb/tb_sdffce.v
new file mode 100755
index 000000000..1c9952806
--- /dev/null
+++ b/tests/sim/tb/tb_sdffce.v
@@ -0,0 +1,79 @@
+`timescale 1ns/1ns
+module tb_sdffce();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ reg en = 0;
+ wire q;
+
+ sdffce uut(.clk(clk),.d(d),.rst(rst),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_sdffce");
+ $dumpvars(0,tb_sdffce);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_sdffe.v b/tests/sim/tb/tb_sdffe.v
new file mode 100755
index 000000000..36072f93d
--- /dev/null
+++ b/tests/sim/tb/tb_sdffe.v
@@ -0,0 +1,70 @@
+`timescale 1ns/1ns
+module tb_sdffe();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ reg en = 0;
+ wire q;
+
+ sdffe uut(.clk(clk),.d(d),.rst(rst),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_sdffe");
+ $dumpvars(0,tb_sdffe);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule