added a RAM with a select/enable input

This commit is contained in:
hneemann 2017-03-11 12:21:42 +01:00
parent 5ece68c132
commit 4263ece634
10 changed files with 570 additions and 9 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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;
}
}

View File

@ -96,6 +96,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
add(ROM.DESCRIPTION, menu);
add(RAMDualPort.DESCRIPTION, menu);
add(RAMSinglePort.DESCRIPTION, menu);
add(RAMSinglePortSel.DESCRIPTION, menu);
add(GraphicCard.DESCRIPTION, menu);
add(Counter.DESCRIPTION, menu);

View File

@ -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);

View File

@ -204,7 +204,7 @@ Es können sowohl komplette Takte als auch einzelne Gatter-Veränderungen angeze
<string name="elem_RAMDualPort">RAMDualPort</string>
<string name="elem_RAMDualPort_short">RAM</string>
<string name="elem_RAMDualPort_pin_A">Die Adresse, an der gelesen und geschrieben wird.</string>
<string name="elem_RAMDualPort_pin_c">Der Takt. Eine steigende Flanke aktiviert das Speichern.</string>
<string name="elem_RAMDualPort_pin_C">Der Takt. Eine steigende Flanke aktiviert das Speichern.</string>
<string name="elem_RAMDualPort_pin_D_in">Die Daten die gespeichert werden sollen</string>
<string name="elem_RAMDualPort_pin_D">Ausgabe der gespeicherten Daten.</string>
<string name="elem_RAMDualPort_pin_ld">Ist diese Leitung high, wird der Ausgang aktiviert, und die Daten liegen dort an.</string>
@ -214,11 +214,22 @@ Es können sowohl komplette Takte als auch einzelne Gatter-Veränderungen angeze
<string name="elem_RAMSinglePort">RAMSinglePort</string>
<string name="elem_RAMSinglePort_short">RAM</string>
<string name="elem_RAMSinglePort_pin_A">Die Adresse, an der gelesen und geschrieben wird.</string>
<string name="elem_RAMSinglePort_pin_c">Der Takt. Eine steigende Flanke aktiviert das Speichern.</string>
<string name="elem_RAMSinglePort_pin_C">Der Takt. Eine steigende Flanke aktiviert das Speichern.</string>
<string name="elem_RAMSinglePort_pin_D">Der bidirektionale Datenanschluß.</string>
<string name="elem_RAMSinglePort_pin_ld">Ist dieser Eingang 1 wird das Datenwort ausgegeben.</string>
<string name="elem_RAMSinglePort_pin_str">Ist dieser Eingang 1 wird mit steigendem Takt das Datenwort gespeichert.</string>
<string name="elem_RAMSinglePort_tt">Ein RAM Module mit einem bidirektionellem Anschluss für das Lesen und Schreiben von Daten.</string>
<string name="elem_RAMSinglePortSel">RAMSinglePortSel</string>
<string name="elem_RAMSinglePortSel_short">RAM</string>
<string name="elem_RAMSinglePortSel_pin_A">Die Adresse, an der gelesen und geschrieben wird.</string>
<string name="elem_RAMSinglePortSel_pin_C">Der Takt. Eine steigende Flanke aktiviert das Speichern.</string>
<string name="elem_RAMSinglePortSel_pin_D">Der bidirektionale Datenanschluß.</string>
<string name="elem_RAMSinglePortSel_pin_sel">Ist dieser Eingang 1 ist der Baustein aktiv.</string>
<string name="elem_RAMSinglePortSel_pin_W/¬R">Ist dieser Eingang 1 wird mit steigendem Takt das Datenwort gespeichert, ist der Eingang 0, wird das gespeicherte Datenwort ausgegeben.</string>
<string name="elem_RAMSinglePortSel_tt">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.</string>
<string name="elem_GraphicCard">Grafik-RAM</string>
<string name="elem_GraphicCard_tt">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

View File

