Bagaimana cara mengubah bilangan bulat besar menjadi bilangan bulat kecil di vhdl?

Saya memiliki kode VHDL tempat saya mencoba mengalikan nilai piksel. Saya memiliki entitas berikut:

entity xGradient is

port(
    clk : in std_logic;
    x11, x12, x13, x21, x22, x23, x31, x32, x33 : in integer range 0 to 255;
    gradientInX : out integer range 0 to 255
);

end xGradient;

Saya melakukan operasi berikut pada ini:

gradientInX <= x11 + 2*x21 + x31 - x13 - 2*x23 - x33;

Masalah yang mungkin Anda perhatikan adalah bahwa nilai yang diperoleh dari operasi melebihi kisaran nilai yang mungkin dari bilangan bulat keluaran saya. Simulasi saya macet ketika ini terjadi. Saya tidak tahu kata yang tepat untuk apa yang saya coba lakukan dan oleh karena itu sepertinya saya tidak tahu cara memperbaiki masalah ini dan ini membuat saya gila. Saya pada dasarnya hanya ingin memotong, atau mengurangi ukuran keluaran untuk memastikannya cocok dengan port keluaran gradienInX. Saya mencoba menggunakan blok proses seperti ini:

-- declared signals
signal gradientMem: integer;

--beginning of my architecture
begin 

SobelOperator : process(gradientMem)

begin
    gradientMem <= x11 + 2*x21 + x31 - x13 - 2*x23 - x33;

    if (gradientMem > 255) then
        gradientMem <= 255;
    elsif (gradientMem < 0) then
        gradientMem <= 0;
    end if;

end process SobelOperator;

lalu menugaskan gradienMem ke gradienInX tetapi tidak berhasil karena beberapa alasan. Bantuan apapun akan sangat dihargai. Catatan: Saya belum memasukkan semua kode VHDL karena saya pikir kodenya akan terlalu panjang. Pesan kesalahan yang saya dapatkan adalah sinyal yang dihasilkan nilai operasinya berada di luar jangkauan (karena nilai yang dihasilkan negatif dan keluarannya hanya berkisar 0 hingga 255).

Matius


person Omnomnious    schedule 09.04.2017    source sumber
comment
Pertanyaan Anda melewatkan dua bagian penting: 1) Deklarasi gradientMen dan 2) pesan kesalahan. VHDL memeriksa batas jangkauan pada tugas. Anda ingin membuat aritmatika saturasi. Jadi tentukan gradientMem dengan rentang yang lebih besar.   -  person Paebbels    schedule 09.04.2017
comment
Saya baru saja mengeditnya untuk memasukkannya. Saya kira masalah utama saya adalah daftar sensitivitas yang tidak benar. Saya juga bertanya-tanya apakah VHDL memiliki operasi spesifik bilangan bulat yang memaksa hasil ke kisaran tertentu tetapi saya kira tidak ada fungsi atau operasi seperti itu jadi saya hanya perlu mengimplementasikannya sendiri. Apa pun yang terjadi, sepertinya masalah saya sudah teratasi. Terima kasih atas tanggapan Anda dan jangan ragu untuk menambahkan hal lain.   -  person Omnomnious    schedule 09.04.2017


Jawaban (3)


Ini adalah salah satu dari sedikit situasi di mana Anda harus menggunakan variabel dan bukan sinyal.

SobelOperator : process(x11, x21, x31, x13, x23, x33)
    variable gradientMem : integer;
begin
    gradientMem := x11 + 2*x21 + x31 - x13 - 2*x23 - x33;

    if (gradientMem > 255) then
        gradientMem := 255;
    elsif (gradientMem < 0) then
        gradientMem := 0;
    end if;
    gradientInX <= gradientMem;
end process SobelOperator;

Omong-omong, operasi ini disebut kliping.

Jika Anda ingin memotong, prosesnya harus ditulis seperti:

SobelOperator : process(x11, x21, x31, x13, x23, x33)
    variable gradientMem : integer;
begin
    gradientMem := x11 + 2*x21 + x31 - x13 - 2*x23 - x33;

    gradientInX <= gradientMem mod 256;
