Hallo, ich versuche folgende Gleichung in VHDL umzusetzen: Y = (X1 - X2 - X3 + X4) / 2 ; Dabei sind X1 - X4 Signale vom Typ std_logic_vector(31 downto 0). Mein Problem ist, dass X1 - X4 sehr groß werden können (also 0xFFFFFFFF) oder eben sehr klein (also 0x00000000). Y soll am Ende auch ein std_logic_vector(31 downto 0) werden. Wenn es einen Überlauf gibt, dann soll Y = 0xFFFFFFFF ergeben. Desweiteren soll es ein Vorzeichen Signal geben (prefix), das mir Anzeigt, ob der Wert Y positiv oder negativ ist. Mein (recht kläglicher) Versuch war folgender: entity test is port( clk : in std_logic; rst_n : in std_logic; -- ... X1 : in std_logic_vector(31 downto 0); X2 : in std_logic_vector(31 downto 0); X3 : in std_logic_vector(31 downto 0); X4 : in std_logic_vector(31 downto 0); -- ... Y : out std_logic_vector(31 downto 0); prefix : out std_logic -- ... ); end entity test; architecture stb of test signal s_Y_signed : signed(31 downto 0); signal s_X1 : std_logic_vector(31 downto 0); signal s_X2 : std_logic_vector(31 downto 0); signal s_X3 : std_logic_vector(31 downto 0); signal s_X4 : std_logic_vector(31 downto 0); -- ... begin -- ... s_Y_signed <= conv_signed((( conv_integer(s_X1) - conv_integer(s_X2) - conv_integer(s_X3) + conv_integer(s_X4)) / 2), s_Y_signed'length); Y <= conv_std_logic_vector( s_Y_signed, Y'length); prefix <= s_Y_signed(s_Y_signed'high); -- ... test_proc : process (clk, rst_n) begin if (rst_n = '0') then s_X1 <= (others => '0'); s_X2 <= (others => '0'); s_X3 <= (others => '0'); s_X4 <= (others => '0'); -- ... elsif (clk'event and clk = '1') then s_X1 <= X1; s_X2 <= X2; s_X3 <= X3; s_X4 <= X4; -- ... end if; end process test_proc -- ... end architecture stb; Das mit dem Überlauf fehlt hier noch komplett, da ich mir noch nicht ganz klar darüber geworden bin wie ich das am Besten detektieren könnte. Der abgetaktete Prozess schaut hier etwas klein aus, in der Oringalfassung ist er deutlich größer. Ich hab jetzt nur die wichtigen Zuweisungen gelassen. Ich hoffe jemand kann mir helfen mein Problem zu lösen. Vll. bin ich auch mit diesem Ansatz komplett auf dem Holzweg und jemand anderes kann mir einen neuen Denkanstoß in eine andere Richtung geben. Gruß, Stahlkopf
Nur für unsigned Additionen gesprochen erst mal. Ein Überlauf sollte doch so festzustellen sein, daß intern die Register ein Bit breiter gemacht werden als das Ergebnis breit ist. Überlauf ist dann einfach das zusätzliche Bit was gesetzt ist. Zur Vorzeichen Betrachtung mag ich mich nicht äußern, aber sollte grundsätzlich auch keinen Unterschied machen.
Verwende ersteinmal die richtigen Bibliotheken: Siehe Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete" Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete" Duke
Hallo,
danke Panko für deine Hilfe. Du meinst dann, dass das Überlaufproblem
dann so behoben werden kann:
signal s_Y_signed : signed(32 downto 0);
if (s_Y_signed(s_Y_signed'high - 1) = '0') then
-- no overflow
Y <= conv_std_logic_vector( s_Y_signed, Y'length);
else
-- overflow
Y <= (others => '1');
end if;
In dem Fall würde ich dann die Zuweisungen für Y und prefix in den
Process mit hineinziehen. Der würde dann anschließend so ausschauen:
test_proc : process (clk, rst_n)
begin
if (rst_n = '0') then
s_X1 <= (others => '0');
s_X2 <= (others => '0');
s_X3 <= (others => '0');
s_X4 <= (others => '0');
-- ...
Y <= (others => '0');
prefix <= '0';
-- ...
elsif (clk'event and clk = '1') then
s_X1 <= X1;
s_X2 <= X2;
s_X3 <= X3;
s_X4 <= X4;
-- ...
if (s_Y_signed(s_Y_signed'high - 1) = '0') then
-- no overflow
Y <= conv_std_logic_vector( s_Y_signed, Y'length);
else
-- overflow
Y <= (others => '1');
end if;
prefix <= s_Y_signed(s_Y_signed'high);
-- ...
end if;
end process test_proc
Auch Dankeschön Duke für den Link. Mit den Bibliotheken hab ich mich
auch schonmal rumgeärgert. Und die Problematik std_logic_arith und
numeric_std ist mir bekannt. Allerdings hab ich nicht das passende
Pendant für meine Konvertierungen in numeric_std gefunden. Wenn ich z.B.
to_integer verwende, bekomm ich beim kompilieren den Fehler zurück, dass
er das Subprogramm nicht kennt. Aus dem Grund bin ich dann am Ende doch
bei std_logic_arith gelandet (was natürlich jetzt einen Fehler bedeuten
könnte).
Kannst du mir da evtl. helfen und die richtigen Konvertierungstypen für
die numeric_std Library sagen (ich hab den krähenden Vogel (Goggel)
schon bemüht, allerdings ohne Erfolg)?
Gruß,
Stahlkopf
Stahlkopf schrieb: > Kannst du mir da evtl. helfen und die richtigen Konvertierungstypen für > die numeric_std Library sagen Lothar hat da was schönes zusammengestellt: http://www.lothar-miller.de/s9y/archives/14-Numeric_Std.html Duke
Hallo,
danke nochmal für den Link. Der ist Gold wert!!! Damit haben sich
endlich mal ein paar Fragezeichen zu den Bibliotheken aufgelöst.
Ich habe jetzt also die Umrechnung wie folgt gemacht:
entity test is
port(
clk : in std_logic;
rst_n : in std_logic;
-- ...
X1 : in std_logic_vector(31 downto 0);
X2 : in std_logic_vector(31 downto 0);
X3 : in std_logic_vector(31 downto 0);
X4 : in std_logic_vector(31 downto 0);
-- ...
Y : out std_logic_vector(31 downto 0);
prefix : out std_logic
-- ...
);
end entity test;
architecture stb of test
signal s_Y_signed_ext : signed(32 downto 0);
signal s_Y_signed : signed(31 downto 0);
signal s_X1 : std_logic_vector(31 downto 0);
signal s_X2 : std_logic_vector(31 downto 0);
signal s_X3 : std_logic_vector(31 downto 0);
signal s_X4 : std_logic_vector(31 downto 0);
-- ...
begin
-- ...
s_Y_signed_ext <= to_signed((( to_integer(unsigned(s_X1)) -
to_integer(unsigned(s_X2)) -
to_integer(unsigned(s_X3)) +
to_integer(unsigned(s_X4))) / 2),
s_Y_signed_ext'length);
s_Y_signed <= s_Y_signed_ext(s_Y_signed_ext'high) &
s_Y_signed_ext(30 downto 0);
-- ...
test_proc : process (clk, rst_n)
begin
if (rst_n = '0') then
s_X1 <= (others => '0');
s_X2 <= (others => '0');
s_X3 <= (others => '0');
s_X4 <= (others => '0');
-- ...
Y <= (others => '0');
prefix <= '0';
elsif (clk'event and clk = '1') then
s_X1 <= X1;
s_X2 <= X2;
s_X3 <= X3;
s_X4 <= X4;
-- ...
if (s_Y_signed_ext(s_Y_signed_ext'high - 1) = '0') then
-- no overflow
Y <= std_logic_vector(
to_unsigned(to_integer(s_Y_signed), Y'length));
else
-- overflow
Y <= (others => '1');
end if;
prefix <= s_Y_signed(s_Y_signed'high);
end if;
end process test_proc
-- ...
end architecture stb;
So weit, so gut. Kompilieren funktioniert ohne Probleme. Wenn ich das
jetzt allerdings simuliere, erhalte ich in Modelsim die Fehlermeldung
(und das obwohl er anscheinend alles durch simuliert und nicht
abbricht):
Error: (vsim-86) numstd_conv_unsigned_nu: NATURAL arg value is negative
(-8947848)
Ich geh davon aus, dass mit der Konvertierung etwas nicht ganz passt.
Vermutlich werden irgendwo Werte übergeben, die außerhalb der Reichweite
des Datentyps sind. Allerdings seh ich nicht, an welcher Stelle das
passiert.
Any Idea? Nochmals danke für eure Hilfe!
Gruß,
Stahlkopf
Edit: Fürs bessere Verständnis der Fehlermeldung, hier die eingestellten Werte: X0: 0x00000000 X1: 0x01111111 X2: 0x00000000 X3: 0x00000000 Damit ist das Ergebnis der Rechnung negativ. Aber das sollte ja schließlich mit signed möglich sein...
Stahlkopf schrieb: > Edit: > Fürs bessere Verständnis der Fehlermeldung, hier die eingestellten > Werte: > > X0: 0x00000000 > X1: 0x01111111 > X2: 0x00000000 > X3: 0x00000000 Das ist natürlich vollkommener Blödsinn. Ich bin da um eine Stelle verrutscht. Richtig wäre: X1: 0x00000000 X2: 0x01111111 X3: 0x00000000 X4: 0x00000000 Gruß, Stahlkopf
BTW, Du kannst auch direkt mit signed und unsigned rechnen.
Wenn Du bis zu auf integer konvertierst, dürften die meisten Systeme nur
mit 32 Bit (signed) rechnen.
Duke
P.S.:
Für sowas:
s_Y_signed <= s_Y_signed_ext(s_Y_signed_ext'high) &
s_Y_signed_ext(30 downto 0);
gibt es resize...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.