From 9d3505c86ad22e85d43aa327280b6d13b282baec Mon Sep 17 00:00:00 2001 From: Fredrik Andersson Date: Sat, 28 Jan 2023 10:09:49 +0100 Subject: [PATCH] Cleanup 6502 example --- examples/yosys_6502/example_yosys_6502.py | 56 +------------------ src/digsim/circuit/components/__init__.py | 2 + src/digsim/circuit/components/_mem64kbyte.py | 32 +++++++++++ src/digsim/circuit/components/_memstdout.py | 28 ++++++++++ .../circuit/components/atoms/_component.py | 11 ---- src/digsim/circuit/components/atoms/_port.py | 15 +++++ 6 files changed, 80 insertions(+), 64 deletions(-) create mode 100644 src/digsim/circuit/components/_mem64kbyte.py create mode 100644 src/digsim/circuit/components/_memstdout.py diff --git a/examples/yosys_6502/example_yosys_6502.py b/examples/yosys_6502/example_yosys_6502.py index 35908a9..e01c390 100644 --- a/examples/yosys_6502/example_yosys_6502.py +++ b/examples/yosys_6502/example_yosys_6502.py @@ -4,57 +4,7 @@ import os from digsim.circuit import Circuit -from digsim.circuit.components import Clock, PushButton, YosysComponent -from digsim.circuit.components.atoms import Component, PortIn, PortOut, PortWire - - -class Memory(Component): - def __init__(self, circuit, rom_filename=None, rom_address=0): - super().__init__(circuit, "Memory") - self.add_port(PortIn(self, "clk")) - self.add_port(PortWire(self, "Address", width=16)) - self.add_port(PortWire(self, "DataIn", width=8)) - self.add_port(PortWire(self, "WE")) - self.add_port(PortOut(self, "DataOut", width=8)) - self._mem_array = [0] * 65536 - if rom_filename is not None: - with open(rom_filename, mode="rb") as rom: - romdata = rom.read() - for idx, byte in enumerate(romdata): - self._mem_array[rom_address + idx] = byte - - def update(self): - if not self.is_rising_edge(self.clk) or self.Address.value == "X": - return - addr = self.Address.value - we = self.WE.value - if we == 1: - datain = self.DataIn.value - self._mem_array[addr] = datain - else: - dataout = self._mem_array[addr] - self.DataOut.value = dataout - - -class StringOutput(Component): - def __init__(self, circuit): - super().__init__(circuit, "StringOutput") - self.add_port(PortIn(self, "clk")) - self.add_port(PortWire(self, "Address", width=16)) - self.add_port(PortWire(self, "DataIn", width=8)) - self.add_port(PortWire(self, "WE")) - self._str = "" - - def update(self): - if self.WE.value == 0 or self.Address.value != 0x8000: - return - if self.is_rising_edge(self.clk): - datain = self.DataIn.value - if datain == 0x0A: - print(f"OUTPUT: '{self._str}'") - self._str = "" - else: - self._str += chr(datain) +from digsim.circuit.components import Clock, Mem64kByte, MemStdOut, PushButton, YosysComponent test_circuit = Circuit(vcd="6502.vcd") @@ -64,10 +14,10 @@ def update(self): rdy = PushButton(test_circuit, "RDY") yosys_6502 = YosysComponent(test_circuit, filename=f"{os.path.dirname(__file__)}/6502.json") -mem = Memory( +mem = Mem64kByte( test_circuit, rom_filename=f"{os.path.dirname(__file__)}/code.bin", rom_address=0xF800 ) -output = StringOutput(test_circuit) +output = MemStdOut(test_circuit, address=0x8000) clk.wire = mem.clk yosys_6502.AB.wire = mem.Address diff --git a/src/digsim/circuit/components/__init__.py b/src/digsim/circuit/components/__init__.py index 4109464..5a98453 100644 --- a/src/digsim/circuit/components/__init__.py +++ b/src/digsim/circuit/components/__init__.py @@ -6,6 +6,8 @@ from ._gates import AND, NAND, NOT, SR, XOR # noqa: F401 from ._hexdigit import HexDigit # noqa: F401 from ._led import Led # noqa: F401 +from ._mem64kbyte import Mem64kByte # noqa: F401 +from ._memstdout import MemStdOut # noqa: F401 from ._on_off_switch import OnOffSwitch # noqa: F401 from ._power import GND, VDD # noqa: F401 from ._seven_segment import SevenSegment # noqa: F401 diff --git a/src/digsim/circuit/components/_mem64kbyte.py b/src/digsim/circuit/components/_mem64kbyte.py new file mode 100644 index 0000000..0bdeecd --- /dev/null +++ b/src/digsim/circuit/components/_mem64kbyte.py @@ -0,0 +1,32 @@ +# Copyright (c) Fredrik Andersson, 2023 +# All rights reserved + +from digsim.circuit.components.atoms import Component, PortIn, PortOut, PortWire + + +class Mem64kByte(Component): + def __init__(self, circuit, rom_filename=None, rom_address=0): + super().__init__(circuit, "Memory") + self.add_port(PortIn(self, "clk")) + self.add_port(PortWire(self, "Address", width=16)) + self.add_port(PortWire(self, "DataIn", width=8)) + self.add_port(PortWire(self, "WE")) + self.add_port(PortOut(self, "DataOut", width=8)) + self._mem_array = [0] * 65536 + if rom_filename is not None: + with open(rom_filename, mode="rb") as rom: + romdata = rom.read() + for idx, byte in enumerate(romdata): + self._mem_array[rom_address + idx] = byte + + def update(self): + if not self.clk.is_rising_edge() or self.Address.value == "X": + return + addr = self.Address.value + we = self.WE.value + if we == 1: + datain = self.DataIn.value + self._mem_array[addr] = datain + else: + dataout = self._mem_array[addr] + self.DataOut.value = dataout diff --git a/src/digsim/circuit/components/_memstdout.py b/src/digsim/circuit/components/_memstdout.py new file mode 100644 index 0000000..42b86a7 --- /dev/null +++ b/src/digsim/circuit/components/_memstdout.py @@ -0,0 +1,28 @@ +# Copyright (c) Fredrik Andersson, 2023 +# All rights reserved + +from digsim.circuit.components.atoms import Component, PortIn, PortWire + + +class MemStdOut(Component): + def __init__(self, circuit, address=0x8000): + super().__init__(circuit, "MemStdOut") + self._address = address + self.add_port(PortIn(self, "clk")) + self.add_port(PortWire(self, "Address", width=16)) + self.add_port(PortWire(self, "DataIn", width=8)) + self.add_port(PortWire(self, "WE")) + self._str = "" + + def update(self): + if self.WE.value == 0 or self.Address.value != self._address: + return + if self.clk.is_rising_edge(): + datain = self.DataIn.value + if datain == 0x0A: + print(f"StringOutput [line]: '{self._str}'") + self._str = "" + else: + inchar = chr(datain) + print(f"StringOutput [char]: '{inchar}'") + self._str += inchar diff --git a/src/digsim/circuit/components/atoms/_component.py b/src/digsim/circuit/components/atoms/_component.py index 1251c03..0719b5d 100644 --- a/src/digsim/circuit/components/atoms/_component.py +++ b/src/digsim/circuit/components/atoms/_component.py @@ -99,17 +99,6 @@ def remove_connections(self): def add_event(self, port, value, delay_ns): self.circuit.add_event(port, value, delay_ns) - def is_rising_edge(self, port): - rising_edge = False - if ( - port.value == 1 - and port in self._edge_detect_dict - and self._edge_detect_dict[port] == 0 - ): - rising_edge = True - self._edge_detect_dict[port] = port.value - return rising_edge - def __str__(self): comp_str = f"{self.display_name()}" for port in self.inports(): diff --git a/src/digsim/circuit/components/atoms/_port.py b/src/digsim/circuit/components/atoms/_port.py index bca68d7..6fe8120 100644 --- a/src/digsim/circuit/components/atoms/_port.py +++ b/src/digsim/circuit/components/atoms/_port.py @@ -16,6 +16,7 @@ def __init__(self, parent, name, width=1, output=False): self._output = output # Is this port an output port self._wired_ports = [] # The ports that this port drives self._value = None # The value of this port + self._edge_detect_value = "X" # Last edge detect value self.init() # Initialize the port @property @@ -82,6 +83,20 @@ def is_output(self): def is_input(self): return not self._output + def is_rising_edge(self): + rising_edge = False + if self.value == 1 and self._edge_detect_value == 0: + rising_edge = True + self._edge_detect_value = self.value + return rising_edge + + def is_falling_edge(self): + falling_edge = False + if self.value == 0 and self._edge_detect_value == 1: + falling_edge = True + self._edge_detect_value = self.value + return falling_edge + @abc.abstractmethod def set_value(self, value): pass