เมื่อเขียน VHDL ฉันขอแนะนำให้ใช้ std_logic_vector (slv) แทนจำนวนเต็ม (int) สำหรับSIGNALSสัญญาณ(ในทางกลับกันการใช้ int สำหรับ generics ค่าคงที่บางค่าและตัวแปรบางอย่างอาจมีประโยชน์อย่างมาก) เพียงแค่ใส่ถ้าคุณประกาศสัญญาณประเภท int หรือต้องระบุช่วงสำหรับจำนวนเต็มคุณอาจกำลังทำ บางสิ่งผิดปกติ.
ปัญหาของ int คือโปรแกรมเมอร์ VHDL ไม่รู้ว่าการแทนค่าตรรกะภายในของ int นั้นคืออะไรดังนั้นเราจึงไม่สามารถใช้ประโยชน์จากมันได้ ตัวอย่างเช่นถ้าฉันกำหนด int ของช่วง 1 ถึง 10 ฉันไม่รู้ว่าคอมไพเลอร์เข้ารหัสค่าเหล่านั้นอย่างไร หวังว่ามันจะถูกเข้ารหัสเป็น 4 บิต แต่เราไม่รู้อะไรมากไปกว่านั้น หากคุณสามารถสอบสวนสัญญาณภายใน FPGA มันอาจถูกเข้ารหัสเป็น "0001" ถึง "1010" หรือเข้ารหัสเป็น "0000" ถึง "1001" อาจเป็นไปได้ว่ามันถูกเข้ารหัสด้วยวิธีที่ไม่สมเหตุสมผลกับมนุษย์เรา
แต่เราควรใช้ slv แทน int เพราะจากนั้นเราสามารถควบคุมการเข้ารหัสและเข้าถึงโดยตรงไปยังแต่ละบิต การเข้าถึงโดยตรงเป็นสิ่งสำคัญอย่างที่คุณจะเห็นในภายหลัง
เราสามารถใช้ int เพื่อ slv เมื่อใดก็ตามที่เราต้องการเข้าถึงบิตแต่ละอัน แต่มันก็ยุ่งเหยิงเร็วมาก นั่นเหมือนกับการได้รับสิ่งที่เลวร้ายที่สุดของทั้งสองโลกแทนที่จะเป็นสิ่งที่ดีที่สุดของทั้งสองโลก โค้ดของคุณจะยากสำหรับคอมไพเลอร์ในการปรับให้เหมาะสมและแทบเป็นไปไม่ได้ที่คุณจะอ่าน ฉันไม่แนะนำสิ่งนี้
ดังที่ฉันพูดด้วย slv คุณสามารถควบคุมการเข้ารหัสบิตและเข้าถึงบิตโดยตรง แล้วคุณจะทำอย่างไรกับสิ่งนี้ ฉันจะแสดงตัวอย่างให้คุณดู สมมติว่าคุณต้องส่งสัญญาณพัลส์หนึ่งครั้งทุก ๆ 4,294,000,000 นาฬิกา นี่คือวิธีที่คุณจะทำกับ int:
signal count :integer range 0 to 4293999999; -- a 32 bit integer
process (clk)
begin
if rising_edge(clk) then
if count = 4293999999 then -- The important line!
count <= 0;
pulse <= '1';
else
count <= count + 1;
pulse <= '0';
end if;
end if;
end process;
และรหัสเดียวกันโดยใช้ slv:
use ieee.numeric_std.all;
signal count :std_logic_vector (32 downto 0); -- a 33 bit integer, one extra bit!
process (clk)
begin
if rising_edge(clk) then
if count(count'high)='1' then -- The important line!
count <= std_logic_vector(4293999999-1,count'length);
pulse <= '1';
else
count <= count - 1;
pulse <= '0';
end if;
end if;
end process;
รหัสนี้ส่วนใหญ่เหมือนกันระหว่าง int และ slv อย่างน้อยก็ในแง่ของขนาดและความเร็วของตรรกะที่เกิดขึ้น แน่นอนว่าคนหนึ่งกำลังนับและอีกคนกำลังนับถอยหลัง แต่นั่นไม่สำคัญสำหรับตัวอย่างนี้
ความแตกต่างอยู่ใน "บรรทัดสำคัญ"
จากตัวอย่าง int สิ่งนี้จะส่งผลให้ตัวเปรียบเทียบแบบ 32- อินพุต ด้วย 4-LUT LUT ที่ Xilinx Spartan-3 ใช้นี่จะต้องใช้ 11 LUTs และตรรกะ 3 ระดับ คอมไพเลอร์บางตัวอาจแปลงสิ่งนี้ให้เป็นการลบซึ่งจะใช้โซ่หิ้วและขยายที่เทียบเท่ากับ 32 LUT แต่อาจวิ่งได้เร็วกว่าตรรกะ 3 ระดับ
จากตัวอย่าง slv ไม่มีการเปรียบเทียบแบบ 32 บิตดังนั้นจึงเป็น "ศูนย์ LUT's, ระดับศูนย์ตรรกะ" โทษเพียงอย่างเดียวคือที่เคาน์เตอร์ของเราเป็นหนึ่งบิตพิเศษ เนื่องจากช่วงเวลาเพิ่มเติมสำหรับตัวนับบิตพิเศษนี้ทั้งหมดอยู่ในโซ่หิ้วพกพาจึงมีการหน่วงเวลาเพิ่มเติมเกือบเป็นศูนย์
แน่นอนว่านี่เป็นตัวอย่างที่ดีมากเนื่องจากคนส่วนใหญ่จะไม่ใช้ตัวนับ 32 บิตในลักษณะนี้ มันใช้กับเคาน์เตอร์ขนาดเล็ก แต่ความแตกต่างจะลดลงอย่างมากแม้ว่าจะยังคงสำคัญ
นี่เป็นเพียงตัวอย่างหนึ่งของวิธีการใช้ slv over int เพื่อให้ได้เวลาที่เร็วขึ้น มีวิธีอื่น ๆ อีกมากมายที่จะใช้ประโยชน์จาก slv - ใช้เวลาจินตนาการเพียงอย่างเดียว
อัปเดต: เพิ่มรายการเพื่อระบุความคิดเห็นของ Martin Thompson เกี่ยวกับการใช้ int กับ "if (count-1) <0"
(หมายเหตุ: ฉันถือว่าคุณหมายถึง "ถ้านับ <0" เนื่องจากจะทำให้มันเทียบเท่ากับรุ่น slv ของฉันและลบความจำเป็นในการลบพิเศษนั้น)
ภายใต้สถานการณ์บางอย่างสิ่งนี้อาจสร้างการใช้งานตรรกะที่ตั้งใจ แต่ไม่รับประกันว่าจะทำงานตลอดเวลา มันจะขึ้นอยู่กับรหัสของคุณและคอมไพเลอร์ของคุณเข้ารหัสค่า int
ขึ้นอยู่กับคอมไพเลอร์ของคุณและวิธีที่คุณระบุช่วงของ int เป็นไปได้โดยสิ้นเชิงว่าค่า int ของศูนย์ไม่ได้เข้ารหัสเป็นบิตเวกเตอร์ของ "0000 ... 0000" เมื่อมันทำให้เป็นตรรกะ FPGA เพื่อให้รูปแบบของคุณทำงานต้องเข้ารหัสเป็น "0000 ... 0000"
ตัวอย่างเช่นสมมติว่าคุณกำหนด int ให้มีช่วง -5 ถึง +5 คุณคาดหวังว่าค่า 0 จะถูกเข้ารหัสเป็น 4 บิตเช่น "0000" และ +5 เป็น "0101" และ -5 เป็น "1011" นี่เป็นรูปแบบการเข้ารหัสแบบเติมเต็มทั่วไป
แต่อย่าคิดว่าคอมไพเลอร์จะใช้ twos-complement แม้ว่าผิดปกติการเติมเต็มอาจส่งผลให้ตรรกะ "ดีกว่า" หรือคอมไพเลอร์สามารถใช้การเข้ารหัสแบบ "biased" โดยที่ -5 ถูกเข้ารหัสเป็น "0000", 0 เป็น "0101" และ +5 เป็น "1010"
หากการเข้ารหัสของ int นั้น "ถูกต้อง" ผู้แปลจะมีแนวโน้มที่จะสรุปว่าจะทำอย่างไรกับบิตนำพา แต่ถ้ามันไม่ถูกต้องแล้วตรรกะที่เกิดขึ้นจะน่ากลัว
อาจเป็นไปได้ว่าการใช้ int ด้วยวิธีนี้อาจส่งผลให้เกิดขนาดและความเร็วของตรรกะที่สมเหตุสมผล แต่ไม่สามารถรับประกันได้ การสลับไปใช้คอมไพเลอร์อื่น (เช่น XST เป็นเรื่องย่อ) หรือไปที่สถาปัตยกรรม FPGA อื่นอาจทำให้เกิดสิ่งผิดปกติขึ้น
Unsigned / Signed vs. slv เป็นอีกการถกเถียงกัน คุณสามารถขอบคุณคณะกรรมการรัฐบาลสหรัฐฯที่ให้ทางเลือกมากมายแก่เราใน VHDL :) ฉันใช้ slv เพราะนั่นเป็นมาตรฐานสำหรับการเชื่อมต่อระหว่างโมดูลและคอร์ นอกเหนือจากนั้นและกรณีอื่น ๆ ในแบบจำลองฉันไม่คิดว่ามีประโยชน์มากในการใช้ slv ผ่านการลงชื่อ / ไม่ได้ลงชื่อ ฉันก็ไม่แน่ใจเหมือนกันว่าสัญญาณที่รองรับสัญญาณระบุตรี