Skip to content

Commit

Permalink
Fix bug related to clock divider simulation, fix intel#191
Browse files Browse the repository at this point in the history
  • Loading branch information
mkorbel1 committed Nov 1, 2022
1 parent 77a6b14 commit 9d51ac3
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 7 deletions.
22 changes: 15 additions & 7 deletions lib/src/modules/conditional.dart
Original file line number Diff line number Diff line change
Expand Up @@ -336,14 +336,22 @@ class Sequential extends _Always {
clk.glitch.listen((event) async {
// we want the first previousValue from the first glitch of this tick
_preTickClkValues[i] ??= event.previousValue;
if (!_pendingExecute) {
unawaited(Simulator.clkStable.first.then((value) {
// once the clocks are stable, execute the contents of the FF
_execute();
_pendingExecute = false;
}));

if (Simulator.phase == SimulatorPhase.clkStable) {
// this could be an output of a flop driving the clock of this
// flop, so execute immediately (e.g. clock divider)
_execute();
_pendingExecute = false;
} else {
if (!_pendingExecute) {
unawaited(Simulator.clkStable.first.then((value) {
// once the clocks are stable, execute the contents of the FF
_execute();
_pendingExecute = false;
}));
}
_pendingExecute = true;
}
_pendingExecute = true;
});
}
}
Expand Down
69 changes: 69 additions & 0 deletions test/clock_divider_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import 'package:rohd/rohd.dart';
import 'package:rohd/src/utilities/simcompare.dart';
import 'package:test/test.dart';

import '../example/example.dart';

class ClockDivider extends Module {
Logic get clkOut => output('clkOut');
ClockDivider(Logic clkIn, Logic reset) : super(name: 'clockDivider') {
clkIn = addInput('clkIn', clkIn);
reset = addInput('reset', reset);
final clkOut = addOutput('clkOut');

Sequential(clkIn, [
If(
reset,
then: [clkOut < 0],
orElse: [clkOut < ~clkOut],
),
]);
}
}

class TwoCounters extends Module {
TwoCounters(Logic resetClks, Logic resetCounters) {
resetClks = addInput('resetClks', resetClks);
resetCounters = addInput('resetCounters', resetCounters);

final clk = SimpleClockGenerator(10).clk;
final clkDiv = ClockDivider(clk, resetClks).clkOut;

addOutput('cntFast', width: 8) <=
Counter(Const(1), resetCounters, clk, name: 'fastCounter').val;
addOutput('cntSlow', width: 8) <=
Counter(Const(1), resetCounters, clkDiv, name: 'slowCounter').val;
}
}

void main() {
test('clock divider', () async {
final mod = TwoCounters(Logic(), Logic());
await mod.build();
final vectors = [
Vector({'resetClks': 1, 'resetCounters': 1}, {}),
Vector({'resetClks': 0, 'resetCounters': 1}, {}),
Vector({'resetClks': 0, 'resetCounters': 1}, {}),
Vector(
{'resetClks': 0, 'resetCounters': 0}, {'cntSlow': 0, 'cntFast': 0}),
Vector(
{'resetClks': 0, 'resetCounters': 0}, {'cntSlow': 1, 'cntFast': 1}),
Vector(
{'resetClks': 0, 'resetCounters': 0}, {'cntSlow': 1, 'cntFast': 2}),
Vector(
{'resetClks': 0, 'resetCounters': 0}, {'cntSlow': 2, 'cntFast': 3}),
Vector(
{'resetClks': 0, 'resetCounters': 0}, {'cntSlow': 2, 'cntFast': 4}),
Vector(
{'resetClks': 0, 'resetCounters': 0}, {'cntSlow': 3, 'cntFast': 5}),
Vector(
{'resetClks': 0, 'resetCounters': 0}, {'cntSlow': 3, 'cntFast': 6}),
];

await SimCompare.checkFunctionalVector(mod, vectors);
final simResult = SimCompare.iverilogVector(
mod.generateSynth(), mod.runtimeType.toString(), vectors,
signalToWidthMap: {'cntSlow': 8, 'cntFast': 8});
expect(simResult, equals(true));
});
}

0 comments on commit 9d51ac3

Please sign in to comment.