(vhdl) mod 12 rechnen

Gast #547079
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
#547105
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
Gast #547954
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
#548001
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
Gast #548046
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.
Gast #548053
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
#548429
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren