Forum: FPGA, VHDL & Co. Frage zum Coding Style eines normalen RAMs mit Initialisierung


von Michael F. (mifi)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich versuche immer noch die LM32-CPU auf einem Altera FPGA zu portieren
wo auch das Debugging mit dem JTAG später möglich sein soll.

Im original Source wird z.B. ein Monitor RAM (lm32_monitor_ram.v) 
erwendet:
1
lm32_monitor_ram ram (
2
    // ----- Inputs -------
3
    .ClockA             (clk_i),
4
    .ClockB             (clk_i),
5
    .ResetA             (rst_i),
6
    .ResetB             (rst_i),
7
    .ClockEnA           (`TRUE),
8
    .ClockEnB           (`FALSE),
9
    .AddressA           (MON_ADR_I[10:2]),
10
    .AddressB           (9'b0),
11
    .DataInA            (write_data),
12
    .DataInB            (32'b0),
13
    .WrA                (write_enable),
14
    .WrB                (`FALSE),
15
    // ----- Outputs -------
16
    .QA                 (data),
17
    .QB                 (dataB)
18
    );

Weiterhin sind die Parameter wie folgt gesetzt:

CSDECODE_B   = "0b000" ;
CSDECODE_A   = "0b000" ;
WRITEMODE_B  = "NORMAL" ;
WRITEMODE_A  = "NORMAL" ;
GSR          = "ENABLED" ;
RESETMODE    = "SYNC" ;
REGMODE_B    = "NOREG" ;
REGMODE_A    = "NOREG" ;
DATA_WIDTH_B = 9 ;
DATA_WIDTH_A = 9 ;

Intern wird dies auf ein DP8KC Primitive abgebildet, 8K True Dual Port 
Block RAM. Für mich sieht das jetzt aber so aus als wenn hier die Dual
Port Funktion nicht verwendet wird, sondern nur ein einfaches RAM, kann
das sein?

Bei den Altera Beispielen habe ich die Möglichkeit
"Old Data Read-During-Write Behavior" oder
"New Data Read-During-Write Behavior" zu verwenden.

Old Data Read-During-Write Behavior
1
module single_clk_ram(
2
   output reg [7:0] q,
3
   input [7:0] d,
4
   input [6:0] write_address, read_address,
5
   input we, clk
6
);
7
8
reg [7:0] mem [127:0];
9
always @ (posedge clk) begin
10
   if (we)
11
      mem[write_address] <= d;
12
   q <= mem[read_address]; // q doesn't get d in this clock cycle
13
end
14
15
endmodule

New Data Read-During-Write Behavior
1
module single_clock_wr_ram(
2
   output reg [7:0] q,
3
   input [7:0] d,
4
   input [6:0] write_address, read_address,
5
   input we, clk
6
);
7
8
reg [7:0] mem [127:0];
9
always @ (posedge clk) begin
10
   if (we)
11
      mem[write_address] = d;
12
   q = mem[read_address]; // q does get d in this clock cycle if
13
                          // we is high
14
end
15
16
endmodule

Was ist hier nun die richtige Version?
Und das andere Problem, wie kann man das RAM vorher mit Daten 
initialisieren (siehe Anhang original lm32_monitor_ram)?

Viele Grüße,
Michael

von Michael F. (mifi)


Lesenswert?

Hallo,

habe die Lösung gefunden.
Im Projekt "https://github.com/m-labs/lm32"; gibt es die Datei
"lm32_dp_ram.v" welche das Dual Port RAM entsprechend umsetzt.

Gruß,
Michael

von Daniel (Gast)


Lesenswert?

Michael Fischer schrieb:
> Für mich sieht das jetzt aber so aus als wenn hier die Dual
> Port Funktion nicht verwendet wird, sondern nur ein einfaches RAM, kann
> das sein?
Ja. Der Port B wird hier nicht verwendet.

> Was ist hier nun die richtige Version?
http://www.latticesemi.com/~/media/Documents/UserManuals/EI/FPGALibrariesReferenceGuide31.pdf
Auf Seite 192 unten, sieht man die Möglichkeiten für WRITEMODE. Im 
Orignal wird "NORMAL" verwendet. Es gibt noch "WRITETHROUGH" und 
"READBEFORE". Dazu hast Du ja die Pendants für Altera schon gefunden.
Mir ist hier auch nicht klar, welches Verhalten für Lattice 'normal' 
ist.

Dieser Punkt spielt aber nur eine Rolle, wenn man auf einer Adresse 
gleichzeitig schreibt und liest. Dieser Fall ist mir bisher noch nicht 
begegnet.

Die dritte Frage hat sich ja schon erledigt.

Daniel

von Lattice User (Gast)


Lesenswert?

Daniel schrieb:

> Mir ist hier auch nicht klar, welches Verhalten für Lattice 'normal'
> ist.
>

Aus dem ECP3 Handbuch:

In NORMAL mode, the output data does not change or get updated, during 
the write operation. This mode is supported for all data widths.

In WRITETHROUGH mode, the output data is updated with the input data 
during the write cycle. This mode is supported for all data widths.

In READBEFOREWRITE mode, the output data port is updated with the 
existing data stored in the write address, during a write cycle. This 
mode is supported for x9, x18 and x36 data widths.

von Daniel (Gast)


Lesenswert?

Danke für die Aufklärung!

von Michael F. (mifi)


Lesenswert?

Hallo,

Danke für die Info.

Was mir noch gefehlt hat war das lm32_monitor.mem File. Irgendwie habe
ich nicht verstanden wie ich das aus dem lm32_monitor_ram.v extrahieren
oder wieder herstellen kann.

Also habe ich es mal anderes versucht, und den Bereich 0x0 - 0x800 von
einem Lattice Evalboard ausgelesen. Dies wurde jetzt als
lm32_monitor.mem verwendet. Es sieht so aus als würde es immer noch
beim Original funktionieren. Mich wundert es aber schon etwas das der
ausgelesene Bereich fast voll ist. In der original Datei 
lm32_monitor_ram.v sieht es aber nicht so aus.

Gruß,
Michael

von Daniel (Gast)


Lesenswert?

Michael Fischer schrieb:
> Mich wundert es aber schon etwas das der
> ausgelesene Bereich fast voll ist.
Womit voll? Mit 0xFF?

Daniel

von Lattice User (Gast)


Lesenswert?

Michael Fischer schrieb:
> Hallo,
>
> Danke für die Info.
>
> Was mir noch gefehlt hat war das lm32_monitor.mem File. Irgendwie habe
> ich nicht verstanden wie ich das aus dem lm32_monitor_ram.v extrahieren
> oder wieder herstellen kann.

Ist auch nicht einfach, da das Mapping vom INIT_VAL zu den einzelnen 
Bits im RAM in den verschiedenen Konfigurationen nicht dokumentiert ist, 
zumindesten habe eine Docu besiher nicht gefunden :-(

von Michael F. (mifi)


Angehängte Dateien:

Lesenswert?

Hallo Daniel,

nicht mit 0xFF, schau mal in den Anhang.

Gruß,
Michael

von Daniel (Gast)


Lesenswert?

Michael Fischer schrieb:
> lm32_monitor.mem
Das sind 512 * 4 Byte = 2048 Byte

In lm32_monitor_ram.v sind Varianten für alle Lattice-Chips drin.
Wenn man sich z.B. auf den MachXO2 beschränkt, sieht man das da
12 Zeilen á 40 Byte +
 1 Zeile mit 22 Byte
und das ganze 4 Mal gefüllt sind: (12 * 40 + 22) * 4 = 2008 Byte

stimmt also ganz gut überein (da sind ja auch ein paar Nullen am Ende).

Interessant wäre der .asm oder .c-Quelltext, um sich das mem-File selbst 
zu erzeugen bzw. um Anpassungen vornehmen zu können.

Daniel

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.