در این آموزش از سری آموزشهای گام به گام نرم افزار Hspice در مورد کاربرد subcircuit ها در برنامه نویسی با اچ اس پایس و نحوه استفاده از آنها صحبت خواهیم کرد. ابتدا به تعریف زیر مدار و کاربرد آن را در ساده سازی کد نویسی ها می پردازیم و در بخش بعدی کاربرد آن را درعمل نشان می دهیم و یک زنجیره اینورتری را با استفاده از زیر مدار کد نویسی کرده و در انتها نتایج شبیه سازی را مورد تجزیه و تحلیل قرار خواهیم داد.
subcircuit چیست و چه کاربردی در کد نویسی دارد؟
اگر بخواهیم یک زیرمدار یا subcircuit را به زبان ساده تعریف کنیم با ذکر یک مثال شروع می کنیم. در واقع کد نویسی به این معناست که هر آن چه را در دنیای واقعی می بینیم بتوانیم به کامپیوتر بفهمانیم و هوش کامپیوتر به اندازه ذهن انسان قدرتمند نیست که بتواند مسایل را آنگونه که ما درک می کنیم تفسیر کند و هر چیزی را باید با جزییات کامل برای کامپیوتر تعریف کنیم.
اما گاهی اوقات نیاز است که برخی از مسایل تکراری را که تعریف مشخصی دارند چنیدن بار استفاده کنیم و اگر بخواهیم هر بار از اول این کار را انجام دهیم بسیار وقت گیر و خسته کننده خواهد شد. به عنوان مثال فرض کنید که یک کامیون بیسکویت داریم. داخل هر بسته ۱۲ عدد بیسکویت قرار دارد و یک کارتن کوچک بیسکویت شامل ۱۰ بسته و یک کارتن بزرگ می تواند ۲۰ کارتن کوچک را در خود جای دهد و یک کامیون قادر به حمل ۱۰۰ کارتن بزرگ می باشد.
اگر نیاز باشد مثال فوق را به صورت کد نویسی در بیاوریم و در طول برنامه نویسی چندین بار کامیون بیسکویت را تکرار کنیم هر بار باید از اول به کامپیوتر بفهمانیم که یک کامیون شامل کارتن بزرگ است و داخل هر کارتن بزرگ چند کارتن کوچک قرار دارد و هر کارتن کوچک می تواند چند بسته را در خود نگه دارد و هر بسته شامل چند عدد بیسکویت است.
اگر مثال فوق نیاز به ۵ خط برنامه نویسی داشته باشد و نیاز باشد ده بار آن را در طول برنامه تکرار کنیم می بینیم که نیاز به ۵۰ خط کد نویسی داریم که علاوه بر افزایش حجم برنامه تعریف کردن تعداد زیادی متغیر غیر تکراری که تشابه اسمی نداشته باشند کاری بس دشوار است.
اما اگر همین مثال را با زیر برنامه ها بنویسیم و یک بار کامیون بیسکویت را به صورت زیر برنامه تعریف کنیم خواهیم توانست با هر بار فراخوانی تنها با یک خط کدنویسی منظورمان را به کامپیوتر بفهمانیم و به جای ۵۰ خط برنامه نویسی تنها با ۱۵ خط کار را به اتمام برسانیم.
مثال فوق برای درک فیزیکی مساله بود و یک حالت کلی داشت اگر بخواهیم کمی تخصصی تر مساله را موشکافی کنیم و آن را به مدارات الکترونیکی تعمیم دهیم می توانیم گیت های منطقی را مثال بزنیم.
در مدارات دیجیتالی گیت های منطقی بسیار تکرار خواهند شد و همانطور که می دانیم این گیت ها از ترانزیستورها تشکیل یافته اند و به عنوان نمونه یک گیت AND چهار ورودی از ده عدد ترانزیستور تشکیل شده است که اگر بخواهیم آن را به صورت زیر مدار در بیاوریم و چنیدن بار در یک مدار استفاده کنیم کارمان بسیار ساده تر خواهد شد.
کدنویسی در مدارات پیچیده تر بدون استفاده از subcircuit ها عملاً غیر ممکن خواهد شد به طور مثال در یک CPU چند میلیارد ترانزیستور قرار دارد که اگر بخواهیم برای هر ترانزیستور یک خط کد بنویسیم کاری نشدنی است و حتی اگر جنبه پیچیدگی آن را کنار بگذاریم نرم افزار Hspice تعداد خطوط برنامه نویسی محدودی را می پذیرد و حتی نسخه های جدیدتر آن بیش از چند صد هزار خط کد نویسی را پردازش نمی کند.
کد نویسی یک زنجیره اینورتری با استفاده از زیرمدارات
یک زنجیره اینورتری که شماتیک آن را در شکل زیر مشاهده می کنید از چندین گیت not پشت سر هم تشکیل شده است. که در این مثال خاص تعداد گیت های not که به دنبال هم دیگر قرار می گیرند ۴ عدد است و می تواند بسته به کاربرد به n عدد هم افزایش پیدا کند.
یکی از کاربردهای این مدار ایجاد یک واحد تاخیر یا همان Delay Cell است که برای تولید آن حتما باید تعداد اینورترها زوج باشد. وقتی که یک سیگنال را به وروی Delay Cell اعمال می کنیم هیچ تغییری در ماهیت سیگنال ایجاد نخواهد شد ، فقط بین ورودی و خروجی واحد تاخیر یک وقفه زمانی رخ خواهد داد که در مدارات دیجیتالی در موارد بسیاری از جمله در بحث زمان بندی و یا رفع گلیچ به این تاخیر نیاز داریم و هر چه قدر تعداد اینورترهای پشت سر هم بیشتر باشد تاخیر نیز به همان اندازه افزایش پیدا می کند.
از کاربردهای دیگر زنجیره اینورتری می توان به بازیابی سیگنالها ، حذف نویز ، نوسان سازهای حلقوی و … اشاره نمود.
طراحی مدار داخلی اینورتر را در بخش قبلی مورد بررسی قرار دادیم و دیدیم که گیت not از دو عدد ترانزیستور nmos و pmos تشکیل یافته است بنابراین به دو خط کد نویسی برای تعریف دو ترانزیستور نیاز خواهیم داشت که در صورت استفاده از زیر مدار تعداد خطوط مورد نیاز برای آن به نصف کاهش پیدا می کند.
برای یک مدار ساده مانند زنجیره اینورتری شاید این مساله زیاد به چشم نیاید اما در مدارات دیجیتال پیچیده می بینیم که تعداد گیت های not استفاده شده بسیار زیاد می باشد و همین زیر مدار کوچک به ساده تر شدن برنامه کمک زیادی می کند.
برای نوشتن یک زیر مدار از دستور subckt. استفاده می کنیم و هر آنچه را که درون یک مدار که قرار است بعداً فراخوانی شود ، وجود دارد ، داخل آن تعریف خواهیم نمود. برای مشخص نمودن انتهای یک subcircuit از دستور ends. استفاده می کنیم. برای نوشتن زیر مدار یک اینورتر به صورت زیر عمل می کنیم.
subckt INV in out.
m1 out in vdd vdd mp18 w=3u l=0.18u
m2 out in ۰ ۰ mn18 w=1u l=0.18u
ends INV.
در اولین سطر که با دستور subckt. آغاز می شود به ترتیب نام زیر مدار و گره های مورد نیاز را که قرار است فراخوانی شود می نویسیم که در اینجا یک نام دلخواه (INV مخفف INVERTER) را برای زیر مدار انتخاب می کنیم و بعد گره های in و out را که در زیر مدار استفاده شده به عنوان گره ورودی و خروجی تعریف می کنیم.
در داخل زیر مدار همانطور که قبلاً هم گفتیم مدار داخلی گیت not را که شامل دو عدد ترانزیستور است و ما آن را با m1,m2 نامگذاری کرده ایم تعریف می کنیم در انتها دستور .ends را که بعد از آن نام زیر مدار تکرار می شود قرار خواهیم داد که به معنی اتمام زیر مدار است و بعد از آن می توانیم دستورات بعدی یا مدارات دیگری را به همان روال عادی که قبلاً کد نویسی می کردیم قرار دهیم.
نکته ۱: اگر در ادامه .ends چیزی ننویسیم باز هم مشکلی پیش نمی آید ولی نوشتن دوباره نام زیر مدار در انتهای .ends به خوانا شدن کد نویسی ها کمک خواهد کرد پس از اینجا به بعد همیشه این کار را انجام می دهیم.
حال اگر بخواهیم در جایی از برنامه گیت not را فراخوانی کنیم با نوشتن عبارت X این کار را انجام خواهیم داد مثلاً نوشتن عبارت زیر به این معنی است که بین گره a و b یک اینورتر وجود دارد.
X1 a b INV
اگر بخواهیم کمی جزئی تر مساله را بررسی کنیم می توانیم گیت not را به صورت یک تابع در نظر بگیریم که کاری با محتویات درون آن نداریم و اگر یک ورودی را به این تابع بدهیم خروجی مورد انتظارمان را دریافت خواهیم نمود. در این مثال گره a به جای گره in و گره b به جای out در مدار گیت not عمل می کند و رعایت ترتیب حتماً ضروری است مثلاً اگر جای a و b را عوض کنیم کارکرد مدار به هم میریزد.
نکته ۲: گره هایی که در subcircuit ها تعریف می شوند گره محلی (Local) هستند و در داخل همان زیر مدار اعتبار دارند مثلاً اگر گره in و out را دوباره در برنامه اصلی استفاده کنیم هیچ مشکلی پیش نمی آید.
نکته ۳: برای اینکه از یک گره مشترک هم در داخل زیر مدارات و هم در داخل برنامه اصلی استفاده کنیم از دستور global. استفاده می کنیم. مثلاً دستور global vdd. به این معنی است که در هر جایی از برنامه گره vdd وجود داشت آنها را به هم متصل کند و یک گره عمومی به حساب بیاید.
می توانیم در داخل یک زیر مدار ، زیر مدار دیگری را تعریف کنیم. مثلاً می توانیم زنجیره اینورتری را به صورت یک زیر مدار دربیاوریم که داخل خود آن هم چنیدن زیر مدار دیگر ، شامل گیت های not پشت به پشت بسته شده وجود دارد. شکل زیر مدارداخلی یک زنجیره اینورتری را نشان می دهد.
برای کد نویسی این مدار هم می توانیم ۸ عدد ترانزیستور را تعریف کنیم و آن را مستقیماً بنویسیم و هم می توانیم با استفاده از زیر مدارات آن را کد نویسی کنیم. روش اول نیازی به توضیح خاصی ندارد و قبلاً در مورد آن بحث نمودیم روش دوم را با نام گذاری گره های ورودی و خروجی و داخلی به صورت زیر کد نویسی می کنیم.
همانطور که می بینیم دو زیر مدار خواهیم داشت که اولی مربوط یه گیت not می شود و دومی مربوط واحد تاخیر است که از چهار گیت not تشکیل یافته و با نام Delay نامگذاری کرده ایم. و در خط ۱۸ آن را فراخوانی نموده ایم.
نکته ۴: علامت ستاره چین که در خط ۱۶ گذاشته شده هیچ تاثیری در روند برنامه نویسی ندارد و صرفاً جهت مرتب سازی و نظم دادن به برنامه گذاشته شده و اگر جایی از برنامه بخواهیم دستوری را بی اثر کنیم ولی آن را داشته باشیم می توانیم جلوی آن یک ستاره بگذاریم.
نکته ۵: برای فراخوانی کتابخانه تکنولوژی فایل ۰٫۱۸um لزومی ندارد که حتماً در همان پوشه ای که برنامه را می نویسیم آن را داشته باشیم. و میتوانیم آدرس جایی که تکنولوژی فایل در آن قرار دارد را قبل از نام فایل بگذاریم.
تجزیه و تحلیل نتایج شبیه سازی زنجیره اینورتری در نرم افزار Spice explorer
نتایج شبیه سازی زنجیره اینورتری را که با استفاده از subcircuit ها کد نویسی کرده ایم در شکل زیر مشاهده می کنیم. همانطور که می بینیم چون تعداد اینورترها زوج است (چهار عدد اینورتر) خروجی دقیقاً عین ورودی است با این تفاوت که مقداری (به اندازه تاخیر ۴ گیت not) شیفت داده شده است.
برای محاسبه تاخیر delay cell شکل رو زوم می کنیم و فاصله زمانی بین لحظه ای که شکل موج ورودی به ۵۰ درصد مقدار نهایی خود می رسد (۰٫۹v) با لحظه ای که موج خروجی هم به همین مقدار می رسد را محاسبه خواهیم کرد. این کار را هم در حالتی شکل موج های ورودی و خروجی صعودی هستند (تغییر وضعیت از صفر به یک منطقی) و هم در حالت نزولی (تغییر وضعیت از یک به صفر منطقی) محاسبه خواهیم کرد و از طریق فرمول زیر تاخیر قابل محاسبه خواهد بود.
Delay=tr+tf/2
همانطور که می بینیم زمان های صعود و نزول به ترتیب برابر ۳۰۶psec و ۱۷۳psec می باشد که مقدار تاخیر با توجه به فرمول بالا حدود ۲۴۰ پیکو ثانیه به دست می آید.
برای دریافت مشاوره انجام پروژه های دانشگاهی وارد صفحه انجام پروژه hspice سایت استاد راهنما شوید.