Vhdl'de Mod İşlemi

Başlatan vitruvius, 19 Mayıs 2012, 20:11:15

vitruvius

Merhaba, vhdl'de değişken bir ifadenin mod(N) değerini nasıl alabilirim? Adc'den okuyacağım değerleri basamaklara ayıracaktım ama mod 2'nin kuvveti olmalı diye hata alıyorum.

Yapmak istediğim şey şu:
process(clk)
	begin
		if(clk'event and clk='1') then
		birler<=(sayac mod 10);
		end if;
	end process;


Hata da : Unsupported modulo value 10 found in expression at line 85. The modulo should be a power of 2.

Teşekkür ederim.

yamak

FPGA ile ancak 2 ye veya 2 nin kuvvetlerine bölme işlemi yapılabilir. Eğer bşka sayılara bölme yapmak istersen kendi algoritmanı yazmalısın

speak48

#2
verilogta böyle; quartus sentezlerken kendi bölme algoritmasını kullanıyor.
ama bölmeyi tamamen combinozel lojikle gerçeklediği için uygun bir yöntem değil.daha önce 8clkta bölme yapan devre paylaşmıştım lazımsa bi bak
gördüğüm kadarıyla binary sayıyı desimale çevirmeye çalışıyordun.
eğer bu işlemi c deki gibi 10 a 100 e bölem dersen fpga için uygun bir tasarım olmaz.
eğer sana desimal lazımsa ya işlemleri başta desimalle yapıcan desimal toplayıcıya=>sayaça bak yada binariden desimale çevirme algoritmasına bak add 3 diye bi algoritma vardı "binary 2 bcd" diye arasan bulursun.


//module modal(a,b,c,clk);
//input clk;
//input [7:0] a;
//input [7:0] b;
//output reg [7:0] c;
//
//reg [7:0] x;
//reg [7:0] y;
//
//always@(posedge clk)
//begin
//x<=a;
//y<=b;
//c<= x % y;
//
//end
//endmodule

module modal(a,b,c);

input [7:0] a;
input [7:0] b;
output reg [7:0] c;

always@(a,b)
begin
c<=a%b;
end
endmodule



yamak

Ya da IP kullanabilirsin. ISE de divider generator var onu kullanmıştım daha önce. Aşağıdaki kodlardan örnek alabilirsin.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity font_display_circuit is
    port(
         clk,video_on:in std_logic;
            pixel_x,pixel_y:in std_logic_vector(9 downto 0);
            rect_left_reg_out,rect_top_reg_out:in std_logic_vector(9 downto 0);
            text_rgb:out std_logic_vector(7 downto 0);
            LED:out std_logic_vector(7 downto 0);
            text_on:out std_logic_vector(2 downto 0)
            );
end font_display_circuit;

architecture Behavioral of font_display_circuit is
        
        signal rom_addr:std_logic_vector(10 downto 0);
        signal char_addr,char_addr_l,char_addr_n,char_addr_l2:std_logic_vector(6 downto 0);
        signal row_addr,row_addr_l,row_addr_n,row_addr_l2:std_logic_vector(3 downto 0);
        signal bit_addr,bit_addr_l,bit_addr_n,bit_addr_l2:std_logic_vector(2 downto 0);
        signal font_word:std_logic_vector(7 downto 0);
        signal font_bit,text_bit_on,logo1_on,logo2_on,x_coor_on,coor_on:std_logic;
        signal pix_x,pix_y:std_logic_vector(9 downto 0);
        -----------------------dividing unit-------------------------
        signal ce,rfd:std_logic;
        signal dividend:std_logic_vector(9 downto 0);
        signal divisor: std_logic_vector(9 downto 0);
        signal quotient:std_logic_vector(9 downto 0);
        signal fractional:std_logic_vector(9 downto 0);
        signal dividend_reg,divisor_reg:unsigned(9 downto 0);
        signal quotient_first_x1,quotient_second_x1:unsigned(9 downto 0);
        signal quotient_first_y1,quotient_second_y1:unsigned(9 downto 0);
        signal fractional_first_x1,fractional_second_x1:unsigned(9 downto 0);
        signal fractional_first_y1,fractional_second_y1:unsigned(9 downto 0);
        ---------------------------------------------------------------
        signal rect_coor_x,rect_coor_y:unsigned(9 downto 0);
        signal first_digit_x1,second_digit_x1,third_digit_x1,i:integer:=0;
        signal first_digit_y1,second_digit_y1,third_digit_y1:integer:=0;
        signal first_digit_ascii_x1,second_digit_ascii_x1,third_digit_ascii_x1:std_logic_vector(6 downto 0);
        signal first_digit_ascii_y1,second_digit_ascii_y1,third_digit_ascii_y1:std_logic_vector(6 downto 0);
        component dividing_circuit
                port (
                clk: in std_logic;
                ce: in std_logic;
                rfd: out std_logic;
                dividend: in std_logic_vector(9 downto 0);
                divisor: in std_logic_vector(9 downto 0);
                quotient: out std_logic_vector(9 downto 0);
                fractional: out std_logic_vector(9 downto 0));
        end component;
begin
        font_unit:entity work.font_rom
            port map(clk=>clk,addr=>rom_addr,data=>font_word);
        dividing_unit: dividing_circuit port map (
                            clk => clk,
                            ce => ce,
                            rfd => rfd,
                            dividend => dividend,
                            divisor => divisor,
                            quotient => quotient,
                            fractional => fractional);
        
        pix_x<=pixel_x;
        pix_y<=pixel_y;
        rect_coor_x<=unsigned(rect_left_reg_out+10);
        rect_coor_y<=unsigned(rect_top_reg_out+10);
        logo1_on<='1' when unsigned(pix_y(9 downto 4))=8 and 
                        30<=unsigned(pix_x(9 downto 3)) else
                    '0';
       row_addr_l<=pix_y(3 downto 0);
        bit_addr_l<=pix_x(2 downto 0);

        with pix_x( 9 downto 3) select
            char_addr_l<=
                "1011001" when "0011110",--Y
                "1110101" when "0011111",--u
                "1110011" when "0100000",--s
                "1110101" when "0100001",--u
                "1100110" when "0100010",--f
                "0000000" when "0100011",--space 
                "1011001" when "0100100",--Y
                "1100001" when "0100101",--a
                "1101101" when "0100110",--m
                "1100001" when "0100111",--a
                "1101011" when "0101000",--k
                "0000000" when others;
                
      logo2_on<='1' when unsigned(pix_y(9 downto 4))=7 and 
                        30<=unsigned(pix_x(9 downto 3)) else
                    '0';
       row_addr_l2<=pix_y(3 downto 0);
        bit_addr_l2<=pix_x(2 downto 0);
        rect_coor_x<=unsigned(rect_left_reg_out+10);
        rect_coor_y<=unsigned(rect_top_reg_out+10);
        with pix_x( 9 downto 3) select
            char_addr_l2<=
                "1010110" when "0011110",--V
                "1100111" when "0011111",--g
                "1100001" when "0100000",--a
                "0000000" when "0100001",--space
                "1000100" when "0100010",--D
                "1110010" when "0100011",--r 
                "1101001" when "0100100",--i
                "1110110" when "0100101",--v
                "1100101" when "0100110",--e
                "1110010" when "0100111",--r
                "0000000" when "0101000",--space
                "1010101" when "0101001",--U
                "1111001" when "0101010",--y
                "1100111" when "0101011",--g
                "1110101" when "0101100",--u
                "1101100" when "0101101",--l
                "1100001" when "0101110",--a
                "1101101" when "0101111",--m
                "1100001" when "0110000",--a
                "1110011" when "0110001",--s
                "1101001" when "0110010",--i
                "0000000" when others;
      first_digit_ascii_x1<=std_logic_vector(conv_unsigned((48+first_digit_x1),7));
      second_digit_ascii_x1<=std_logic_vector(conv_unsigned((48+second_digit_x1),7));
      third_digit_ascii_x1<=std_logic_vector(conv_unsigned((48+third_digit_x1),7));
      first_digit_ascii_y1<=std_logic_vector(conv_unsigned((48+first_digit_y1),7));
      second_digit_ascii_y1<=std_logic_vector(conv_unsigned((48+second_digit_y1),7));
      third_digit_ascii_y1<=std_logic_vector(conv_unsigned((48+third_digit_y1),7));
      x_coor_on<='1' when unsigned(pix_y(9 downto 4))=0 and
                                 1<=unsigned(pix_x(9 downto 3)) else
                     '0';
      row_addr_n<=pix_y(3 downto 0);
      bit_addr_n<=pix_x(2 downto 0);
      with pix_x(9 downto 3) select
      char_addr_n<=
      "1001011"  when "0000001",--K
      "1101111"  when "0000010",--o
      "1101111"  when "0000011",--o
      "1110010"  when "0000100",--r
      "1100100"  when "0000101",--d
      "1101001"  when "0000110",--i
      "1101110"  when "0000111",--n
      "1100001"  when "0001000",--a
      "1110100"  when "0001001",--t
      "0101000"  when "0001010",--(
      "0101001"  when "0010010",--) 
      "0101100"  when "0001110",--,	
      first_digit_ascii_x1 when "0001011",
      second_digit_ascii_x1 when "0001100",
      third_digit_ascii_x1 when "0001101",
      first_digit_ascii_y1 when "0001111",
      second_digit_ascii_y1 when "0010000",
      third_digit_ascii_y1 when "0010001",
      "0000000" when others;
      process(pix_x,pix_y,logo1_on,logo1_on,char_addr_l,row_addr_l,bit_addr_l,font_bit,char_addr_l2,row_addr_l2,bit_addr_l2)
      begin
        if logo1_on='1' then
            char_addr<=char_addr_l;
            row_addr<=row_addr_l;
            bit_addr<=bit_addr_l;
            if font_bit='1' then
                text_rgb<="00000101";
            else
                text_rgb<="11000000";
           end if;
        elsif logo2_on='1' then
            char_addr<=char_addr_l2;
            row_addr<=row_addr_l2;
            bit_addr<=bit_addr_l2;
            if font_bit='1' then
                text_rgb<="00000101";
            else
                text_rgb<="11000000";
           end if;
       elsif x_coor_on='1' then
            char_addr<=char_addr_n;
            row_addr<=row_addr_n;
            bit_addr<=bit_addr_n;
            if font_bit='1'  then
                text_rgb<="00000000";
            else
                text_rgb<="11111111";
            end if;
        end if;
     end process;
     ce<='1';
     process(clk)
     variable delay,j:integer;
     begin
        if clk'event and clk='1' then
            i<=i+1;
            if i<40 then --x koordinatının ilk hanesi hesaplanıyor. 
                dividend_reg<=rect_coor_x;
                divisor_reg<=conv_unsigned(100,10);
                quotient_first_x1<=unsigned(quotient);
                fractional_first_x1<=unsigned(fractional);
                dividend<=std_logic_vector(dividend_reg);
                divisor<=std_logic_vector(divisor_reg);
            end if;
            if i>=40 and i<80 then --x koordinatının ikinci ve üçüncü hanesi hesaplanıyo
                dividend_reg<=fractional_first_x1;
                divisor_reg<=conv_unsigned(10,10);
                quotient_second_x1<=unsigned(quotient);
                fractional_second_x1<=unsigned(fractional);
                dividend<=std_logic_vector(dividend_reg);
                divisor<=std_logic_vector(divisor_reg);
            end if;
            if i>=80 and i<120 then --y koordinatının ilk hanesi hesaplanıyo
                dividend_reg<=rect_coor_y;
                divisor_reg<=conv_unsigned(100,10);
                quotient_first_y1<=unsigned(quotient);
                fractional_first_y1<=unsigned(fractional);
                dividend<=std_logic_vector(dividend_reg);
                divisor<=std_logic_vector(divisor_reg);
        end if;
            if i>=120 then --y koordinatının ikinci ve üçüncü hanesi hesaplanıyo
                dividend_reg<=fractional_first_y1;
                divisor_reg<=conv_unsigned(10,10);
                quotient_second_y1<=unsigned(quotient);
                fractional_second_y1<=unsigned(fractional);
                dividend<=std_logic_vector(dividend_reg);
                divisor<=std_logic_vector(divisor_reg);
                if i=160 then
                    i<=0;
                end if;
            end if;
        end if;
    end process;

rom_addr<=char_addr&row_addr;
font_bit<=font_word(conv_integer(unsigned(not bit_addr)));
text_on<=x_coor_on&logo1_on&logo2_on;
first_digit_x1<=conv_integer(quotient_first_x1) when i>=40 and i<80 else 
                first_digit_x1;
second_digit_x1<=conv_integer(quotient_second_x1) when i<40 else
                second_digit_x1;
third_digit_x1<=conv_integer(fractional_second_x1) when i<40 else
                third_digit_x1;
first_digit_y1<=conv_integer(quotient_first_y1) when i>=120 else
                first_digit_y1;
second_digit_y1<=conv_integer(quotient_second_y1) when i<120 and i>=80 else
                second_digit_y1;
third_digit_y1<=conv_integer(fractional_second_y1) when i<120 and i>=80 else
                third_digit_y1;
end Behavioral;

kralsam

Merhabalar,
Bence yakın modları kullanarak yorum yapabilirsin. Örneğin mod 5 alabilmek için mod4 e bakıp yorum yapabilirsin. mod 10 içinde 8 kullanılabilir geldi bana..
Kolay gelsin.

vitruvius

Cevaplarınız için teşekkürler. Kendi algoritmamı nasıl yazabilirim? Yani mod alma işlemi nasıl gerçekleşiyor?

speak48

mod alma aslında bir bölme işlemidir.
integer ve binaryde işlem yaptığımızdan bölme işleminin iki sonucu vardı biri bölüm diğeride kalan.
kalan kısmı mod alma işlemine denk gelir.
işaretsiz binaride bölme işleminin nasıl yapılacağını lojik devreler yada mikroişlemciler dersinde görmüş olman lazım.
ama senin işini binary2bcd algoritması işini görecektir.

vitruvius

Hocam benim buradaki hedefim adc'den okuyacağım değeri lcd ekranda yazdırmak. Lcd ekrana veriyi karakter karakter yollayabileceğimden aldığım değeri basamaklarına ayırmam lazım diye düşündüm. Bcd sayıya çevirmek ile ne kazanacağım? Yani onu da basamaklarına ayırmam gerekmez mi?

ISE'nin IP'sini hiç anlamadım. Şöyle bir şey yapılamaz mı? Mod(10) için konuşuyorum. Sayıdan sürekli 10 çıkartarak bir if ile de sonucun 10'dan küçük olduğu andaki en son kalan ifadeyi alamaz mıyım? Uygun bir tasarım olmaz mı?

speak48

dediğimi hiç araştımamışsın binary2bcd nin sonucunda sayı desimale 4 bitlik bcd halinde basamaklarına ayrılmış olur.
zaten bölmenin iki yolu vardır.
1 sürekli çıkararak bu en kötü yöntemdir hem fpga hem cpu için.sekiz bitte 255/10 işlemi için 25 kere 10 çıkarcak 25 clk yapar.
2 kaydır çıkar bu en idealidir 8 bit için toplam 8 clkta işlemi tamamlar.

ama binary2bcd de 255 yani 11111111 girer 1001010101 çıkar (10)(0101)(0101) => (2)(5)(5) basamaklarına ayrılmış olur.


vitruvius

Teşekkür ederim hocam. Araştıracak pek vaktim olmamıştı bugün itibariyle bütün vaktimi bu işe ayıracağım.