@ -200,20 +200,32 @@
<string name="elem_RAMDualPort">RAMDualPort</string>
<string name="elem_RAMDualPort_short">RAM</string>
<string name="elem_RAMDualPort_pin_A">The address to read and write</string>
<string name="elem_RAMDualPort_pin_c">Clock</string>
<string name="elem_RAMDualPort_pin_C">Clock</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 when the clock becomes high, the the data is stored.</string>
<string name="elem_RAMDualPort_tt">A RAM module with separate inputs for storing and output for reading the stored data.</string>
<string name="elem_RAMSinglePort">RAMSinglePort</string>
<string name="elem_RAMSinglePort_short">RAM</string>
<string name="elem_RAMSinglePort_pin_A">The address to read and write.</string>
<string name="elem_RAMSinglePort_pin_c">Clock</string>
<string name="elem_RAMSinglePort_pin_C">Clock</string>
<string name="elem_RAMSinglePort_pin_D">The bidirectional data connection.</string>
<string name="elem_RAMSinglePort_pin_ld">If this input is high the output is activated and the data is visible at the output.</string>
<string name="elem_RAMSinglePort_pin_str">If this input is high when the clock becomes high, the the data is stored.</string>
<string name="elem_RAMSinglePort_tt">A RAM module with a bidirectional connection for reading and writing the data.</string>
<string name="elem_RAMSinglePortSel">RAMSinglePortSel</string>
<string name="elem_RAMSinglePortSel_short">RAM</string>
<string name="elem_RAMSinglePortSel_pin_A">The address to read and write.</string>
<string name="elem_RAMSinglePortSel_pin_C">Clock</string>
<string name="elem_RAMSinglePortSel_pin_D">The bidirectional data connection.</string>
<string name="elem_RAMSinglePortSel_pin_sel">If this input is high this RAM is enabled. Otherwise the output is always in high Z state.</string>
<string name="elem_RAMSinglePortSel_pin_W/¬R">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.</string>
<string name="elem_RAMSinglePortSel_tt">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.</string>
<string name="elem_GraphicCard">Graphic RAM</string>
<string name="elem_GraphicCard_tt">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

View File

@ -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);
}

View File

@ -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");

View File

