mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-19 09:54:49 -04:00
adds a dual ported RAM
This commit is contained in:
parent
43d191b8a0
commit
e65635ef0e
@ -4,9 +4,10 @@ HEAD, planned as v0.16
|
||||
- RAM components and EEPROM now allow an input invert configuration.
|
||||
- Measurement values dialog is also able to modify the values.
|
||||
- Now you can open the measurement value table and graph in a running simulation.
|
||||
- Added a bit extender to extend signed values.
|
||||
- Added a bit extender component to extend signed values.
|
||||
- Added a simple unclocked RS flip-flop
|
||||
- Added a bit selector
|
||||
- Added a bit selector component
|
||||
- Added a dual ported RAM component
|
||||
- Added tooltips showing the actual value to wires.
|
||||
- Bug fixes
|
||||
- Fixed a bug in the RAMSinglePortSel component: Write was not edge-triggered on WE. Now it is.
|
||||
|
140
src/main/java/de/neemann/digital/core/memory/RAMDualAccess.java
Normal file
140
src/main/java/de/neemann/digital/core/memory/RAMDualAccess.java
Normal file
@ -0,0 +1,140 @@
|
||||
package de.neemann.digital.core.memory;
|
||||
|
||||
import de.neemann.digital.core.*;
|
||||
import de.neemann.digital.core.element.Element;
|
||||
import de.neemann.digital.core.element.ElementAttributes;
|
||||
import de.neemann.digital.core.element.ElementTypeDescription;
|
||||
import de.neemann.digital.core.element.Keys;
|
||||
|
||||
import static de.neemann.digital.core.element.PinInfo.input;
|
||||
|
||||
/**
|
||||
* RAM module with different ports to read and write the data
|
||||
* and an additional read port. Used to implement graphic card memory.
|
||||
*
|
||||
* @author hneemann
|
||||
*/
|
||||
public class RAMDualAccess extends Node implements Element, RAMInterface {
|
||||
|
||||
/**
|
||||
* The RAMs {@link ElementTypeDescription}
|
||||
*/
|
||||
public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(RAMDualAccess.class,
|
||||
input("str"),
|
||||
input("C"),
|
||||
input("ld"),
|
||||
input("1A"),
|
||||
input("1D_in"),
|
||||
input("2A"))
|
||||
.addAttribute(Keys.ROTATE)
|
||||
.addAttribute(Keys.BITS)
|
||||
.addAttribute(Keys.ADDR_BITS)
|
||||
.addAttribute(Keys.LABEL);
|
||||
|
||||
private final DataField memory;
|
||||
private final ObservableValue out1;
|
||||
private final ObservableValue out2;
|
||||
private final int addrBits;
|
||||
private final int bits;
|
||||
private final String label;
|
||||
private final int size;
|
||||
private ObservableValue addr1In;
|
||||
private ObservableValue data1In;
|
||||
private ObservableValue str1In;
|
||||
private ObservableValue clk1In;
|
||||
private ObservableValue ld1In;
|
||||
private ObservableValue addr2In;
|
||||
private int addr1;
|
||||
private int addr2;
|
||||
private boolean lastClk = false;
|
||||
private boolean ld;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param attr the elemets attributes
|
||||
*/
|
||||
public RAMDualAccess(ElementAttributes attr) {
|
||||
super(true);
|
||||
bits = attr.get(Keys.BITS);
|
||||
out1 = new ObservableValue("1D", bits, true).setPinDescription(DESCRIPTION);
|
||||
out2 = new ObservableValue("2D", bits).setPinDescription(DESCRIPTION);
|
||||
addrBits = attr.get(Keys.ADDR_BITS);
|
||||
size = 1 << addrBits;
|
||||
memory = new DataField(size);
|
||||
label = attr.getCleanLabel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputs(ObservableValues inputs) throws NodeException {
|
||||
this.str1In = inputs.get(0).checkBits(1, this);
|
||||
this.clk1In = inputs.get(1).checkBits(1, this).addObserverToValue(this);
|
||||
this.ld1In = inputs.get(2).checkBits(1, this).addObserverToValue(this);
|
||||
this.addr1In = inputs.get(3).checkBits(addrBits, this).addObserverToValue(this);
|
||||
this.data1In = inputs.get(4).checkBits(bits, this);
|
||||
this.addr2In = inputs.get(5).checkBits(addrBits, this).addObserverToValue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableValues getOutputs() {
|
||||
return new ObservableValues(out1, out2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readInputs() throws NodeException {
|
||||
long data = 0;
|
||||
boolean clk = clk1In.getBool();
|
||||
boolean str;
|
||||
if (!lastClk && clk) {
|
||||
str = str1In.getBool();
|
||||
if (str)
|
||||
data = data1In.getValue();
|
||||
} else
|
||||
str = false;
|
||||
ld = ld1In.getBool();
|
||||
if (ld || str)
|
||||
addr1 = (int) addr1In.getValue();
|
||||
|
||||
if (str)
|
||||
memory.setData(addr1, data);
|
||||
|
||||
addr2 = (int) addr2In.getValue();
|
||||
|
||||
lastClk = clk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeOutputs() throws NodeException {
|
||||
if (ld) {
|
||||
out1.set(memory.getDataWord(addr1), false);
|
||||
} else {
|
||||
out1.set(0, true);
|
||||
}
|
||||
out2.setValue(memory.getDataWord(addr2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataField getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDataBits() {
|
||||
return bits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAddrBits() {
|
||||
return addrBits;
|
||||
}
|
||||
}
|
@ -150,6 +150,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
||||
.add(RAMSinglePortSel.DESCRIPTION)
|
||||
.add(EEPROM.DESCRIPTION)
|
||||
.add(GraphicCard.DESCRIPTION)
|
||||
.add(RAMDualAccess.DESCRIPTION)
|
||||
.add(Counter.DESCRIPTION))
|
||||
.add(new LibraryNode(Lang.get("lib_arithmetic"))
|
||||
.add(Add.DESCRIPTION)
|
||||
|
@ -7,10 +7,7 @@ import de.neemann.digital.core.element.ElementTypeDescription;
|
||||
import de.neemann.digital.core.element.Keys;
|
||||
import de.neemann.digital.core.element.PinDescriptions;
|
||||
import de.neemann.digital.core.io.*;
|
||||
import de.neemann.digital.core.memory.EEPROM;
|
||||
import de.neemann.digital.core.memory.RAMDualPort;
|
||||
import de.neemann.digital.core.memory.RAMSinglePort;
|
||||
import de.neemann.digital.core.memory.RAMSinglePortSel;
|
||||
import de.neemann.digital.core.memory.*;
|
||||
import de.neemann.digital.core.pld.*;
|
||||
import de.neemann.digital.core.switching.*;
|
||||
import de.neemann.digital.core.wiring.*;
|
||||
@ -79,6 +76,7 @@ public final class ShapeFactory {
|
||||
map.put(RAMSinglePort.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, RAMSinglePort.DESCRIPTION));
|
||||
map.put(RAMSinglePortSel.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, RAMSinglePortSel.DESCRIPTION));
|
||||
map.put(EEPROM.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, EEPROM.DESCRIPTION));
|
||||
map.put(RAMDualAccess.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, RAMDualAccess.DESCRIPTION));
|
||||
|
||||
map.put(In.DESCRIPTION.getName(), InputShape::new);
|
||||
map.put(Reset.DESCRIPTION.getName(), ResetShape::new);
|
||||
|
@ -434,8 +434,25 @@
|
||||
<string name="elem_GraphicCard_pin_str">Ist dieser Eingang 1 wird mit steigendem Takt das Datenwort gespeichert.</string>
|
||||
<string name="elem_GraphicCard_pin_C">Der Takt. Eine steigende Flanke aktiviert das Speichern.</string>
|
||||
<string name="elem_GraphicCard_pin_ld">Ist dieser Eingang 1 wird das Datenwort ausgegeben.</string>
|
||||
<string name="elem_GraphicCard_pin_B">Auswahl der anzuzeigenden Seite. Mit diesem Eingang kann zwischen zwei Speicherseiten umgeschaltet werden.</string>
|
||||
<string name="elem_GraphicCard_pin_B">Auswahl der anzuzeigenden Seite.
|
||||
Mit diesem Eingang kann zwischen zwei Speicherseiten umgeschaltet werden.</string>
|
||||
<string name="elem_GraphicCard_pin_D">Der bidirektionale Datenanschluss.</string>
|
||||
|
||||
<string name="elem_RAMDualAccess">RAM, Dual Port</string>
|
||||
<string name="elem_RAMDualAccess_short">RAM</string>
|
||||
<string name="elem_RAMDualAccess_tt">RAM mit einem Port der das Beschreiben und Lesen des RAMs ermöglicht, und einem
|
||||
zweiten Leseport. Dieser zweite Port kann verwendet werden, um einer Grafik-Logik Zugriff auf den Speicherinhalt
|
||||
zu geben. Auf diese Weise kann ein Prozessor in das RAM schreiben, und eine Grafik-Logik kann das RAM
|
||||
gleichzeitig auslesen.</string>
|
||||
<string name="elem_RAMDualAccess_pin_1D">Ausgabeport 1</string>
|
||||
<string name="elem_RAMDualAccess_pin_2D">Ausgabeport 2</string>
|
||||
<string name="elem_RAMDualAccess_pin_1A">Die Adresse, an der über Port 1 gelesen bzw. geschrieben wird.</string>
|
||||
<string name="elem_RAMDualAccess_pin_2A">Die Adresse, an der über Port 2 gelesen wird.</string>
|
||||
<string name="elem_RAMDualAccess_pin_C">Der Takt. Eine steigende Flanke aktiviert das Speichern.</string>
|
||||
<string name="elem_RAMDualAccess_pin_1D_in">Die Daten die gespeichert werden sollen.</string>
|
||||
<string name="elem_RAMDualAccess_pin_ld">Ist diese Leitung high, wird der Ausgang D1 aktiviert, und die Daten liegen dort an.</string>
|
||||
<string name="elem_RAMDualAccess_pin_str">Ist diese Leitung high wird das Datenwort an D1 gespeichert, wenn der Takt ansteigt.</string>
|
||||
|
||||
<string name="elem_Counter">Zähler</string>
|
||||
<string name="elem_Counter_tt">Ein einfacher Zähler-Baustein.
|
||||
Zählt jede steigende Flanke am C Eingang und kann über den clr Eingang zurückgesetzt werden.
|
||||
|
@ -398,7 +398,7 @@
|
||||
<string name="elem_RAMDualPort_tt">A RAM module with separate inputs for storing and output for reading the stored data.</string>
|
||||
<string name="elem_RAMDualPort_pin_A">The address to read from or write to.</string>
|
||||
<string name="elem_RAMDualPort_pin_C">Clock input</string>
|
||||
<string name="elem_RAMDualPort_pin_D_in">The data to be stored in the RAM</string>
|
||||
<string name="elem_RAMDualPort_pin_D_in">The data to be stored in the RAM.</string>
|
||||
<string name="elem_RAMDualPort_pin_D">The data output pin</string>
|
||||
<string name="elem_RAMDualPort_pin_ld">If this input is high the output is activated and the data is visible at the output.</string>
|
||||
<string name="elem_RAMDualPort_pin_str">If this input is high and when the clock becomes high, the the data is stored.</string>
|
||||
@ -441,6 +441,22 @@
|
||||
<string name="elem_GraphicCard_pin_ld">If this input is high the output is activated and the data is visible at the output.</string>
|
||||
<string name="elem_GraphicCard_pin_B">Selects the screen buffer to show.</string>
|
||||
<string name="elem_GraphicCard_pin_D">The bidirectional data connection.</string>
|
||||
|
||||
<string name="elem_RAMDualAccess">RAM, Dual Port</string>
|
||||
<string name="elem_RAMDualAccess_short">RAM</string>
|
||||
<string name="elem_RAMDualAccess_tt">RAM with one port that allows to write to and read from the RAM, and a second
|
||||
read only port.
|
||||
This second port can be used to give some graphic logic access to the memory contents. In this way, a processor
|
||||
can write to the RAM, and a graphics logic can simultaneously read from the RAM.</string>
|
||||
<string name="elem_RAMDualAccess_pin_1D">Output Port 1</string>
|
||||
<string name="elem_RAMDualAccess_pin_2D">Output Port 2</string>
|
||||
<string name="elem_RAMDualAccess_pin_1A">The address at which port 1 is read or written.</string>
|
||||
<string name="elem_RAMDualAccess_pin_2A">The address used to read via port 2.</string>
|
||||
<string name="elem_RAMDualAccess_pin_C">Clock</string>
|
||||
<string name="elem_RAMDualAccess_pin_1D_in">The data to be stored in the RAM.</string>
|
||||
<string name="elem_RAMDualAccess_pin_ld">If this input is high the output is activated and the data is visible at the output 1D.</string>
|
||||
<string name="elem_RAMDualAccess_pin_str">If this input is high and when the clock becomes high, the the data is stored.</string>
|
||||
|
||||
<string name="elem_Counter">Counter</string>
|
||||
<string name="elem_Counter_tt">A simple counter component. The clock input increases the counter.
|
||||
Can be reset back to 0 with the clr input.
|
||||
|
33
src/main/resources/vhdl/DIG_RAMDualAccess.vhdl
Normal file
33
src/main/resources/vhdl/DIG_RAMDualAccess.vhdl
Normal file
@ -0,0 +1,33 @@
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
USE ieee.numeric_std.all;
|
||||
|
||||
entity DIG_RAMDualAccess is
|
||||
generic (
|
||||
Bits : integer;
|
||||
AddrBits : integer );
|
||||
port (
|
||||
PORT_1D: out std_logic_vector ((Bits-1) downto 0);
|
||||
PORT_2D: out std_logic_vector ((Bits-1) downto 0);
|
||||
PORT_str: in std_logic;
|
||||
PORT_C: in std_logic;
|
||||
PORT_ld: in std_logic;
|
||||
PORT_1A: in std_logic_vector ((AddrBits-1) downto 0);
|
||||
PORT_1D_in: in std_logic_vector ((Bits-1) downto 0);
|
||||
PORT_2A: in std_logic_vector ((AddrBits-1) downto 0) );
|
||||
end DIG_RAMDualAccess;
|
||||
|
||||
architecture DIG_RAMDualAccess_arch of DIG_RAMDualAccess is
|
||||
-- CAUTION: uses distributed RAM
|
||||
type memoryType is array(0 to (2**AddrBits)-1) of STD_LOGIC_VECTOR((Bits-1) downto 0);
|
||||
signal memory : memoryType;
|
||||
begin
|
||||
process ( PORT_C )
|
||||
begin
|
||||
if rising_edge(PORT_C) AND (PORT_str='1') then
|
||||
memory(to_integer(unsigned(PORT_1A))) <= PORT_1D_in;
|
||||
end if;
|
||||
end process;
|
||||
PORT_1D <= memory(to_integer(unsigned(PORT_1A))) when PORT_ld='1' else (others => 'Z');
|
||||
PORT_2D <= memory(to_integer(unsigned(PORT_2A)));
|
||||
end DIG_RAMDualAccess_arch;
|
@ -37,7 +37,7 @@ public class TestInSimulator extends TestCase {
|
||||
File examples = new File(Resources.getRoot(), "/dig/test/vhdl");
|
||||
try {
|
||||
int tested = new FileScanner(this::check).scan(examples);
|
||||
assertEquals(23, tested);
|
||||
assertEquals(24, tested);
|
||||
assertEquals(tested, testBenches);
|
||||
} catch (FileScanner.SkipAllException e) {
|
||||
// if ghdl is not installed its also ok
|
||||
|
@ -40,8 +40,8 @@ public class TestExamples extends TestCase {
|
||||
*/
|
||||
public void testTestExamples() throws Exception {
|
||||
File examples = new File(Resources.getRoot(), "/dig/test");
|
||||
assertEquals(112, new FileScanner(this::check).scan(examples));
|
||||
assertEquals(102, testCasesInFiles);
|
||||
assertEquals(113, new FileScanner(this::check).scan(examples));
|
||||
assertEquals(103, testCasesInFiles);
|
||||
}
|
||||
|
||||
|
||||
|
225
src/test/resources/dig/test/vhdl/dualPortRam.dig
Normal file
225
src/test/resources/dig/test/vhdl/dualPortRam.dig
Normal file
@ -0,0 +1,225 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<circuit>
|
||||
<version>1</version>
|
||||
<attributes/>
|
||||
<visualElements>
|
||||
<visualElement>
|
||||
<elementName>RAMDualAccess</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>AddrBits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="480" y="200"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Out</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>1D</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="580" y="200"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Out</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>2D</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="580" y="240"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>In</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>str</string>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="360" y="200"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>In</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>C</string>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="360" y="240"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>In</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>ld</string>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="360" y="280"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>In</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>1A</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="360" y="320"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>In</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>1Di</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="360" y="360"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>In</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Label</string>
|
||||
<string>2A</string>
|
||||
</entry>
|
||||
<entry>
|
||||
<string>Bits</string>
|
||||
<int>8</int>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="360" y="400"/>
|
||||
</visualElement>
|
||||
<visualElement>
|
||||
<elementName>Testcase</elementName>
|
||||
<elementAttributes>
|
||||
<entry>
|
||||
<string>Testdata</string>
|
||||
<testData>
|
||||
<dataString>str C ld 1A 1Di 1D 2A 2D
|
||||
|
||||
loop (a, 256)
|
||||
1 c 0 (a) (a+10) z 0 x
|
||||
end loop
|
||||
|
||||
|
||||
loop (a, 256)
|
||||
0 0 1 (a) 0 (a+10) (a+10) (a+20)
|
||||
end loop
|
||||
</dataString>
|
||||
</testData>
|
||||
</entry>
|
||||
</elementAttributes>
|
||||
<pos x="540" y="360"/>
|
||||
</visualElement>
|
||||
</visualElements>
|
||||
<wires>
|
||||
<wire>
|
||||
<p1 x="560" y="240"/>
|
||||
<p2 x="580" y="240"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="360" y="240"/>
|
||||
<p2 x="380" y="240"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="240"/>
|
||||
<p2 x="480" y="240"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="360" y="320"/>
|
||||
<p2 x="420" y="320"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="360" y="400"/>
|
||||
<p2 x="460" y="400"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="420" y="260"/>
|
||||
<p2 x="480" y="260"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="540" y="200"/>
|
||||
<p2 x="580" y="200"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="360" y="200"/>
|
||||
<p2 x="480" y="200"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="360" y="280"/>
|
||||
<p2 x="400" y="280"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="440" y="280"/>
|
||||
<p2 x="480" y="280"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="360" y="360"/>
|
||||
<p2 x="440" y="360"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="540" y="220"/>
|
||||
<p2 x="560" y="220"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="380" y="220"/>
|
||||
<p2 x="480" y="220"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="460" y="300"/>
|
||||
<p2 x="480" y="300"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="560" y="220"/>
|
||||
<p2 x="560" y="240"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="400" y="240"/>
|
||||
<p2 x="400" y="280"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="420" y="260"/>
|
||||
<p2 x="420" y="320"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="440" y="280"/>
|
||||
<p2 x="440" y="360"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="380" y="220"/>
|
||||
<p2 x="380" y="240"/>
|
||||
</wire>
|
||||
<wire>
|
||||
<p1 x="460" y="300"/>
|
||||
<p2 x="460" y="400"/>
|
||||
</wire>
|
||||
</wires>
|
||||
</circuit>
|
Loading…
x
Reference in New Issue
Block a user