آرایه های دروازه ای قابل برنامه ریزی میدانی مباحث ویژه در الکترونیک آرایه های دروازه ای قابل برنامه ریزی میدانی Field Programmable Gate Arrays (FPGAs) مدرس: دکتر محمدرضا مسلمی moslemi@iauzarghan.ac.ir
مقدمه ASIC چیست؟ مخفف کلمات Application Specific Integrated IC است. این واژه معمولا به مدارهای مجتمعی که صرفا برای کاربردهای خاص ساخته می شوند اطلاق می شود. از این نوع مدارهای مجتمع در ساخت انواع میکروپروسسورها، انواع حافظه های خواندنی-نوشتنی (RAM) و فقط خواندنی (ROM) استفاده می شود. مزایا در صورتی که مدارهای با کاربرد خاص به صورت مدار مجتمع در آیند، کاهش قابل توجهی در اندازه مدار خواهیم داشت. با کاهش اندازه مدار یکپارچگی سیگنال ها در مدار افزایش می یابد. سرعت مدار افزایش می یابد.
معایب معمولا از زمان طراحی این مدار تا تولید آن توسط کارخانجات سازنده آی سی زمان نسبتا طولانی نیاز است. به دلیل آن که تولید توسط کارخانجات تولید آی سی و در یک فرآیند خارج از روال آن انجام می شود، هزینه تمام شده بالایی دارند. معمولا برای تولید انبوه استفاده می شوند و برای تعداد کم مقرون به صرفه نمی باشند.
FPGA چیست؟ مزایا مخفف کلمات Field Programmable Gate Array است. این واژه معمولا به مدارهای مجتمعی که برای پیاده سازی مدارهای دیجیتال قابل برنامه ریزی هستند اطلاق می شود. از این نوع مدارهای مجتمع در ساخت انواع میکروپروسسورها، انواع حافظه ها، مدارات ورودی-خروجی و پردازش تصویر استفاده می شود. مزایا در صورتی که مدارهای دیجیتال در یک FPGA قرار گیرد، کاهش قابل توجهی در اندازه مدار خواهیم داشت. با کاهش اندازه مدار یکپارچگی سیگنال ها در مدار افزایش می یابد. سرعت مدار افزایش می یابد.
معایب کاربردها ظرفیت بالای فشرده سازی دارند. قیمت تمام شده آنها بسیار پایین می باشد زمان عرضه این آی سی ها به بازار بسیار کم می باشد. امنیت مدار بالا رفته و امکان کپی کردن آن از بین می رود. معایب سطح سیلیکون FPGA به صورت بهینه مورد استفاده قرار نمی گیرد. تاخیر و توان مصرفی آنها نسبت به مدارات ASIC بیشتر است. کاربردها اگرچه نمی توان محدوده خاصی برای کاربرد این مدارها تعیین کرد با این وجود برخی از کاربردهای آنها عبارتند از: کارتهای ورودی-خروجی، فیلترهای دیجیتال، میکروکنترلر و میکروپروسسورهای خاص، پردازش سیگنال و تصویر، سیستم های مخابراتی و ابزار دقیق و سیستم های نظامی
Xilinx, Altera, Lattice, Actel شرکت های سازنده مهم ترین شرکت های سازنده FPGA عباتند از: Xilinx, Altera, Lattice, Actel مهم ترین سهم شرکت های سازنده از بازار FPGA تاریخچه آی سی های دو شرکت مهم تولید کننده
درباره زایلینکس (Xilinx) این شرکت در سال 1984 تاسیس گردید. بیش از 2600 کارمند دارد. بیش از نیمی از محصولات FPGA مورد نیاز را در دنیا تامین می کند. با سازندگان مهمی چون IBM، UMC و Seiko مشارکت دارد. مهمترین نرم افزارهای شبیه سازی: ISI, Fandation درباره آلترا (Altera) این شرکت در سال 1983 تاسیس گردید. در سال 1992 ساختار جدول جستجو (Look Up Table) را معرفی نمود. دومین شرکت تولید کننده آی سی های FPGA در دنیا است. با شرکت TSMC مشارکت دارد. مهمترین نرم افزارهای شبیه سازی: Quartus II, Max Plus II
ساختار داخلی FPGA چگونه می توان مدارهای دیجیتالی مختلف را درون یک FPGA پیاده سازی کرد؟ همانطور که می دانیم برای هر مدار دیجیتال با هر تعداد ورودی و خروجی می توان یک جدول درستی (Truth table) رسم نمود. در جدول درستی تمامی حالت های ممکن ورودی به تصویر درآمده و به ازای هر یک از این حالات خروجی تعیین می گردد. فرض کنید مدار مورد نظر 4 ورودی و 1 خروجی دارد. در این حالت می توان این مدار را با یک RAM با 4 بیت ورودی آدرس و 1 بیت خروجی داده جایگزین نمود. RAM مورد نظر دارای 16 آدرس مختلف، معادل 16 حالت ورودی جدول درستی است که در هر آدرس خروجی تابع مورد نظر نوشته می شود. بسته به این که ورود مدار چه باشد داده ذخیره شده در یکی از خانه های RAM در خروجی ذخیره می شود. برای پیاده سازی مدارهای بزرگتر می توان از مجموعه ای از این بلوک های حافظه استفاده نمود.
در این مدارها به دلیل استفاده از RAM، مدار ذخیره شده در FPGA فرار بوده و پس از قطع برق از بین می رود. بنابراین پس از قطع برق، پیکربندی مجدد لازم است. معمولا کل برنامه را درون یک PROM کپی می کنند تا پس از وصل برق، مجددا درون FPGA بارگذاری شود. استفاده از RAM باعث افزایش انعطاف پذیری می گردد. یعنی هر زمان که بخواهیم می توانیم با پیکر بندی مجدد، مدار داخلی را عوض کنیم. چهار بلوک زیر می تواند در ساختار داخلی FPGA به عنوان بلوک های پایه مورد استفاده قرار گیرد. PROM (Anti fuse) EEPROM FLASH RAM سازندگان دنیای FPGA، به کوچکترین واحد تشکیل دهنده (یعنی هر یک از حافظه های مورد استفاده) اصطلاحا LUT (Look Up Table) می گویند.
یک مدار منطقی ثابت مثالی از روش پیاده سازی یک منطق برنامه پذیر با 3 ورودی و یک خروجی با استفاده از آنتی فیوز
بسته به ورودی کنترل MUX، مدار ترکیبی یا ترتیبی خواهد بود. چگونه می توان مدارهای ترتیبی را درون یک FPGA پیاده سازی کرد؟ مدارهای ترتیبی (Sequential) نیز می توانند درون یک FPGA پیاده سازی شوند. در FPGA، خروجی هر LUT به صورت مستقیم و همچنین از طریق یک فلیپ فلاپ به یک مالتی پلکسر وارد می شود. بسته به ورودی کنترل MUX، مدار ترکیبی یا ترتیبی خواهد بود. از ترکیب دو سلول منطقی (Logic Cell) یک Slice به وجود می آید واحد پایه در FPGA Xilinx: LC – Logic Cell Altera: LE – Logic Element
Configurable Logic Block (CLB) ALM (Adaptive Logic Module) در Slice مداری برای انتقال رقم نقلی نیز وجود دارد. Slice 0 LUT Carry D Q CE PRE CLR از ترکیب 2 عدد Slice یک Configurable Logic Block (CLB) تشکیل می گردد. CLB در واقع اصلی ترین بخش از هر FPGA است که توابع منطقی را پیاده سازی می کند. در سری Stratix II خانواده Altera اصطلاحا ALM (Adaptive Logic Module) نامیده می شود. یک Slice که از ترکیب دو LC تشکیل شده است. هر Slice دارای 4 خروجی می باشد. 2 خروجی حافظه و 2 خروجی ترکیبی
جمع بندی LUT LC Configurable Logic Block Slice CLB FPGA Look Up Table شامل یک RAM با 4 ورودی و یک خروجی می باشد. LC Logic Cell شامل 2 عدد LUT به همراه 2 عدد F.F. می باشد. Slice از ترکیب 2 عدد LC تشکیل می شود. CLB Configurable Logic Block از ترکیب 2 عدد Slice تشکیل می گردد. FPGA Field Programmable Gate Array از کنار هم قرار گرفتن CLB ها تشکیل می شود.
ساختار داخلی یک FPGA معمول
در اغلب FPGA های جدید علاوه بر تعداد زیاد CLB، برخی امکانات دیگر نیز برای تسهیل در پیاده سازی مدارهای دیجیتال پیچیده تر وجود دارد. یکی از مهم ترین این امکانات RAM داخلی غیر از نمونه های کوچک موجود در LUT ها است. در صورتی که بخواهیم مداری با تعداد زیاد ورودی را پیاده سازی نماییم، به جای استفاده از تعداد زیاد CLB از بخشی از همین حافظه داخلی استفاده می کنیم. به عنوان مثال، مدل اسپارتان 2 از شرکت زایلینکس، دارای بلوک های هر کدام با ظرفیت 4096 بیت است. جدول نحوه استفاده از حافظه داخلی اسپارتان 2
ضرب کننده در بعضی محصولات جدید شرکت های Xilix, Altera بلوک های ضرب کننده وجود دارد. عمل ضرب در این محصولات را می توان توسط ضرب کننده های داخلی 18 بیتی نیز با سرعت بالاتر انجام داد. این ضرب کننده ها معمولا در کارهای پردازش سیگنال کاربرد دارند. میکروپروسسور داخلی در بعضی محصولات جدید شرکت های Xilix, Altera مثل Virtex-II Pro یک میکروپروسسور داخلی وجود دارد. این FPGA کاملا تخصصی است و برای کاربردهای تخصصی استفاده می شود. PowerPC در واقع یک میکروپروسسور داخلی است که توسط شرکت IBM داخل FPGA قرار داده شده است.
پیاده سازی مدار بر روی تراشه مراحل مختلف ساخت یک FPGA طراحی ابتدایی پیاده سازی مدار بر روی تراشه سنتز و بهینه سازی مدار شبیه سازی طراحی ابتدایی در این مرحله باید مدار مورد نظر خود را طراحی نماییم. روش معمول برای پیاده سازی مدار استفاده از برنامه های سطح بالا برای برنامه ریزی مدار است. البته در بسیاری از نرم افزارهای شبیه ساز، امکان این که شماتیک مدار را رسم کرد نیز وجود دارد. این نرم افزارها قادرند خروجی متنی برنامه را نیز به زبان های مرسوم تولید کنند. HDL Designer (HDS) یکی از این نرم افزارهاست. البته این امکان معمولا نیاز به دانستن یک زبان برنامه نویسی را برای کارهای پیچیده تر منتفی نمی کند.
VHDL: Very High Speed Description Language دو زبان اصلی برنامه نویسی FPGA عبارتند از: VHDL, Verilog برخلاف برنامه های مرسوم که معمولا به صورت خط به خط اجرا می شوند، این برنامه ها بر اساس رخدادها (Cuncurrent) اجرا می شوند. به همین دلیل معمولا از کلمه ((کد)) به جای ((برنامه)) استفاده می شود. VHDL: Very High Speed Description Language زبان توصیفی با سرعت خیلی بالا در این مرحله، معمولا کد VHDL را در یک فایل با پسوند .vhd ذخیره می کنند. از آنجای که هر طرح پیاده شده با کد VHDL را بعدا می توان به صورت پکیج آماده در سایر طرح ها نیز استفاده کرد، معمولا نام فایل را همان موجودیت (entity) مورد استفاده در کد قرار می دهیم.
ModelSim از شرکت Model Technology LDV از شرکت Cadence شبیه سازی برنامه هایی وجود دارند که کد مورد نظر ما را گرفته و عملکرد مدار را برای ما شبیه سازی می کنند. به این ترتیب که ما شکل ورودی های مدار را برای آنها تعیین کرده و این نرم افزارها، خروجی های مختلف را به ما می دهند. به وسیله این نرم افزارها می توانیم از عملکرد مدار خود به ازای حالت های مختلف ورودی، قبل از پیاده سازی آن بر روی FPGA مطمئن شویم. دو نرم افزار معروف برای شبیه سازی عملکرد کدهای VHDL و Verilog عبارتند از: ModelSim از شرکت Model Technology LDV از شرکت Cadence
برای شبیه سازی عملکرد مدار، معمولا لازم است که غیر از برنامه اصلی یک برنامه دیگر نوشته شود. این برنامه که صرفا برای تست مدار می باشد، test fixture (برای برنامه Verilog) و test bench (برای برنامه VHDL) نامیده می شود. معمولا برنامه تست به این صورت است که شکل موج های مختلف که حاوی تمام حالات ممکن ورودی می باشد تولید می شود. معمولا در نوشتن برنامه test bench، طراح به بسیاری از نکات منفی و حالت هایی که در طراحی مدار اصلی از آن غافل شده است پی می برد.
سنتز مهم ترین مرحله در ساخت آی سی منطقی که از زبان توصیف سخت افزار برای طراحی آن استفاده شده است، مر حله سنتز (Synthesis) است. در این مرحله کد HDL تبدیل به مجموعه ای از گیت های مناسب می شود. نرم افزارهای FPGA Express, FPGA Compiler II, Leonardo Spectrum, Simplify از جمله نرم افزارهای تخصصی سنتز می باشند. پیاده سازی آخرین مرحله انجام یک پروژه مرحله ای است که فایل سنتز شده دریافت و مدار مربوط به آن بر روی FPGA پیاده می شود. در مرحله پیاده سازی 4 گام اصلی وجود دارد.
Translation: تمام اطلاعاتی که برای مراحل بعد لازم است در این مرحله ساخته می شود. Mapping: این که مدار منطقی مورد نظر ما باید چه ترکیبی از کوچکترین عناصر سازنده FPGA یعنی LUTها بافرها، بلوک های رم و ... باشد در این مرحله تعیین می گردد. Placement: در این مرحله برای هر کدام از عناصر موجود در فایل تولید شده در مرحله قبل، یک محل مخصوص در نظر گرفته می شود. Routing: آخرین مرحله می باشد. در این مرحله، عناصر روی FPGA با سیم ها و منابع routing موجود به هم وصل می شوند. لازم به ذکر است که برخی از نرم افزارهای معروف قادرند تمامی مراحل از ورود کد های مورد نظر تا مرحله پیاده سازی را انجام دهند. از مهم ترین این نرم افزارها می توان به Quartus II و Xilinx ISE Design اشاره نمود.
ساختار یک برنامه VHDL هر کد VHDL دارای سه بخش اصلی زیر می باشد. 1- معرفی کتابخانه ها (Library Decleration): در این بخش تمامی کتابخانه های استفاده شده در کد معرفی می گردند. 2- موجودیت (Entity): پین ها (پورتهای) ورودی و خروجی مدار را مشخص می کند. 3- معماری (Architectue): نحوه عملکرد مدار را مشخص می کند. کتابخانه معمولا قطعات پر استفاده و معمول را در کتابخانه قرار می دهند تا بتوان از قابلیت های استفاده مجدد و اشتراک گذاری آنها در سایر برنامه نیز استفاده نمود. معمولا در هر کد VHDL به حداقل 3 بسته (Package) متعلق به 3 کتابخانه نیاز داریم.
VHDL به حروف بزرگ و کوچک حساس نمی باشد. بسته std_logic_1164 مربوط به کتابخانه ieee بسته standard مربوط به کتابخانه std بسته work متعلق به کتابخانه work برای اعلان کتابخانه به دو خط کد نیاز داریم: LIBRARY library_name; Use library_name.package_name.package_parts; مثلا LIBRARY ieee; Use ieee.std_logic_1164.all; LIBRARY std; Use std.standard.all; VHDL به حروف بزرگ و کوچک حساس نمی باشد.
موجودیت در کد به صورت زیر تعریف می شود. ENTITY entity_name IS PORT ( port_name: signal_mode signal_type; …); END entity_name; پارامتر mode شامل یکی از مقادیر زیر است. In, out, inout, buffer نوع بافر زمانی استفاده می شود که بخواهیم از یک سیگنال خروجی به صورت داخلی استفاده نماییم.
معماری (Architecture) پارامتر type شامل یکی از مقادیر زیر است. Bit, integer, std_logic معماری (Architecture) معماری دو بخش دارد. 1- بخش اعلان (اختیاری و در صورت لزوم): سیگنال ها و متغیرها و ثوابت تعریف می شوند. 2- بخش کد که عملکرد مدار را توصیف می کند. ARCHITECTURE architecture_name of entity_name IS [Decleration] BEGIN (code) END architecture_name;
مثال: طراحی یک گیت NAND ساده ENTITY nand_gate IS PORT (a, b: IN BIT; -- inputs x: OUT BIT); -- outputs END nand_gate; ARCHITECTURE my_arch of nand_gate IS Signal int: std_logic; -- internal signal decleration BEGIN int <= a and b; x <= NOT int; END my_arch ; ENTITY nand_gate IS PORT (a, b: IN BIT; x: OUT BIT); END nand_gate; ARCHITECTURE my_arch of nand_gate IS BEGIN x <= a NAND b; END my_arch ; به جای تعریف سیگنال داخلی int می توان از عملگر NAND استفاده کرد. عملگرهای منطقی زیر در استاندارد VHDL تعریف شده اند. NOT, AND, NAND, OR, NOR, XOR, XNOR
مثال: طراحی یک نیم جمع کننده library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity Half_adder_mine is Port ( X : in STD_LOGIC; Y : in STD_LOGIC; S : out STD_LOGIC; C : out STD_LOGIC); end Half_adder_mine; architecture Behavioral of Half_adder_mine is begin S <= X xor Y; C <= X and Y; end Behavioral;
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity Three_input_gates is Port ( IN0, IN1, IN2 : in STD_LOGIC; OUT0, OUT1, OUT2, OUT3, OUT4, OUT5 : out STD_LOGIC); end Three_input_gates; architecture Behavioral of Three_input_gates is begin OUT0 <= IN0 and IN1 and IN2; OUT1 <= IN0 or IN1 or IN2; OUT2 <= not (IN0 and IN1 and IN2); OUT3 <= not (IN0 or IN1 or IN2); OUT4 <= IN0 xor IN1 xor IN2; OUT5 <= IN0 xnor IN1 xnor IN2; end Behavioral;
داده های از قبل تعریف شده BIT, BIT_VERCTOR STD_LOGIC, STD_LOGIC_VECTOR انواع داده داده های از قبل تعریف شده داده های تعریف شده توسط کاربر داده های از قبل تعریف شده BIT, BIT_VERCTOR STD_LOGIC, STD_LOGIC_VECTOR STD_ULOGIC, STD_ULOGIC_VECTRO BOOLEAN INTEGER NATURAL REAL SIGNED, UNSIGNED داده های تعریف شده توسط کاربر INTEGER ENUMERATED
داده های از قبل تعریف شده این داده ها در استانداردهای IEEE1076 و IEEE1164 و در کتابخانه ها و بسته های زیر تعریف شده اند. انواع داده نام بسته نام کتابخانه BIT, BOOLEAN, INTEGRE, REAL STANDARD STD STD_LOGIC, STD_ULOGIC STD_LOGIC_1164 IEEE SIGNRD, UNSIGNED STD_LOGIC_ARITH STD_LOGIC_VECTOR STD_LOGIC_SIGNED STD_LOGIC_UNSIGNED
نوع BIT و BIT_VECTOR (دو سطح منطقی ‘0’ و ‘1’ را دارند)
انواع STD_LOGIC و STD_LOGIC_VECTOR یک سیستم منطقی 8 مقداره متعلق به استاندارد ieee1164 است که بیشتر این مقادیر فقط برای شبیه سازی استفاده می شوند. فقط مقادیر ‘0’, ‘1’, ‘Z’ قابل سنتز هستند. حالت های «ضعیف» و «قوی» به این دلیل استفاده شده اند که اگر دو سیگنال از این نوع به یک گره متصل باشند مقادیر نوع قوی تعیین کننده نهایی خواهند بود.
انواع STD_ULOGIC و STD_ULOGIC_VECTOR یک سیستم منطقی 9 مقداره است. علاوه بر مقادیر قبلی مقدار ‘U’ (Unresolved) نیز اضافه شده است. در این حالت بر خلاف حالت قبلی نمی توان سیم های با مقادیر مختلف را به هم متصل نمود. برای نشان دادن خطای مربوطه از این مقدار استفاده می شود. نوع داده حداقل مقدار حداکثر مقدار Boolean FALSE TRUE INTEGER -2147483647 2147483647 NATURAL REAL -1.0E38 1.0E38 SIGNED
نوع Boolean: شامل مقادیر TRUE و FALSE است. نوع INTEGER: شامل اعداد صحیح از 2147483647- تا 2147483647 است. نوع NATURAL: شامل اعداد صحیح نامنفی از 0 تا 2147483647 است. نوع REAL: شامل اعداد حقیقی از -1.0E38 تا 1.0E38 است. (این نوع داده قابل سنتز نیست.
داده های تعریف شده توسط کاربر: کاربر امکان تعریف دو نوع داده را دارد. نوع INTEGER نوع ENUMERATED
نحوه تعریف نوع جدید داده TYPE type_name IS ARRAY (specification) OF data_type; SIGNAL signal_name: type_name [:=initial_value]; نحوه استفاده مثال: نحوه تعریف یک آرایه 1D*1D TYPE row IS ARRAY (7 downto 0) OF std_logic; -- 1D Array TYPE matrix IS ARRAY (0 to 3) OF row; -- 1D * 1D SIGNAL x: matrix; مثال: نحوه تعریف یک آرایه 2D TYPE matrix2D IS ARRAY (0 to 3, 7 downto 0) of std_logic; -- 2D Array پیوند دهی داده ها: علامت & به معنی پیوند دهی بین داده ها است. ARCHITECTURE rtl OF exIS SIGNAL a:std_logic_vetor (5 DOWNTO 0); SIGNAL b, c, d : std_logic_vector(2 DOWNTO 0); BEGIN B <= ‘0’ & c(1) & d(2); END generic_decoder; If c = “011”, d = “101” ===> B = “011” یک نمونه دیگر از کاربرد این دستور IF c & d = “001100” THEN
کتابخانه ها وقتی یک عنصر در VHDL تعریف می شود به صورت اتوماتیک در کتابخانه WORK ذخیره می شود. کابخانه نام یک فولدر در کامپیوتر نیست. بلکه نام اشاره گری است که در هنگام راه اندازی نرم افزار تعیین می شود. کتابخانه های std, work همیشه در دسترس هستند و نیازی به تعریف مجدد آنها نیست. در صورت استفاده از کتابخانه دیگر باید در ابتدای برنامه تعریف شوند. در مورد طرح های بزرگ، امکان استفاده از توابع، مقادیر ثابت، انواع داده و ... در بلوک های مختلف وجود دارد. مقدار ثابت به عنوان مثال می تواند پهنای باس داده باشد. هر موقع درون بسته این عدد ثابت تغییر کند در کلیه زیر بخش های پروژه به صورت همزمان تغییر می کنند. بسته (Package) یک بسته (Package) می تواند شامل function ها، procedure ها، انواع داده، ثابت ها و نشانگرها باشد. یک بسته از دو بخش زیر تشکیل شده است. اعلام بسته بدنه بسته
اگر بخواهیم درون موجودیت، از یک داده جدید استفاده کنیم، باید قبل از تعریف موجودیت، آن داده را درون یک بسته تعریف کرده باشیم. LIBRARY ieee; USE ieee.std_logic_1164.all; ---------------------------------------------------------------------------- PACKAGE my_data_types IS TYPE vector_array IS ARRAY (natural range <>) of std_logic_vector (7 downto 0); END my_data_types; بعد از ذخیره کردن این بسته در مسیر جاری، به صورت زیر از آن در برنامه اصلی استفاده می کنیم. LIBRARY ieee; USE ieee.std_logic_1164.all; USE work.my_data_types.all; -- User-defined package ---------------------------------------------------------------------------- entity MUX is port(I:in vector_array (3 downto 0); S vector_array (1 downto 0); Y: out bit); end MUX;
بخش اعلام بسته شامل علاوه بر معرفی داده ها، شامل functionها، procedure ها، ثابت های مورد استفاده در آن بسته نیز می باشد. بخش بدنه بسته بیان کننده رفتار زیر برنامه هایی است که در بخش اعلام معرفی شده اند. PACKAGE my_pack IS FUNCTION minimum (a, b: IN std_logic_vector) RETURN std_logic_vector; CONSTANT max_int: integer := 16#FFFF#; TYPE arithmetic_mode_type IS (signed, unsigned) END my_pack; -------------------------------------------------------------------------------- PACKAGE BODY my_pack IS BEGIN IF a < b THEN RETURN a; ELSE RETURN b; END IF; END minimum;
عملگرها برای تخصیص مقادیر به سیگنال ها، متغیرها و توابع استفاده می شود. 1- عملگر => برای تخصیص مقدار به سیگنال به کار می رود. 2- عملگر =: برای دادن مقدار اولیه به یک ثابت یا متغیر به کار می رود. 3- عملگر <= برای تخصیص مقدار به تک تک المان های یک بردار و همراه OTHERS به کار می رود. تخصیص منطقی ریاضی رابطه ای شیفت تجمیع
برای انجام عملیات منطقی روی داده های از نوع BIT، STD_LOGIC و STD_ULOGIC استفاده می شود. عملگرهای منطقی: NOT, AND, OR, NAND, NOR, XOR, XNOR عملگرهای منطقی مثال: Y <= NOT a AND b; -- (a’.b) Y <= NOT(a AND b); -- (a.b)’ Y <= a NAND b; -- (a.b)’ برای انجام عملیات ریاضی روی داده های از نوع INTEGER، SIGNED، UNSIGNED و REAL استفاده می شود. عملگرهای منطقی: + (جمع), - (تفریق), * (ضرب), / (تقسیم), ** (توان), MOD (خارج قسمت), REM (باقیمانده), ABS (قدرمطلق) عملگرهای ریاضی
عملگرهای رابطه ای یا مقایسه ای برای انجام مقایسه بین دو مقدار داده استفاده می شود. عملگرهای منطقی: = (مساوی), /= (مخالف), < (کوچکتر), > (بزرگتر), <= (کوچکتر یا مساوی), >= (بزرگتر یا مساوی) عملگرهای شیفت برای انجام شیفت استفاده می شود. sll: مکانهای سمت راست با صفر پر می شوند. srl: مکانهای سمت چپ با صفر پر می شوند. ARCHITECTURE rtl OF ex3 IS BEGIN q1 <= ‘0’; q2 <= ‘0’; q3 <= ‘0’; END rtl; ARCHITECTURE rtl2 OF ex3 IS BEGIN q1 <= “001”; q2 <= “010”; q3 <= “111”; END rtl; مقدار دهی چند گانه
If then else Case statement Variable declaration Loop statement انواع ساختارها در VHDL ساختارهای متوالی If then else Case statement Variable declaration Loop statement Return statement Null statement Wait statement ساختارهای موازی Process When else With select Signal declaration Block statement
عبارت IF یک دستور IF شامل یک یا چند عبارت داخلی است که بسته به برقراری شروط، یکی از عبارت ها اجرا می شود. ENTITY ex_if IS PORT (a, b : IN INTEGER; c : OUT BOOLEAN); END; ARCHITECTURE rtl OF ex_if IS BEGIN PROCESS (a,b) IF a > b THEN c <= TRUE; ELSE c <= FALSE; END IF; END PROCESS; END rtl; IF SEL = ‘0’ THEN C <= A; ELSE C <= B; END IF;
عبارت WHEN a b c q ex Data [1 0] مجددا تاکید می گردد که همانند یک سخت افزار که ذاتا موازی است، کد VHDL نیز به صورت موازی اجرا می شود. در نتیجه ترتیب خطوط در VHDL معنی ندارد. ARCHITECTURE example of ex IS BEGIN a <= b; b <= c; END my_arch ; ARCHITECTURE example of ex IS BEGIN b <= c; a <= b; END my_arch ; مثال فوق به این معنا است که وقتی که c تغییر می کند، تمام خطوطی که C در سمت راست قرار دارد به طور همزمان اجرا می شوند. عبارت WHEN ENTITY ex IS PORT (a, b, c: IN std_logic; data: IN std_logic_vector (1 downto 0); q: OUT std_logic); END ex; ----------------------------------- ARCHITECTURE rtl OF ex IS BEGIN q <= a WHEN data = "00" else b WHEN data = "11" else c; END rtl; a b c q ex Data [1 0]
طراحی یک مدار مقایسه کننده library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity Compare_mine is Port ( A : in STD_LOGIC_VECTOR (3 downto 0); B : in STD_LOGIC_VECTOR (3 downto 0); Y0 : out STD_LOGIC; Y1 : out STD_LOGIC; Y2 : out STD_LOGIC; Y3 : out STD_LOGIC; Y4 : out STD_LOGIC; Y5 : out STD_LOGIC); end Compare_mine; architecture Behavioral of Compare_mine is begin Y0 <= '1' when A = B else '0'; Y1 <= '1' when A /= B else '0'; Y2 <= '1' when A < B else '0'; Y3 <= '1' when A <= B else '0'; Y4 <= '1' when A > B else '0'; Y5 <= '1' when A >= B else '0'; end Behavioral;
طراحی یک دیکودر 3*8 architecture Behavioral of Decoder3_8_mine is begin Y <= "00000001" when D = "000" else "00000010" when D = "001" else "00000100" when D = "010" else "00001000" when D = "011" else "00010000" when D = "100" else "00100000" when D = "101" else "01000000" when D = "110" else "10000000" when D = "111" else "00000000" ; end Behavioral; library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity Decoder3_8_mine is Port ( D : in STD_LOGIC_VECTOR (2 downto 0); Y : out STD_LOGIC_VECTOR (7 downto 0)); end Decoder3_8_mine;
طراحی یک مالتی پلکسر 1*8 architecture Behavioral of MUX81_mine is begin Y <= D(0) when A = "000" else D(1) when A = "001" else D(2) when A = "010" else D(3) when A = "011" else D(4) when A = "100" else D(5) when A = "101" else D(6) when A = "110" else D(7) when A = "111" else 'Z' ; end Behavioral; library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity MUX81_mine is Port ( D : in STD_LOGIC_VECTOR (7 downto 0); A : in STD_LOGIC_VECTOR (2 downto 0); Y : out STD_LOGIC); end MUX81_mine;
عبارت WITH در صورتی که در برنامه مجبور باشیم حالتهای زیادی را با استفاده از WHEN ELSE پیاداه سازی نماییم می توانیم برای راحتی از WITH استفاده کنیم. همان مثال قبل را این بار با استفاده از دستور WITH می نویسیم. ENTITY ex IS PORT (a, b, c: IN std_logic; data: IN std_logic; q: OUT std_logic); END ex; ----------------------------------- ARCHITECTURE rtl OF ex IS BEGIN WITH data SELECT q <= a WHEN "00“, b WHEN "11“, c WHEN OTHERS; END rtl;
ENTITY case_mux IS PORT (a, b, sel : IN BIT; c : OUT BIT); END; ARCHITECTURE rtl OF case_mux IS BEGIN case sel IS WHEN ‘0’ => c <= a; WHEN ‘1’ => c <= b; END case; END rtl; عبارت CASE استفاده از این دستور در اغلب موارد به درک بهتر برنامه کمک می کند. ENTITY case_ex2 IS PORT (a : IN INTEGER RANGE 0 to 30; c : OUT INTEGER RANGE 0 to 6); END; ARCHITECTURE rtl OF ex_case2 IS BEGIN case a IS WHEN 0 => b <= 3; WHEN 1 | 2 => b <= 2; WHEN OTHERS’ => b <= 0; END case; END rtl; اگر متغیر case دارای مقادیر و حالت های بسیاری باشد، معین کردن هر حالت کار دشواری خواهد بود. در این حالت از کلمه “OTHERS” استفاده می کنیم.
حلقه FOR LOOP (WHILE LOOP) ENTITY ex IS PORT (a, b, c: IN std_logic_vector (4 downto 0); q : OUT std_logic_vector (4 downto 0)); END ex; ARCHITECTURE rtl OF ex IS BEGIN for I in 0 to 4 LOOP -- (WHILE I <= 4 LOOP) IF a(i) = ‘1’ THEN q(i) <= b(i); ELSE q(i) <= c(i); END IF; END LOOP; END; دستور همزمان Generate معادل دستور ترتیبیFor بوده و برای تکرار استفاده می شود. OK: For I In Range 0 to 7 GENERATE output(i) <= ‘1’ WHEN (a(i) AND b(i))=‘1’ ELSE ‘0’; END GENERATE; خط شامل این دستور باید برچسب داشته باشد.
خاصیت های داده ها: جهت آگاهی از خواص داده ها می توان به صورت زیر عمل نمود d‘LOW: مقدار پایینی اندیس ارایه را بر می گرداند. d‘HIGH: مقدار بالایی اندیس ارایه را بر می گرداند. d‘LEFT: سمت چپ ترین اندیس ارایه را بر می گرداند. d‘RIGHT: سمت راست ترین اندیس ارایه را بر می گرداند. d‘LENGTH: اندازه یا طول بردار را بر می گرداند. d‘RANGE: محدوده بردار را برمی گرداند. d‘REVERSE_RANGE: محدوده بردار را به صورت معکوس برمی گرداند.
خاصیت های سیگنال ها: جهت آگاهی از خواص سیگنال ها می توان به صورت زیر عمل نمود. (فقط دو خاصیت اول قابل سنتز هستند) s‘EVENT: هرگاه سیگنال s تغییر کند (رویدادی داشته باشد) این خاصیت ‘1’ می شود. s‘STABLE: هرگاه سیگنال s تغییر نکند (رویدادی نداشته باشد) این خاصیت ‘1’ می شود. s‘ACTIVE: هرگاه s = ‘1’ باشد مقدار درست را بر می گرداند. s‘LAST_EVENT: مقدار زمان سپری شده از آخرین تغییر سیگنال s را بر می گرداند. s‘LAST_ACTIVE: مقدار زمان سپری شده از آخرین دفعه ای که s = ‘1’ بوده را بر می گرداند. s‘LAST_VALUE: آخرین مقدار s قبل از آخرین تغییر را برمی گرداند.
زمان مقدار ‘1’ 10 ‘0’ 20 b -- b مقدار سیگنال این امکان نیز وجود دارد که چندین مقدار را به یک سیگنال بدهیم. (تاخیرها باید به ترتیب صعودی باشند) C <= ‘1’, ‘0’ AFTER 10 ns, b AFTER 20 ns; زمان مقدار ‘1’ 10 ‘0’ 20 b -- b مقدار سیگنال انواع تاخیرها در VHDL تاخیر درونی تاخیر انتقالی در تاخیر درونی اگر پس از زمان تعیین شده، هنوز سیگنال وجود داشت آن سیگنال در خروجی ظاهر می شود. (برای حذف جهش های نویزی کاربرد دارد) در تاخیر انتقالی، سیگنال مورد نظر پس از تاخیر تعیین شده به خروجی منتقل می شود. A B 10 20 30 40 50 60 ns B1 B2 b1 <= a AFTER 10 ns; b2 < a TRANSPORT AFTER 10 ns;
عبارت فرآیند (Process) فرآیند، یک مجموعه دستور با قالب مشخصی است که دارای یک لیست حساسیت بوده و دستورات مذکور فقط زمانی اجرا می شود که یکی از سیگنال های موجود در لیست حساسیت تغییر کند. در صورتی که در فرآیند از دستور WAIT استفاده شود نیازی به لیست حساسیت نبوده و در صورت تحقق شرط WAIT بدنه فرآیند اجرا می شود. مثلا: wait until clk = ‘1’ Executing Waiting اگر در بدنه یک کد، چندین پروسس تعریف شود همه آنها به صورت همزمان اجرا می شوند. یک پروسس می تواند در حالت اجرا یا انتظار باشد. پروسس بعد از هر بار اجرا مجددا به حالت انتظار می رود. Sync_process: PROCESS BEGIN WAIT UNTIL clk = ‘0’; c_out <= NOT (a_in AND b_in); d_out <= NOT b_in AFTER 10 ns; END PROCESS sync_process;
در VHDL دو نوع پروسس وجود دارد. 1- پروسس ترکیبی 2- پروسس ترتیبی (پالسی) پروسس ترکیبی در یک پروسس ترکیبی تمام سیگنال های ورودی (یعنی آنهایی که در سمت راست علامت (( <= )) یا سیگنال هایی که داخل علامت if/case قرار دارند) باید در لیست حساسیت پروسس وارد شوند. Sync_process: PROCESS (a_in, b_in) BEGIN c_out <= NOT (a_in AND b_in); d_out <= NOT b_in AFTER 10 ns; END PROCESS sync_process; در داخل پرانتز، لیست سیگنال هایی که پروسس با آنها شروع می شود قرار دارد. اگر مثلا a_in از لیست حذف شود، c_out مقدار قبلی خودش را حفظ می کند و تا زمانی که b_in تغییر نکند، مقدار جدید به خودش نمی گیرد.
پروسس ترتیبی (پالسی) پروسس های پالسی همزمان هستند و می توان چند تا از این پروسس ها را با یک پالس ساعت یکسان به هم متصل کرد. example: PROCESS BEGIN WAIT UNTIL clk = ‘1’; d_out <= d_in; END PROCESS example; چنانچه در یک پروسس پالسی مقدار دهی به سیگنال انجام نشود مقدار قبلی خود را حفظ می کند. PROCESS BEGIN WAIT UNTIL clk = ‘1’; IF en = ‘1’ THEN q <= d; END IF; END PROCESS;
عبارت wait چهار روش گوناگون برای بیان لیست حساسیت ها در یک فرآیند وجود دارد. Process (a,b) Wait until a=1; Wait on a,b; Wait for 10 ns; در صورتی که عبارت wait on a,b در انتهای پروسس آورده شود، موارد اول و سوم یکی می شوند. PROCESS (a) BEGIN c1 <= NOT a; END PROCESS; PROCESS BEGIN c2 <= NOT a; WAIT ON a; END PROCESS; PROCESS BEGIN WAIT UNTIL a = ‘1’; c4 <= NOT a; END PROCESS; PROCESS BEGIN c5 <= NOT a; WAIT UNTIL a = ‘1’ FOR 10 ns; END PROCESS;
مثال: یک DFF با ورودی ریست سنکرون -------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY dff IS port(d, clk, rst: IN STD_LOGIC; q: OUT STD_LOGIC); END dff; ARCHITECTURE behavior OF dff IS BEGIN sve: PROCESS(rst,clk) IF (rst='1') THEN q <= '0'; ELSIF (clk'EVENT AND clk='1') THEN q <= d; END IF; END PROCESS sve; END behavior; مثال: یک DFF با ورودی ریست سنکرون
مثال: طراحی یک DFF به همراه گیت NAND ENTITY example IS PORT (a, b, clk : IN BIT; q: OUT BIT); END example ; ARCHITECTURE example of example IS SIGNAL temp : BIT; BEGIN temp <= a nand b; PROCESS (clk) IF (clk ‘EVENT and clk = ‘1’) then q <= temp; END IF; END PROCESS; مثال: طراحی یک DFF به همراه گیت NAND در مثال های قبل، هیچ گونه تاخیری برای اجزای مدار وجود ندارد. حال می خواهیم از دستور AFTER برای ایجاد تاخیر استفاده کنیم. ARCHITECTURE my_arch of nand_gate IS BEGIN x <= a NAND b AFTER 10 ns; -- Component Delay = 10 ns END my_arch ;
مثالی از مدل رفتاری یک Multiplexer در صورتی که در برنامه مجبور باشیم حالتهای زیادی را با استفاده از WHEN ELSE پیاداه سازی نماییم می توانیم برای راحتی از WITH استفاده کنیم. همان مثال قبل را این بار با استفاده از دستور WITH می نویسیم. ENTITY mux2 IS PORT (sel_0, a, b: IN std_logic; q: OUT std_logic); END mux2; ----------------------------------- ARCHITECTURE mux2_with OF mux2 IS BEGIN WITH sel_0 SELECT c <= a AFTER 10 ns WHEN ‘0’, b AFTER 10 ns WHEN OTHERS; END mux2_with; پارامترهای عمومی (generic) ENTITY nand_gate IS GENERIC (delay: time:=10ns); PORT (a, b: IN BIT; x: OUT BIT); END nand_gate; ARCHITECTURE my_arch of nand_gate IS BEGIN x <= a NAND b AFTER delay; END my_arch ; این پارامترها معمولا برای تعریف پارامترهایی که در بخش های مختلف برنامه استفاده می شود کاربرد دارند. در بخش موجودیت و قبل از تعریف پورت ها تعریف می شوند.
مثال: طراحی یک دیکودر ena Sel x 00 1111 1 01 10 11 1110 1101 1011 0111 LIBRARY ieee; USE ieee.std_logic_1164.all; -------------------------------------------------------- ENTITY decoder IS PORT( ena : IN std_logic; sel : IN std_logic_vector (2 downto 0); x : OUT std_logic_vector (7 downto 0)); END decoder; ARCHITECTURE generic_decoder OF decoder IS BEGIN PROCESS (ena, sel) VARIABLE temp1: std_logic_vector (x'HIGH downto 0); VARIABLE temp2: integer RANGE 0 to x'HIGH; temp1 := (OTHERS => '1'); temp2 := 0; IF (ena='1') then FOR i in sel'RANGE LOOP -- sel range is 2 downto 0 IF (sel(i)='1') THEN -- bin to integer conversion temp2 := 2*temp2+1; ELSE temp2 := 2*temp2; END IF; END LOOP; temp1(temp2) := '0'; x <= temp1; END Process; END generic_decoder; مثال: طراحی یک دیکودر ena Sel x 00 1111 1 01 10 11 1110 1101 1011 0111
مثال: پیاده سازی یک RAM LIBRARY ieee; USE ieee.std_logic_1164.all; -------------------------------------------------------- GENERIC ( bits : INTEGER := 8; words : INTEGER := 16); ENTITY ram IS PORT( wr_ena, clk: IN std_logic; addr: IN INTEGER RANGE 0 to words-1; data_in: IN std_logic_vector (bits-1 downto 0)); data_out: OUT std_logic_vector (bits-1 downto 0)); END ram; ARCHITECTURE ram OF ram IS TYPE vector_array IS ARRAY (0 TO words-1) OF std_logic_vector (bits-1 downto 0); SIGNAL memory: vector_array; BEGIN PROCESS (clk, wr_ena) IF (wr_ena='1') then IF (clk’EVENT AND clk = ‘1’) THEN memory(addr) <= data_in; END IF; ELSEIF (wr_ena=‘0') then IF (clk’EVENT AND clk = ‘1’) THEN data_out<= memory(addr); END Process; مثال: پیاده سازی یک RAM
توصیف ساختاری یک سخت افزار در روش توصیف ساختاری، ابتدا اجزای آن سیستم لیست شده و سپس اتصالات بین آنها مشخص می شوند. این روش معرفی چون به سخت افزار واقعی نزدیک تر است، فهم آن راحت تر می باشد. برای توصیف این روش از یک مثال استفاده می کنیم. می خواهیم یک مقایسه کننده یک بیتی بسازیم. این مقایسه کننده دو بیت ورودی را با هم مقایسه کرده و بسته به پایه های کنترل یکی از 3 پایه خروجی را یک می کند. A B > = < A>B A=B A<B Comparator
ابتدا می خواهیم گیت های NAND ی که در این طرح به کار رفته است را تعریف کنیم. البته این گیتها می توانند داخل طرح ما تعریف شده و یا یکی از قطعات موجود در کتابخانه های پیش فرض باشند. بعد از تعریف گیتهای مورد نیاز به شیوه ای مشابه همان که ترانزیستورها را در مدارات به هم وصل می کنیم اتصالات این گیتها را در برنامه برقرار می کنیم. مدل معکوس کننده عناصر مورد استفاده در این مدل Input port Entity name Output port Bidirectional port Buffer port o1 i1 inv
کد VHDL برای این معکوس کننده ENTITY inv IS PORT ( I1 : IN BIT; O1 : OUT BIT); END inv; ARCHTECTURE single_delay OF inv IS BEGIN o1 <= NOT I1 AFTER 4 ns; END single_delay; TIME یک نوع داده از پیش تعریف شده است و حداقل آن 1 فمتو ثانیه (15-10 ثانیه) می باشد. مدل گیت NAND دو ورودی کد VHDL برای این معکوس کننده ENTITY nand2 IS PORT ( I1, I2 : IN BIT; O1 : OUT BIT); END inv; ARCHTECTURE single_delay OF nand2 IS BEGIN o1 <= I1 nand I2 AFTER 5 ns; END single_delay; o1 i1 nand2 i2
کد VHDL برای این معکوس کننده مدل گیت NAND سه ورودی کد VHDL برای این معکوس کننده ENTITY nand3 IS PORT ( I1, I2 : IN BIT; O1 : OUT BIT); END inv; ARCHTECTURE single_delay OF nand3 IS BEGIN o1 <= NOT (I1 and I2 and I3) AFTER 5 ns; END single_delay; o1 i1 nand3 i2 i3 برقراری اتصال میان گیت ها در VHDL می توان عملکرد یک مدار را به وسیله اتصال اجزای کوچکتر آن توصیف کرد. ابتدا به معرفی مجدد منطق مداری که می خواهیم طراحی کنیم می پردازیم.
این مدار دو ورودی اصلی و سه ورودی کنترل دارد. خروجی A>B زمانی یک است که یا A بزرگتر از B باشد یا A مساوی B بوده و ورودی کنترل > یک باشد. خروجی A=B زمانی یک است که A مساوی B بوده و ورودی = یک باشد. خروجی A<B عکس حالت اول است. تابع جبری برای این مدار به صورت زیر است. a_gt_b = a.gt + b’.gt + a.b‘ a_eq_b = a.b.eq + a’.b’.eq a_lt_b = a’.lt + b.lt + a’.b
این مدار با استفاده از اجزای کوچکتر خود ساخته می شود. o1 i1 nand3 i2 i3 nand2 inv a_gt_b gt eq lt a_lt_b a_eq_b a b این مدار با استفاده از اجزای کوچکتر خود ساخته می شود. اسامی تکراری برای ورودی و خروجی های این مدار به کار رفته است. a_gt_b gt Bit_comparator eq lt a_lt_b a_eq_b a b
ENTITY bit_comparator IS PORt ( a, b, gt, eq, lt : IN BIT; a_gt_b, a_eq_b, a_lt_b : OUT BIT); END bit_comparator ARCHITECTURE gate_level OF bit_comparator IS COMPONENT n1 PORT (i1 : IN BIT; o1 : OUT BIT); END COMPONENT; COMPONENT n2 PORT (i1 , i2 : IN BIT; o1 : OUT BIT); END COMPONENT; COMPONENT n3 PORT (i1 , i2 , i3 : IN BIT; o1 : OUT BIT); END COMPONENT; FOR ALL: n1 USE ENTITY WORK.inv (single_delay); FOR ALL: n2 USE ENTITY WORK.nand2 (single_delay); FOR ALL: n3 USE ENTITY WORK.nand3 (single_delay); -- Intermediate signals SIGNAL im1, im2, im3, im4, im5, im6, im7, im8, im9, im10: BIT; BEGIN -- a_gt_b output G0: n1 PORT Map (a, im1); G1: n1 PORT Map (b, im2); G2: n2 PORT Map (a, im2, im3); G3: n2 PORT Map (a, gt, im4); G4: n2 PORT Map (im2, gt, im5); G5: n3 PORT Map (im3, im4, im5, a_gt_b);
ادامه از صفحه قبل -- a_eq_b output G6: n3 PORT Map (im1, im2, eq, im6); G7: n3 PORT Map (a, b, eq, im7); G8: n2 PORT Map (im6, im7, a_eq_b); -- a_lt_b G9: n2 PORT Map (im1, b, im8); G10: n2 PORT Map (im1, lt, im9); G11: n2 PORT Map (b, lt, im10); G12: n3 PORT Map (im8, im9, im10, a_lt_b); END gate_level; این روش برای طرح های بزرگ و هنگامی که طراحان مختلف بر روی یک طرح کار می کنند مناسب تر است. در این روش (معماری ساختاری قطعه)، ابتدا اجزای مورد استفاده را معرفی می کنیم. سپس با مشخص کردن مرجع، در واقع محل تعریف این جزء را برای VHDL مشخص می کنیم. در نهایت با MAP کردن پورت ها به اتصال اجزای مختلف طبق نقشه مدار می پردازیم.
Test Bench بعد از نوشتن یک کد VHDL و قبل از پیاده سازی آن بر روی FPGA معمولا لازم است تا از صحت عملکرد آن در شرایط مختلف ورودی اطمینان حاصل کنیم. یکی از روش های تایید درستی طرح، نوشتن برنامه یک مدل آزمایشی برای تست و بررسی خروجی های ناشی از کد مورد نظر است. این کار به معنای طراحی یک محیط آزمایشی است که هم سیگنال های ورودی را در اختیار می گذارد و هم سیگنال های خروجی طرح را مورد آزمایش قرار می دهد. بررسی وضعیت ورودی و خروجی ها در یک نرم افزار شبیه ساز انجام می شود. یکی از معروفترین نرم افزار های شبیه سازی ModelSim می باشد. مزایای شبیه سازی: محرک های اجزای ترکیبی توسط مدل هایی که بیانگر سیگنال های حقیقی هستند تولید می شوند. نیازی به تکنولوژی و اجزای جانبی دیگری ندارد. سرعت شبیه سازی بالاست
به هر حال کار اضافی است و زمانبر است. معایب شبیه سازی: به هر حال کار اضافی است و زمانبر است. چون خود نوشتن این برنامه تست هم توسط خود طراح نوشته می شود ممکن است اشتباهات مشابهی تکرار شود. در حالت کلی، محیط آزمایش از دو بخش تشکیل می شود. بخش تولید سیگنال های ورودی و ارتباط آن به مدار مورد نظر چک کردن سیگنال های خارج شده از سیستم In_model <= ‘1’ AFTER 5 ns, ‘0’ AFTER 100 ns, ‘1’ AFTER 200 ns, ‘0’ AFTER 300 ns + 4 ns; Clk <= NOT clk AFTER 50 ns; بخش 1: چگونگی تولید سیگنال های ورودی در این مثال، سیگنال clk بعد از هر 50 نانو ثانیه عکس می شود. اگر در تعریف این سیگنال از نوع std_logic استفاده شود ممکن است مشکلی به صورت زیر به وجود آید. در VHDL کلیه سیگنال ها دارای مقدار اولیه پیش فرضی معادل سمت چپ ترین ارزش در تعریف نوع داده اند. در حالت Bit مقدار اولیه صفر و لی در حالت std_logic مقدار اولیه ‘U’ خواهد بود. برای حل این مشکل باید در تعریف سیگنال مقدار اولیه مورد نظر را نیز اعمال کنیم. SIGNAL clk: STD_LOGIC := ‘0’
البته امکان انتظار به اندازه چندین پالس ساعت هم وجود دارد. In_vect <= “00” AFTER 5 ns, “01” AFTER 100 ns, “10” AFTER 200 ns, “11” AFTER 300 ns + 4 ns; PROCESS BEGIN in_s1 <= ‘1’; in_s2 <= ‘0’; WAIT UNTIL reset = ‘1’; WAIT UNTIL clk= ‘1’; in_s1 <= ‘0’; in_s2 <= ‘1’; چنانچه المان تست شونده ترتیبی باشد، از دستور wait برای نسبت دادن سیگنال ها به ورودی استفاده می شود. یک روش دیگر برای انتظار لبه پالس ساعت، تولید زمان دوره تناوب آن است. با این روش مدل رفتاری دیگر نیازی به سیگنال Clk ندارد. البته امکان انتظار به اندازه چندین پالس ساعت هم وجود دارد. CONSTANT period : TIME := 50 ns; WAIT FOR period; WAIT FOR 2 * period;
محیط های آزمایش به سه کلاس تقسیم بندی می شوند. در کلاس اول که ساده ترین کلاس است، تنها سیگنال های ورودی مدل تولید می شوند و سیگنال های خروجی به صورت دستی و در محیط شبیه ساز مورد بررسی قرار می گیرند. این روش ساده و در عین حال برای مدارهای ساده بسیار مفید است. البته در مدارهای با تعداد زیاد ورودی و خروجی عملا کاربردی ندارد. در کلاس 2 نه تنها سیگنال های ورودی تولید می شوند بلکه درستی ارزش سیگنال های خروجی هم بررسی می شوند. در کلاس 3 تحلیل زمانی هم در برنامه صورت می گیرد. D_out D_in My_comp a b overflow en clk resetn q Test_My_comp LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY test_my_comp IS PORT (d_out, en, overflow : OUT std_logic; q: OUT std_logic_vector (2 DOWNTO 0)); END; ARCHITECTURE testbench OF test_my_comp IS COMPONENT my_comp PORT (clk, resetn, d_in : IN std_logic; a, b: IN std_logic_vector (2 DOENTO 0); d_out, en: OUT std_logic; overflow: OUT std_logic; q: OUT std_logic_vector (2 DOWNTO 0); END component;
SIGNAL clk: std_logic:= ‘0’; SIGNAL resetn: std_logic:= ‘0’; SIGNAL d_in: std_logic:= ‘0’; SIGNAL a, b: std_logic_vector (2 DOENTO 0); FOR U1: my_comp USE ENTITY work.my_comp (rtl); BEGIN U1: my_comp PORT MAP (clk, resetn, d_in, a, b, d_out, en, overflow, q); clk <= NOT clk AFTER 50 ns; resetn <= ‘1’ AFTER 125 ns; a <= “000”, “010” AFTER 125 ns, “100” AFTER 175 ns; b <= “000”, “100” AFTER 125 ns, “011” AFTER 175 ns; PROCESS d_in <= ‘0’; WAIT UNTIL resetn = ‘1’; d_in <= ‘1’; WAIT UNTIL clk = ‘1’; d_in <= ‘0’ AFTER 10 ns; WAIT; END PROCESS; END;
تمرین 1: یک جمع کننده 4 بیتی بسازید تمرین 1: یک جمع کننده 4 بیتی بسازید. این جمع کننده باید دو عدد چهار بیتی دودویی را به عنوان ورودی دریافت کرده و حاص جمع آن را در خروجی نمایش دهد. تمرین 2: ماژولی بسازید که 8 ورودی و 3 خروجی دارد. مدار مورد نظر باید تعداد صفرهای داده ورودی را بشمارد و تعداد صفرها را به صورت دودویی در خروجی خود نشان دهد. تمرین 3: یک شیفت رجیستر 4 بیتی شامل ورودی ریست آسنکرون طراحی کنید. تمرین 4: یک مدار شمارنده BCD با لبه های بالا رونده و پایین رونده کلاک طراحی کنید. این مدار، 1 ورودی کلاک و 4 خروجی برای شمردن دارد. با هر بار لبه بالا رونده یا پایین رونده کلاک، خروجی یک واحد افزایش می یابد.