Forum: FPGA, VHDL & Co. (vhdl) mod 12 rechnen


von flix (Gast)


Lesenswert?

hallo,
ich möchte in vhdl mod 12 rechnen,
das funktioniert auch wunderbar bei der simulation. Bei der Sythese dagt 
Xilinx ISE dann, dass nur 2^x modulo gerechnet werden kann.
1
signal addr : std_logic vector(5 downto 0);
2
3
name:process (..)
4
variable test :integer;
5
6
begin 
7
..
8
..
9
..
10
   test := CONV_INTEGER(addr) mod 12;

funktioniert so für die siumlation, aber nicht synthese.

Hab es versucht so umzustellen :
1
test := CONV_INTEGER(addr)
2
if test = 12 then 
3
  test := 0;
4
else 
5
 test := test;
6
end if;

tut aber nicht mehr das was es soll ? ... , hab auch noch andere 
Varianten davon probiert zb
1
if addr = "01100" then 
2
test := 0;
3
else 
4
 test := test;
5
end if;

  danke für tipps
  flix

von Falk B. (falk)


Lesenswert?

@ flix

>ich möchte in vhdl mod 12 rechnen,
>das funktioniert auch wunderbar bei der simulation. Bei der Sythese dagt
>Xilinx ISE dann, dass nur 2^x modulo gerechnet werden kann.

Ja, das kann XST nicht synthetisieren.

Man kann das über eine Wertetabelle lösen, die man ggf. clever per 
loop/if oder so zusammenbastelt.

Mfg
Falk

von flix (Gast)


Lesenswert?

aber warum gehen meine zwei vorschläge nicht ? ... weis jemand rat ?
  danke
  flix

von Klaus Falser (Gast)


Lesenswert?

Deine 2 Varianten machen doch keine modulo Operation!

von Gast (Gast)


Lesenswert?

War es ein flüchtigkeitsfehler, oder soll es wirklich
1
test := test;
heißen? Ansonsten würde ich ein
1
test := test + 1;
vorschlagen.

von KlausK (Gast)


Lesenswert?

Die unteren beiden Bits kann man direkt nehmen, dann bleiben nur noch 16 
Fälle, für die man modulo 3 rechnen muss:

case addr(5 downto 2) is
  when "0000" => test := "00" & adr(1 downto 0);
  when "0001" => test := "01" & adr(1 downto 0);
  when "0010" => test := "10" & adr(1 downto 0);
  when "0011" => test := "00" & adr(1 downto 0);
  when "0100" => test := "01" & adr(1 downto 0);
  when "0101" => test := "10" & adr(1 downto 0);
  when "0110" => test := "00" & adr(1 downto 0);
  when "0111" => test := "01" & adr(1 downto 0);
  when "1000" => test := "10" & adr(1 downto 0);
  when "1001" => test := "00" & adr(1 downto 0);
  when "1010" => test := "01" & adr(1 downto 0);
  when "1011" => test := "10" & adr(1 downto 0);
  when "1100" => test := "00" & adr(1 downto 0);
  when "1101" => test := "01" & adr(1 downto 0);
  when "1110" => test := "10" & adr(1 downto 0);
  when "1111" => test := "00" & adr(1 downto 0);
end case;

Geht das auch kürzer zu schreiben? (fragt ein Neuling)

Klaus

von Falk B. (falk)


Lesenswert?

Vielleicht nicht kürzer, aber universeller.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity mod_12 is
7
    Port ( data_in : in std_logic_vector(5 downto 0);
8
           mod_out : out std_logic_vector(3 downto 0));
9
end mod_12;
10
11
architecture Behavioral of mod_12 is
12
13
TYPE type_MOD_12_TABLE IS ARRAY (natural RANGE <>) OF integer range 0 to 63;
14
15
CONSTANT MOD_12_TABLE  : type_MOD_12_TABLE(0 TO 63) :=
16
      ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
17
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
18
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
19
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
20
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
21
        0, 1, 2, 3); 
22
23
signal tmp: integer range 0 to 63;
24
25
begin
26
27
   tmp     <= conv_INTEGER(data_in);
28
   mod_out <= conv_std_logic_vector(MOD_12_TABLE(tmp),6);
29
30
end Behavioral;


MFG
Falk

von Ingmar (Gast)


Lesenswert?

Bei großen Vektorbreiten ist das aber schon eine nicht unerhebliche 
verschwendung. Ginge denn die Standardoperation (Modulo = Ausgangswert - 
Teiler x Ganzzahl (Ausgangswert / Teiler) nicht?

Man könnte es zumindest zweistufig lösen über Teiler 4 und Restklasse 3.

von KlausK (Gast)


Lesenswert?

@Falk: Danke für die Anregung, ich hoffe, dass ich es richtig 
modifiziert habe (wieder kürzer, aber nicht mehr universell).

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity mod_12 is
    Port ( data_in : in std_logic_vector(5 downto 0);
           mod_out : out std_logic_vector(3 downto 0));
end mod_12;

architecture Behavioral of mod_12 is

TYPE type_MOD_3_TABLE IS ARRAY (natural RANGE <>) OF integer range 0 to 
15;

CONSTANT MOD_3_TABLE  : type_MOD_3_TABLE(0 TO 15) :=
      ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0);

signal tmp: integer range 0 to 15;

begin

   tmp     <= conv_INTEGER(data_in(5 downto 2));
   mod_out <= conv_std_logic_vector(MOD_3_TABLE(tmp),4) & data_in(1 
downto 0);

end Behavioral;

Entstehen jetzt Probleme durch die unterschiedliche Behandlung der Bits 
5 bis 2 und 1 bis 0 hinsichtlich Laufzeit?

Klaus

von Falk B. (falk)


Lesenswert?

@ KlausK

>@Falk: Danke für die Anregung, ich hoffe, dass ich es richtig
>modifiziert habe (wieder kürzer, aber nicht mehr universell).

Sieht gut aus.

>Entstehen jetzt Probleme durch die unterschiedliche Behandlung der Bits
>5 bis 2 und 1 bis 0 hinsichtlich Laufzeit?

Nein, wieso? Das is alles rein kombinatorisch. Das läuft locker mit 200 
MHz++.

MfG
Falk

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.