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.