Ich habe eine Entität, die einen Array-Typ wie folgt hat:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
Entity LCD_Memory is
port (CLK, Reset, WR : IN std_logic;
I : IN std_logic_vector(7 Downto 0);
Addr : IN std_logic_vector(7 Downto 0);
O : OUT std_logic_vector(7 Downto 0));
End LCD_Memory;
Architecture Behavier of LCD_Memory is
Type LCD_Memory_Array is Array(1 to 200) of std_logic_vector(7 Downto 0);
Signal LCDMem : LCD_Memory_Array :=
("01010000", "01010010", "01001111", "01000111", "01010010", "01000001", "01001101", "00100000", -- Line_PK - 1
"10110000", "00100000", "01001011", "01000101", "01011001", "00100000", "00111010", "00100000", -- Line_PK - 9
"01000101", "01001110", "01010100", "01000101", "01010010", "00100000", "01010010", "01010101", -- Line_GM - 17
"01001110", "00100000", "01001101", "01001111", "01000100", "01000101", "00100000", "00111010", -- Line_GM - 25
"01000101", "01001110", "01010100", "01000101", "01010010", "00100000", "01010010", "01010101", -- Line_GD - 33
"01001110", "00100000", "01000100", "01000101", "01001100", "01000001", "01011001", "00111010", -- Line_GD - 41
"01010010", "01010101", "01001110", "10110000", "01000100", "00100000", "00100000", "00100000", -- Line_RD - 49
"01010010", "01010101", "01001110", "10110000", "01001110", "00100000", "00100000", "00100000", -- Line_RN - 57
"01000100", "01001111", "01001110", "01000101", "00100000", "00100000", "00100000", "00100000", -- Line_DN - 65
"01001101", "01000101", "01001101", "01001111", "01010010", "01011001", "00100000", "00111010", -- Line_Mem - 73
"01000001", "01000011", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_AC - 81
"01000100", "01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_DR - 89
"01001001", "01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_IR - 97
"01010100", "01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_TR - 105
"01000001", "01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_AR - 113
"01001001", "01001110", "01010000", "01010010", "00100000", "00111010", "00100000", "00100000", -- Line_INPR - 121
"01001111", "01010101", "01010100", "01010010", "00100000", "00111010", "00100000", "00100000", -- Line_OUTR - 129
"01001001", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", "00100000", -- Line_I - 137
"01010011", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", "00100000", -- Line_S - 145
"01000101", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", "00100000", -- Line_E - 153
"01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", "00100000", -- Line_R - 161
"01001001", "01000101", "01001110", "00100000", "00111010", "00100000", "00100000", "00100000", -- Line_IEN - 169
"01000110", "01000111", "01001001", "00100000", "00111010", "00100000", "00100000", "00100000", -- Line_FGI - 177
"01000110", "01000111", "01001111", "00100000", "00111010", "00100000", "00100000", "00100000", -- Line_FGO - 185
"00100000", "00100000", "00100000", "00100000", "00100000", "00100000", "00100000", "00100000"); -- Null_1 - 193
-- "00100000", "00100000", "00100000", "00100000", "00100000", "00100000", "00100000", "00100000"); -- Null_2 - 201
attribute ram_style : string;
attribute ram_style of LCDMem : signal is "block";
begin
Process(CLK)
begin
if (CLK'Event and CLK = '1') then
if Reset = '0' then
if WR = '1' then
LCDMem(conv_integer(Addr)) <= I;
O <= I;
else
O <= LCDMem(conv_integer(Addr));
end if;
end if;
end if;
end Process;
end Behavier;
Ich möchte dieses Array in ein Block-RAM einfügen, um die verwendeten LUTs zu reduzieren, aber wenn ich diesen Code synthetisiere, kann XST kein Block-RAM ableiten und zeigt diese Warnung an:
INFO:Xst - HDL ADVISOR - Ein Block-RAM für Signal kann nicht extrahiert werden. Die Lese-/Schreibsynchronisierung scheint READ_FIRST zu sein und ist für die ausgewählte Familie nicht verfügbar. Stattdessen wird normalerweise ein verteiltes RAM erstellt. Um Block-RAM-Ressourcen zu nutzen, sollten Sie Ihre RAM-Synchronisierung erneut überprüfen oder verfügbare Gerätefamilien überprüfen.
Aber dieser Code ist im Write-First-Modus !. Ich habe einen anderen Speicher, der genau so ist, und XST hat einen Block-Ram dafür extrahiert.
Dieser RAM sollte schreibgeschützt sein (wie ein ROM), also habe ich Reset-, WR- und I-Signale auf '0' abgebildet. Ist es der Grund?
Ich verwende den XIlinx Spartan 2 XC2S50 FPGA-Chip, er unterstützt den Write-First-Modus für Block-Rams. Welche Änderungen sollte ich an meinem Unternehmen vornehmen, um Arbeit zu bekommen?
Bearbeiten :
Wenn ich diese Entität als Top-Modul einstelle, implementiert XST sie als Block-Ram. Ich denke, es gibt kein Problem in der Entität, das Problem ist, dass Reset
, WR
, und I
auf '0' abgebildet werden, jetzt ist die Frage, wie man ein Block-RAM als Block-ROM im Write-First-Modus verwendet?
Vielleicht so etwas:
Process(CLK)
begin
if (CLK'Event and CLK = '1') then
O <= LCDMem(conv_integer(Addr));
if WR = '1' then
LCDMem(conv_integer(Addr)) <= I;
end if;
end if;
end if;
end Process;
Ich habe meine Entität in diese geändert:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
Entity LCD_Memory is
port (CLK : IN std_logic;
Addr : IN std_logic_vector(7 Downto 0);
O : OUT std_logic_vector(7 Downto 0));
End LCD_Memory;
Architecture Behavier of LCD_Memory is
Type LCD_Memory_Array is Array(1 to 200) of std_logic_vector(7 Downto 0);
Constant LCDMem : LCD_Memory_Array :=
("01010000", "01010010", "01001111", "01000111", "01010010", "01000001", "01001101", "00100000", -- Line_PK - 1
"10110000", "00100000", "01001011", "01000101", "01011001", "00100000", "00111010", "00100000", -- Line_PK - 9
"01000101", "01001110", "01010100", "01000101", "01010010", "00100000", "01010010", "01010101", -- Line_GM - 17
"01001110", "00100000", "01001101", "01001111", "01000100", "01000101", "00100000", "00111010", -- Line_GM - 25
"01000101", "01001110", "01010100", "01000101", "01010010", "00100000", "01010010", "01010101", -- Line_GD - 33
"01001110", "00100000", "01000100", "01000101", "01001100", "01000001", "01011001", "00111010", -- Line_GD - 41
"01010010", "01010101", "01001110", "10110000", "01000100", "00100000", "00100000", "00100000", -- Line_RD - 49
"01010010", "01010101", "01001110", "10110000", "01001110", "00100000", "00100000", "00100000", -- Line_RN - 57
"01000100", "01001111", "01001110", "01000101", "00100000", "00100000", "00100000", "00100000", -- Line_DN - 65
"01001101", "01000101", "01001101", "01001111", "01010010", "01011001", "00100000", "00111010", -- Line_Mem - 73
"01000001", "01000011", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_AC - 81
"01000100", "01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_DR - 89
"01001001", "01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_IR - 97
"01010100", "01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_TR - 105
"01000001", "01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", -- Line_AR - 113
"01001001", "01001110", "01010000", "01010010", "00100000", "00111010", "00100000", "00100000", -- Line_INPR - 121
"01001111", "01010101", "01010100", "01010010", "00100000", "00111010", "00100000", "00100000", -- Line_OUTR - 129
"01001001", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", "00100000", -- Line_I - 137
"01010011", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", "00100000", -- Line_S - 145
"01000101", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", "00100000", -- Line_E - 153
"01010010", "00100000", "00111010", "00100000", "00100000", "00100000", "00100000", "00100000", -- Line_R - 161
"01001001", "01000101", "01001110", "00100000", "00111010", "00100000", "00100000", "00100000", -- Line_IEN - 169
"01000110", "01000111", "01001001", "00100000", "00111010", "00100000", "00100000", "00100000", -- Line_FGI - 177
"01000110", "01000111", "01001111", "00100000", "00111010", "00100000", "00100000", "00100000", -- Line_FGO - 185
"00100000", "00100000", "00100000", "00100000", "00100000", "00100000", "00100000", "00100000"); -- Null_1 - 193
-- "00100000", "00100000", "00100000", "00100000", "00100000", "00100000", "00100000", "00100000"); -- Null_2 - 201
-- attribute rom_style : string;
-- attribute rom_style of LCDMem : signal is "block";
begin
Process(CLK)
begin
if (CLK'Event and CLK = '1') then
O <= LCDMem(conv_integer(Addr));
end if;
end Process;
end Behavier;
Jetzt implementiert XST es als Read-Only Block RAM. vielleicht nützlich für jemanden ...
Sie sollten niemals Resets für RAM verwenden. Denken Sie daran, dass dies in der Hardware hinterlegt ist. Wenn Sie also ein Reset-Signal verwenden, um die Ausgabe des Speichers zu steuern, ist dieses Verhalten nicht explizit für den BRAM-Block definiert. Wenn Sie etwas rund um den BRAM-Block zurücksetzen möchten, sollten es seine Ausgangsregister sein. Was also getan werden muss, ist, die getakteten gelesenen RAM-Daten zu nehmen und sie in einem zusätzlichen Register zu speichern, das synchron zurückgesetzt werden kann. Aktives High wird bevorzugt. Ich würde dringend vorschlagen, einen zusätzlichen Registrierungsprozess hinzuzufügen, der Folgendes umfasst:
O_reg <= O;
in einem getakteten Prozess mit Sync-Reset. Dies wird Ausgaberegs in Ihrem Speicher ableiten und bei der Platzierung helfen/das Timing verbessern.
Sie hätten auch eine BRAM-IP verwenden und das Array in eine Koeffizientendatei einfügen können, die in das BRAM eingefügt wird.
Brian Carlton
Benutzer154136
en
) anstelle von versuchenReset
.Mahmud_Mehri
Mahmud_Mehri