-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
1 parent
7bc4eb1
commit 516b536
Showing
2 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") |