From 4263ece634434ad85420acb5ca6d4953dbece945 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sat, 11 Mar 2017 12:21:42 +0100 Subject: [PATCH] added a RAM with a select/enable input --- .../digital/core/memory/RAMDualPort.java | 2 +- .../digital/core/memory/RAMSinglePort.java | 2 +- .../digital/core/memory/RAMSinglePortSel.java | 126 ++++++ .../digital/draw/library/ElementLibrary.java | 1 + .../digital/draw/shapes/ShapeFactory.java | 2 + src/main/resources/lang/lang_de.xml | 15 +- src/main/resources/lang/lang_en.xml | 16 +- .../digital/integration/TestExamples.java | 4 +- .../digital/lang/TestElemConsistence.java | 2 +- src/test/resources/dig/test/ram.dig | 409 ++++++++++++++++++ 10 files changed, 570 insertions(+), 9 deletions(-) create mode 100644 src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java create mode 100644 src/test/resources/dig/test/ram.dig diff --git a/src/main/java/de/neemann/digital/core/memory/RAMDualPort.java b/src/main/java/de/neemann/digital/core/memory/RAMDualPort.java index 31530c4d5..655f29f16 100644 --- a/src/main/java/de/neemann/digital/core/memory/RAMDualPort.java +++ b/src/main/java/de/neemann/digital/core/memory/RAMDualPort.java @@ -22,7 +22,7 @@ public class RAMDualPort extends Node implements Element, RAMInterface { input("A"), input("D_in"), input("str"), - input("c"), + input("C"), input("ld")) .addAttribute(Keys.ROTATE) .addAttribute(Keys.BITS) diff --git a/src/main/java/de/neemann/digital/core/memory/RAMSinglePort.java b/src/main/java/de/neemann/digital/core/memory/RAMSinglePort.java index f26a68c2e..372c4a78d 100644 --- a/src/main/java/de/neemann/digital/core/memory/RAMSinglePort.java +++ b/src/main/java/de/neemann/digital/core/memory/RAMSinglePort.java @@ -23,7 +23,7 @@ public class RAMSinglePort extends RAMDualPort { public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(RAMSinglePort.class, input("A"), input("str"), - input("c"), + input("C"), input("ld")) .addAttribute(Keys.ROTATE) .addAttribute(Keys.BITS) diff --git a/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java b/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java new file mode 100644 index 000000000..b5e261730 --- /dev/null +++ b/src/main/java/de/neemann/digital/core/memory/RAMSinglePortSel.java @@ -0,0 +1,126 @@ +package de.neemann.digital.core.memory; + +import de.neemann.digital.core.Node; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.ObservableValue; +import de.neemann.digital.core.ObservableValues; +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 de.neemann.digital.draw.elements.PinException; + +import static de.neemann.digital.core.element.PinInfo.input; + +/** + * RAM module with a single port to read and write data and a select input. + * This allows to build a bigger RAM with smaller RAMS and an additional address decoder. + * + * @author hneemann + */ +public class RAMSinglePortSel extends Node implements Element, RAMInterface { + + /** + * The RAMs {@link ElementTypeDescription} + */ + + public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription(RAMSinglePortSel.class, + input("A"), + input("sel"), + input("C"), + input("W/\u00ACR")) + .addAttribute(Keys.ROTATE) + .addAttribute(Keys.BITS) + .addAttribute(Keys.ADDR_BITS) + .addAttribute(Keys.LABEL); + + private final int bits; + private final int addrBits; + private final int size; + private final DataField memory; + private final String label; + private final ObservableValue dataOut; + private ObservableValue addrIn; + private ObservableValue selIn; + private ObservableValue clkIn; + private ObservableValue wnrIn; + private ObservableValue dataIn; + + private boolean lastClk = false; + private boolean sel; + private int addr; + private boolean write; + + /** + * Creates a new instance + * + * @param attr the elements attributes + */ + public RAMSinglePortSel(ElementAttributes attr) { + super(true); + bits = attr.get(Keys.BITS); + addrBits = attr.get(Keys.ADDR_BITS); + size = 1 << addrBits; + memory = new DataField(size); + label = attr.getCleanLabel(); + dataOut = new ObservableValue("D", bits, true).setPinDescription(DESCRIPTION).setBidirectional(true); + } + + @Override + public void setInputs(ObservableValues inputs) throws NodeException { + addrIn = inputs.get(0).checkBits(addrBits, this).addObserverToValue(this); + selIn = inputs.get(1).checkBits(1, this).addObserverToValue(this); + clkIn = inputs.get(2).checkBits(1, this).addObserverToValue(this); + wnrIn = inputs.get(3).checkBits(1, this).addObserverToValue(this); + dataIn = inputs.get(4).checkBits(bits, this).addObserverToValue(this); + } + + @Override + public void readInputs() throws NodeException { + boolean clk = clkIn.getBool(); + sel = selIn.getBool(); + if (sel) { + addr = (int) addrIn.getValue(); + write = wnrIn.getBool(); + if (write && !lastClk && clk) { + long data = dataIn.getValue(); + memory.setData(addr, data); + } + } + lastClk = clk; + } + + @Override + public void writeOutputs() throws NodeException { + if (sel && !write) { + dataOut.set(memory.getDataWord(addr), false); + } else { + dataOut.setHighZ(true); + } + } + + @Override + public ObservableValues getOutputs() throws PinException { + return dataOut.asList(); + } + + @Override + public DataField getMemory() { + return memory; + } + + @Override + public String getLabel() { + return label; + } + + @Override + public int getSize() { + return size; + } + + @Override + public int getBits() { + return bits; + } +} diff --git a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java index 3beb391d7..b71df5b63 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -96,6 +96,7 @@ public class ElementLibrary implements Iterable add(ROM.DESCRIPTION, menu); add(RAMDualPort.DESCRIPTION, menu); add(RAMSinglePort.DESCRIPTION, menu); + add(RAMSinglePortSel.DESCRIPTION, menu); add(GraphicCard.DESCRIPTION, menu); add(Counter.DESCRIPTION, menu); diff --git a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java index 804d5deba..87fb0c91b 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java +++ b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java @@ -9,6 +9,7 @@ import de.neemann.digital.core.element.PinDescriptions; import de.neemann.digital.core.io.*; 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.pld.*; import de.neemann.digital.core.switching.NFET; import de.neemann.digital.core.switching.PFET; @@ -77,6 +78,7 @@ public final class ShapeFactory { map.put(RAMDualPort.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, RAMDualPort.DESCRIPTION.getInputDescription(attr), RAMDualPort.DESCRIPTION.getOutputDescriptions(attr))); map.put(RAMSinglePort.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, RAMSinglePort.DESCRIPTION.getInputDescription(attr), RAMSinglePort.DESCRIPTION.getOutputDescriptions(attr))); + map.put(RAMSinglePortSel.DESCRIPTION.getName(), (attr, inputs, outputs) -> new RAMShape(attr, RAMSinglePortSel.DESCRIPTION.getInputDescription(attr), RAMSinglePortSel.DESCRIPTION.getOutputDescriptions(attr))); map.put(In.DESCRIPTION.getName(), InputShape::new); map.put(Reset.DESCRIPTION.getName(), ResetShape::new); diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index c0e55869d..f1b101b7d 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -204,7 +204,7 @@ Es können sowohl komplette Takte als auch einzelne Gatter-Veränderungen angeze RAMDualPort RAM Die Adresse, an der gelesen und geschrieben wird. - Der Takt. Eine steigende Flanke aktiviert das Speichern. + Der Takt. Eine steigende Flanke aktiviert das Speichern. Die Daten die gespeichert werden sollen Ausgabe der gespeicherten Daten. Ist diese Leitung high, wird der Ausgang aktiviert, und die Daten liegen dort an. @@ -214,11 +214,22 @@ Es können sowohl komplette Takte als auch einzelne Gatter-Veränderungen angeze RAMSinglePort RAM Die Adresse, an der gelesen und geschrieben wird. - Der Takt. Eine steigende Flanke aktiviert das Speichern. + Der Takt. Eine steigende Flanke aktiviert das Speichern. Der bidirektionale Datenanschluß. Ist dieser Eingang 1 wird das Datenwort ausgegeben. Ist dieser Eingang 1 wird mit steigendem Takt das Datenwort gespeichert. Ein RAM Module mit einem bidirektionellem Anschluss für das Lesen und Schreiben von Daten. + + RAMSinglePortSel + RAM + Die Adresse, an der gelesen und geschrieben wird. + Der Takt. Eine steigende Flanke aktiviert das Speichern. + Der bidirektionale Datenanschluß. + Ist dieser Eingang 1 ist der Baustein aktiv. + Ist dieser Eingang 1 wird mit steigendem Takt das Datenwort gespeichert, ist der Eingang 0, wird das gespeicherte Datenwort ausgegeben. + Ein RAM-Baustein mit einem bidirektionellem Anschluss für das Lesen und Schreiben von Daten. + Es gibt einen sel-Eingang. Mit diesem können mehrere solcher Bausteine mit einem Adressdecoder zu einem gtößeren RAM zusammengeschaltet werden. + Grafik-RAM Wird verwendet um Bitmap Grafiken anzuzeigen. Der Baustein verhält sich wie ein RAM-Baustein mit dem Unterschied, dass der RAM-Inhalt als Grafik angezeigt wird. Jede Speicherstelle definiert die Farbe diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 6e62a893a..45a6cab94 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -200,20 +200,32 @@ RAMDualPort RAM The address to read and write - Clock + Clock The data to be stored in the RAM The data output pin If this input is high the output is activated and the data is visible at the output. If this input is high when the clock becomes high, the the data is stored. A RAM module with separate inputs for storing and output for reading the stored data. + RAMSinglePort RAM The address to read and write. - Clock + Clock The bidirectional data connection. If this input is high the output is activated and the data is visible at the output. If this input is high when the clock becomes high, the the data is stored. A RAM module with a bidirectional connection for reading and writing the data. + + RAMSinglePortSel + RAM + The address to read and write. + Clock + The bidirectional data connection. + If this input is high this RAM is enabled. Otherwise the output is always in high Z state. + If this input is high and if the clock becomes high, the the data is stored. If this input is low the stored value is output. + A RAM module with a bidirectional connection for reading and writing the data. + The sel input allows to build a larger RAM from some smaller RAMs and a address decoder. + Graphic RAM Used to show a bitmap graphic. This element works similar to a RAM. In addition it shows its content on a grahic screen. Every pixel is represented by a memory address. There are to screens supported diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index 1d8627d5f..3134ff79e 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -39,8 +39,8 @@ public class TestExamples extends TestCase { */ public void testTestExamples() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test"); - assertEquals(48, new FileScanner(this::check).scan(examples)); - assertEquals(41, testCasesInFiles); + assertEquals(49, new FileScanner(this::check).scan(examples)); + assertEquals(42, testCasesInFiles); } diff --git a/src/test/java/de/neemann/digital/lang/TestElemConsistence.java b/src/test/java/de/neemann/digital/lang/TestElemConsistence.java index 0531705c7..2be2953e4 100644 --- a/src/test/java/de/neemann/digital/lang/TestElemConsistence.java +++ b/src/test/java/de/neemann/digital/lang/TestElemConsistence.java @@ -28,7 +28,7 @@ public class TestElemConsistence extends TestCase { ElementTypeDescription etd = e.getDescription(); String key = "elem_" + etd.getName(); - assertNotNull(Lang.getNull(key)); + assertNotNull("Key "+key+" not found", Lang.getNull(key)); if (Lang.getNull(key + "_tt") == null) missing(key + "_tt"); diff --git a/src/test/resources/dig/test/ram.dig b/src/test/resources/dig/test/ram.dig new file mode 100644 index 000000000..7def20901 --- /dev/null +++ b/src/test/resources/dig/test/ram.dig @@ -0,0 +1,409 @@ + + + 1 + + + In + + + Label + A + + + Bits + 6 + + + + + + Out + + + Label + Dout + + + Bits + 8 + + + + + + RAMSinglePortSel + + + Bits + 8 + + + Addr Bits + 4 + + + + + + In + + + rotation + + + + Label + Din + + + Bits + 8 + + + isHighZ + true + + + + + + In + + + Label + C + + + + + + In + + + Label + W + + + + + + RAMSinglePortSel + + + Bits + 8 + + + Addr Bits + 4 + + + + + + RAMSinglePortSel + + + Bits + 8 + + + Addr Bits + 4 + + + + + + RAMSinglePortSel + + + Bits + 8 + + + Addr Bits + 4 + + + + + + Splitter + + + Input Splitting + 6 + + + Output Splitting + 4,2 + + + + + + Testcase + + + Testdata + + sel A C W Din Dout + +# write some values + 1 0 C 1 7 X + 1 10 C 1 8 X + 1 20 C 1 9 X + 1 30 C 1 10 X + 1 40 C 1 11 X + 1 50 C 1 12 X + 1 60 C 1 13 X + +# read some values + 1 0 0 0 Z 7 + 1 10 0 0 Z 8 + 1 20 0 0 Z 9 + 1 30 0 0 Z 10 + 1 40 0 0 Z 11 + 1 50 0 0 Z 12 + 1 60 0 0 Z 13 + +# read with sel=0 does not work + 0 50 0 0 Z Z + 0 60 0 0 Z Z + +# write with sel=0 does not work + 0 1 C 1 7 X + 0 2 C 1 7 X + 1 1 0 0 Z 0 + 1 2 0 0 Z 0 + + + + + + + + Demultiplexer + + + Selector Bits + 2 + + + flipSelPos + true + + + + + + In + + + Label + sel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file