From 516b536d5c7afdd1cf0f3dada43d9b79554ae892 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Wed, 26 Aug 2020 18:11:00 +0800 Subject: [PATCH] examples/sim: add shift register examples 2 shift register examples are introduced. Both examples stores 8 bit of values at a time. * `sr1.py`: Parallel-to-serial - uses 16-bit shift-right register. When the counter equals 0, new values of all the 8 bits are shifted into the 8 MSBs of the register; when the counter equals i, the i-th values previously shifted into the register is outputted as its LSB. * `sr2.py`: Serial-to-serial - uses 8-bit shift-right register. When the counter equals i, the i-th value shifted into the register is outputted as its LSB, while the ((i-1) mod 8)-th value at the previous clock cycle gets shifted into the register as its MSB. --- examples/sim/sr1.py | 70 +++++++++++++++++++++++++++++++++++++++++++++ examples/sim/sr2.py | 66 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 examples/sim/sr1.py create mode 100644 examples/sim/sr2.py diff --git a/examples/sim/sr1.py b/examples/sim/sr1.py new file mode 100644 index 000000000..175eb5622 --- /dev/null +++ b/examples/sim/sr1.py @@ -0,0 +1,70 @@ +from migen import * + + +class ShiftRegisterParallelToSerial(Module): + """A parallel-to-serial shift-right register, + where the new value of all bits are shifted in only right before all current bits are shifted out. + """ + def __init__(self): + self.values = values = [ + Signal(reset=i%2) for i in range(8) + ] + self.o = Signal() + + sr = Signal(len(values)*2) + counter = Signal(max=len(values)) + self.sync += [ + If(counter == 0, + sr.eq(Cat( + sr[1:-len(values)], + [values[i] for i in range(len(values))] + )) + ).Else( + sr[:-1].eq(sr[1:]) + ), + If(counter == len(values) - 1, + counter.eq(0) + ).Else( + counter.eq(counter + 1) + ) + ] + self.comb += self.o.eq(sr[0]) + + +def counter_test(dut): + # Assert reset condition: + # - If i is even, values[i] should be 0 + # - If i is odd, values[i] should be 1 + for i in range(8): + assert (yield dut.values[i]) == i % 2 + # Assume t is a counter with a reset of 0 + for t in range(32): + # Flip the bits when t=5 + # (Note: since no bits are shifted in before t=8, + # i.e. where values[0] of the currently-latched values + # will be shifted out at t=9, the flipped values will + # not be reflected until t=16) + if t == 5: + for i in range(8): + if i % 2: + yield dut.values[i].eq(0) + else: + yield dut.values[i].eq(1) + # Print the output for each cycle + print("t={} : {}".format(t, (yield dut.o))) + # When 0<=t<=7, since the reset values have not been fully shifted in yet, + # the output should stay 0 + if t in range(8): + assert (yield dut.o) == 0 + # When 8<=t<=15, output (all bits) should correspond to reset condition + if t in range(8, 16): + assert (yield dut.o) == t % 2 + # When t>=16, output should correspond to the flipped condition + if t >= 16: + assert (yield dut.o) == (t+1) % 2 + yield + + +if __name__ == "__main__": + dut = ShiftRegisterParallelToSerial() + run_simulation(dut, counter_test(dut), vcd_name="sr1.vcd") diff --git a/examples/sim/sr2.py b/examples/sim/sr2.py new file mode 100644 index 000000000..a4011fddb --- /dev/null +++ b/examples/sim/sr2.py @@ -0,0 +1,66 @@ +from migen import * + + +class ShiftRegisterSerialToSerial(Module): + """A serial-to-serial shift-right register, + where the new value of each next bit is shifted in every cycle. + """ + def __init__(self): + self.values = values = [ + Signal(reset=i%2) for i in range(8) + ] + self.o = Signal() + + sr = Signal(len(values)) + counter = Signal(max=len(values)) + self.sync += [ + If(counter == i, + sr[-1].eq(values[i]) + ) for i in range(len(values)) + ] + self.sync += [ + If(counter == len(values) - 1, + counter.eq(0) + ).Else( + counter.eq(counter + 1) + ), + sr[:-1].eq(sr[1:]) + ] + self.comb += self.o.eq(sr[0]) + + +def counter_test(dut): + # Assert reset condition: + # - If i is even, values[i] should be 0 + # - If i is odd, values[i] should be 1 + for i in range(8): + assert (yield dut.values[i]) == i % 2 + # Assume t is a counter with a reset of 0 + for t in range(32): + # Flip the bits when t=5 + # (i.e. 2 cycles before values[7] is shifted out, + # and new values[6] is shifted in) + if t == 5: + for i in range(8): + if i % 2: + yield dut.values[i].eq(0) + else: + yield dut.values[i].eq(1) + # Print the output for each cycle + print("t={} : {}".format(t, (yield dut.o))) + # When 0<=t<=7, since the reset values have not been fully shifted in yet, + # the output should stay 0 + if t in range(8): + assert (yield dut.o) == 0 + # When 8<=t<=13, output (bits 0 to 5) should correspond to reset condition + if t in range(8, 14): + assert (yield dut.o) == t % 2 + # When t>=14, output should correspond to the flipped condition (starting on bit 6) + if t >= 14: + assert (yield dut.o) == (t+1) % 2 + yield + + +if __name__ == "__main__": + dut = ShiftRegisterSerialToSerial() + run_simulation(dut, counter_test(dut), vcd_name="sr2.vcd")