end process SobelOperator;
person JHBonarius    schedule 10.04.2017

Seperti yang disarankan @Paebbels dalam komentar, kemungkinan besar rentang gradienMem tidak cukup untuk menangani keluaran operasi.

Hal yang perlu diperhatikan: dalam operasi bilangan bulat, rentang perantara (kebanyakan) dianggap bertanda 32b dan rentang tersebut diperiksa dalam penugasan. Hal ini memberikan banyak spekulasi untuk alat sintesis dan dapat menghasilkan desain yang jauh lebih besar dari optimal.

Untuk mengatasi hal ini, ieee.numeric_std.all digunakan untuk tipe dan operasi yang tidak ditandatangani dan ditandatangani. Hal ini memberikan kontrol mutlak untuk panjang vektor perantara. Ini juga memaksa Anda untuk mendapatkan pemahaman tentang apa yang terjadi pada penjumlahan, pengurangan, perkalian, dll yang biasanya membantu dalam desain RTL.

Namun, hal yang perlu diperhatikan adalah bahwa dalam bentuk vektor, operasi dievaluasi berpasangan dengan menggunakan yang terpanjang dari keduanya sebagai panjang vektor perantara.

Misalnya:

  process
    variable i1      : integer range 0 to 15 := 15;
    variable i2      : integer range 0 to 15 := 9;
    variable i3      : integer range 0 to 15 := 11;
    variable i4      : integer range 0 to 31 := 2;
    variable iSum    : integer range 0 to 63;
    variable u1      : unsigned(3 downto 0) := to_unsigned(15,4);
    variable u2      : unsigned(3 downto 0) := to_unsigned(9,4);
    variable u3      : unsigned(3 downto 0) := to_unsigned(11,4);
    variable u4      : unsigned(5 downto 0) := to_unsigned(2,6);
    variable uSum    : unsigned(5 downto 0);
  begin
    iSum := i1 + i2 + i3 + i4;
    uSum := u1 + u2 + u3 + u4;
    write(output, "int: " & to_string(iSum) & lf &
                  "us : " & to_string(to_integer(uSum)) & lf);
    wait;
  end process;

Memberikan:

# int: 37
# kita : 5

Menggunakan tanda kurung memecahkan masalah:

uSum := (u1 + (u2 + (u3 + u4)));
person FritzDC    schedule 10.04.2017

Ada kesalahan dalam daftar sensitivitas proses Anda SobelOperator : process(gradientMem). Di sini harus ada sinyal-sinyal yang mempengaruhi sinyal-sinyal hasil dengan kata lain ini adalah daftar sinyal-sinyal yang sensitif terhadap suatu proses. Jadi harusnya ada x11, x21, x31, x13, x23 dan x33 seperti SobelOperator : process(x11, x21, x31, x13, x23, x33)

person Roman    schedule 09.04.2017
comment
Hai, terima kasih atas tanggapan Anda! Ya, saya benar-benar memperhatikannya saat menulis pertanyaan saya. Saya akan mencoba memperbaikinya dan melihat apa yang terjadi. Saya masih ingin tahu apakah ada fungsi di perpustakaan numerik misalnya yang akan memotong sinyal integer dari satu rentang ke rentang yang lebih kecil. - person Omnomnious; 09.04.2017
comment
Untuk pemotongan output Anda dapat menggunakan tipe std_logic_vector dan mengambil dari bus hanya sedikit yang Anda butuhkan dan kemudian mengubahnya menjadi integer jika Anda membutuhkan output sebagai tipe integer - person Roman; 09.04.2017
comment
Ya, daftar sensitivitasnya salah, tapi itu bukan penyebab masalah jangkauannya... - person Paebbels; 09.04.2017
comment
@Paebbles Saya tidak dapat menambahkan komentar karena reputasi saya kurang, jadi saya mempostingnya sebagai jawaban. Atau apa yang harus saya lakukan? - person Roman; 09.04.2017
comment
Menulis jawaban boleh saja, tetapi mengubah daftar sensitivitas saja tidak cukup. Itu tidak menyelesaikan kesalahan di luar batas. - person Paebbels; 10.04.2017