@ -0,0 +1,409 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>1</version>
<visualElements>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>A</string>
</entry>
<entry>
<string>Bits</string>
<int>6</int>
</entry>
</elementAttributes>
<pos x="40" y="380"/>
</visualElement>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>Dout</string>
</entry>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
</elementAttributes>
<pos x="460" y="560"/>
</visualElement>
<visualElement>
<elementName>RAMSinglePortSel</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
<entry>
<string>Addr Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="320" y="380"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>rotation</string>
<rotation rotation="2"/>
</entry>
<entry>
<string>Label</string>
<string>Din</string>
</entry>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
<entry>
<string>isHighZ</string>
<boolean>true</boolean>
</entry>
</elementAttributes>
<pos x="460" y="420"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>C</string>
</entry>
</elementAttributes>
<pos x="120" y="440"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>W</string>
</entry>
</elementAttributes>
<pos x="40" y="460"/>
</visualElement>
<visualElement>
<elementName>RAMSinglePortSel</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
<entry>
<string>Addr Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="320" y="520"/>
</visualElement>
<visualElement>
<elementName>RAMSinglePortSel</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
<entry>
<string>Addr Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="320" y="660"/>
</visualElement>
<visualElement>
<elementName>RAMSinglePortSel</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>8</int>
</entry>
<entry>
<string>Addr Bits</string>
<int>4</int>
</entry>
</elementAttributes>
<pos x="320" y="800"/>
</visualElement>
<visualElement>
<elementName>Splitter</elementName>
<elementAttributes>
<entry>
<string>Input Splitting</string>
<string>6</string>
</entry>
<entry>
<string>Output Splitting</string>
<string>4,2</string>
</entry>
</elementAttributes>
<pos x="120" y="380"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Testdata</string>
<testData>
<dataString>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
</dataString>
</testData>
</entry>
</elementAttributes>
<pos x="20" y="820"/>
</visualElement>
<visualElement>
<elementName>Demultiplexer</elementName>
<elementAttributes>
<entry>
<string>Selector Bits</string>
<int>2</int>
</entry>
<entry>
<string>flipSelPos</string>
<boolean>true</boolean>
</entry>
</elementAttributes>
<pos x="140" y="580"/>
</visualElement>
<visualElement>
<elementName>In</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>sel</string>
</entry>
</elementAttributes>
<pos x="40" y="620"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="300" y="800"/>
<p2 x="320" y="800"/>
</wire>
<wire>
<p1 x="180" y="640"/>
<p2 x="200" y="640"/>
</wire>
<wire>
<p1 x="380" y="420"/>
<p2 x="400" y="420"/>
</wire>
<wire>
<p1 x="400" y="420"/>
<p2 x="460" y="420"/>
</wire>
<wire>
<p1 x="180" y="580"/>
<p2 x="200" y="580"/>
</wire>
<wire>
<p1 x="280" y="580"/>
<p2 x="320" y="580"/>
</wire>
<wire>
<p1 x="260" y="740"/>
<p2 x="320" y="740"/>
</wire>
<wire>
<p1 x="300" y="520"/>
<p2 x="320" y="520"/>
</wire>
<wire>
<p1 x="380" y="840"/>
<p2 x="400" y="840"/>
</wire>
<wire>
<p1 x="220" y="680"/>
<p2 x="320" y="680"/>
</wire>
<wire>
<p1 x="40" y="460"/>
<p2 x="260" y="460"/>
</wire>
<wire>
<p1 x="260" y="460"/>
<p2 x="320" y="460"/>
</wire>
<wire>
<p1 x="180" y="620"/>
<p2 x="220" y="620"/>
</wire>
<wire>
<p1 x="40" y="620"/>
<p2 x="140" y="620"/>
</wire>
<wire>
<p1 x="380" y="560"/>
<p2 x="400" y="560"/>
</wire>
<wire>
<p1 x="400" y="560"/>
<p2 x="460" y="560"/>
</wire>
<wire>
<p1 x="140" y="400"/>
<p2 x="160" y="400"/>
</wire>
<wire>
<p1 x="200" y="400"/>
<p2 x="320" y="400"/>
</wire>
<wire>
<p1 x="280" y="720"/>
<p2 x="320" y="720"/>
</wire>
<wire>
<p1 x="260" y="880"/>
<p2 x="320" y="880"/>
</wire>
<wire>
<p1 x="300" y="660"/>
<p2 x="320" y="660"/>
</wire>
<wire>
<p1 x="200" y="820"/>
<p2 x="320" y="820"/>
</wire>
<wire>
<p1 x="120" y="440"/>
<p2 x="280" y="440"/>
</wire>
<wire>
<p1 x="280" y="440"/>
<p2 x="320" y="440"/>
</wire>
<wire>
<p1 x="180" y="600"/>
<p2 x="220" y="600"/>
</wire>
<wire>
<p1 x="260" y="600"/>
<p2 x="320" y="600"/>
</wire>
<wire>
<p1 x="140" y="380"/>
<p2 x="300" y="380"/>
</wire>
<wire>
<p1 x="40" y="380"/>
<p2 x="120" y="380"/>
</wire>
<wire>
<p1 x="300" y="380"/>
<p2 x="320" y="380"/>
</wire>
<wire>
<p1 x="380" y="700"/>
<p2 x="400" y="700"/>
</wire>
<wire>
<p1 x="220" y="540"/>
<p2 x="320" y="540"/>
</wire>
<wire>
<p1 x="280" y="860"/>
<p2 x="320" y="860"/>
</wire>
<wire>
<p1 x="400" y="420"/>
<p2 x="400" y="560"/>
</wire>
<wire>
<p1 x="400" y="560"/>
<p2 x="400" y="700"/>
</wire>
<wire>
<p1 x="400" y="700"/>
<p2 x="400" y="840"/>
</wire>
<wire>
<p1 x="160" y="400"/>
<p2 x="160" y="580"/>
</wire>
<wire>
<p1 x="260" y="460"/>
<p2 x="260" y="600"/>
</wire>
<wire>
<p1 x="260" y="600"/>
<p2 x="260" y="740"/>
</wire>
<wire>
<p1 x="260" y="740"/>
<p2 x="260" y="880"/>
</wire>
<wire>
<p1 x="200" y="400"/>
<p2 x="200" y="580"/>
</wire>
<wire>
<p1 x="200" y="640"/>
<p2 x="200" y="820"/>
</wire>
<wire>
<p1 x="280" y="440"/>
<p2 x="280" y="580"/>
</wire>
<wire>
<p1 x="280" y="580"/>
<p2 x="280" y="720"/>
</wire>
<wire>
<p1 x="280" y="720"/>
<p2 x="280" y="860"/>
</wire>
<wire>
<p1 x="220" y="540"/>
<p2 x="220" y="600"/>
</wire>
<wire>
<p1 x="220" y="620"/>
<p2 x="220" y="680"/>
</wire>
<wire>
<p1 x="300" y="380"/>
<p2 x="300" y="520"/>
</wire>
<wire>
<p1 x="300" y="520"/>
<p2 x="300" y="660"/>
</wire>
<wire>
<p1 x="300" y="660"/>
<p2 x="300" y="800"/>
</wire>
</wires>
</circuit>