به نام خدا!

سلام عرض میکنم خدمت شما...

توی این بحث هم یه شبیه سازی انجام دادم و دیگه هیچی پس دانلودش نکنید

راستش اینا رو برای خودم که تازه کار هستم ضبط کردم و قطعا هیچ یک از شما بزرگواران نیازی به آموش های سطح پاییین بنده ندارید!

بنابراین اکیدا توصیه میکنم دانلود نکنید :)

راستش چون میترسیدم اینا یادم بره ضبط کردم و هم توی کامپیوتر دارم و هم آپلودش کردم که داشته باشم! ولی اگه شما همین الان FPGA خریداری کردید و حتی دانشجو هم نیستید این آموزشای ساده ی من فقط به درد شما میخوره! :)


1) تمام جمع کننده چهار بیتی با FPGA و زبان VHDL

برای دانلود روی لینک زیر کلیک کنید 8 دقیقه است! (میدونم حجمش خیلی بالاست...)

کدی که توی آموزش هست به صورت زیره!

library ieee;
use ieee.std_logic_1164.all;

Entity Adder4bit is
        port(
 a : in std_logic_vector (3 downto 0);
 b : in std_logic_vector (3 downto 0);
 Cin : in std_logic;
        s : out std_logic_vector (3 downto 0);
 Cout:out std_logic
 );
 
End Entity;

Architecture behavioral of Adder4bit is
signal c1,c2,c3 : std_logic;
 Begin
 
c1<=a(0) and b(0);  
s(0)<=a(0) xor b(0);

c2<=(a(1) and b(1))or(a(1) and c1)or(b(1) and c1);
s(1)<=a(1) xor b(1) xor c1;

c3<=(a(2) and b(2))or(a(2) and c2)or(b(2) and c2);
s(2)<=a(2) xor b(2) xor c2;
cout<=(a(3) and b(3))or(a(3) and c3)or(b(3) and c3);
s(3)<=a(3) xor b(3) xor c3;

 
End Architecture; 

2) تقسیم فرکانس کلاک

آموزشش رو ضبط کردم ولی چون هیچی نداشت قرار ندادم! نکاتش رو فقط مینویسم!

از این سایت برای یادگیری کمک بگیرید!

اینم کد من!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Clock_Div is
port (
   Clk_In :in std_logic;
Sig_out : out std_logic
);
end Clock_Div;
 
architecture Div of Clock_Div is
   signal Counter : unsigned (2 downto 0);
begin
process (CLK_IN)
begin

if rising_edge (CLK_IN) then
Counter <= Counter + 1;
end if;
end process;
Sig_out<= Counter(2);
end Div;

امیدوارم مفید بوده باشه!


3) تولید کننده مدولاسیون عرض پالس PWM

خوب کدش به صورت زیر هست و توضیحاتش هم زیر کد نوشتم!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.Numeric_std.ALL;

entity GenPWM is
	generic(PWMFreq: std_logic_vector := x"fff"; -- fff = 4095
			  Res : integer := 8;  -- resolution 2^8 = 256	-> 0 to 255
			  DutyCycle : integer := 128);	-- Duty 128 from 256 -> %50
	port (
			PWM : out std_logic;
			CLK : in Std_logic);
end GenPWM;

architecture Behavioral of GenPWM is
	-------- Define Signals ------------
	signal Counter : unsigned (Res-1 downto 0)	:= (OTHERS=>'0');
	signal PWM_out : std_logic;
	signal CounterPWMFreq	: unsigned (PWMFreq'length downto 0) := (OTHERS=>'0');
	
begin
	
	process (CLK)
	begin
		if rising_edge (CLK) then
			CounterPWMFreq	<=	CounterPWMFreq + 1;

			if  (CounterPWMFreq = ((unsigned (PWMFreq))/(2**(Counter'length))))	then
			CounterPWMFreq	<= (OTHERS=>'0');
			Counter	<= Counter + 1;
		
				if  (Counter >= DutyCycle)	then
				PWM_OUT	<= '0';
				else
				PWM_OUT	<= '1';
				end if;
			end if;
		end if;
	end process;
	
	PWM	<= PWM_OUT;

end Behavioral;

خوب توی کد بالا PWMFreq فرکانس PWM هست! یعنی عددی رو که به این متغییر نسبت میدید رو اگه بر سرعت کلاک خارجی تون تقسیم کنید میفهمید چند بار توی ثانیه PWM تکرار میشه! مثلا اگه سرعت کلاک خارجی (اسیلاتورتون) 50 مگاهرتز باشه و شما PWMFreq رو هم روی 50 مگاهرتز تنظیم کنید! حالا دیوتی سایکلتون مدت زمان روشن بودن LED رو مشخص میکنه! مثلا فرض کنید بیشترین مقدار PWM برابر با 255 باشه و شما دیوتی سایکل رو روی 128 میزارید که میشه 50 درصد! با این تفاسیر باید LED شما در ثانیه یکبار روشن و خاموش بشه!

ولی اگه اون PWMFreq رو که روی 50 مگاهرتز گذاشته بودید رو روی 25 مگاهرتز بزارید حالا در ثانیه دوبار خاموش و روشن میشه (یعنی کل PWM دوبار در ثانیه تکرار میشه -> 25M/50M=2 اینجوری میشه حسابش کرد) بنابراین هرچه مقدار PWMFreq کمتر باشه PWM توی یه ثانیه بیشتر تکرار میشه! شاید بگید خوب چه فرقی میکنه که فرکانس PWM چقدر باشه؟ (یعنی چه فرقی میکنه که PWM توی یه ثانیه چند بار تکرار میشه؟) دلیلیش اینه که اگه مثلا قرار باشه توی یه ثانیه : 0.5 ثانیه روشن باشه و 0.5 ثانیه خاموش (یعنی دیوتی سایکل 50 درصد) چشم ما میفهمه که خاموش و روشن میشه ولی اگه سریع روشن و خاموش بشه چشم ما نمیتونه تشخیص بده پس فک میکنه که نور LED کمتره و...! خوب اینا مفاهیم PWM هست که اگه هنوز متوجه نشدید میتونید توی گوگل سرچ کنید تا چیزیای بیشتری گیرتون بیاد!

نکته: برای شبیه سازی باید زمان بیشتری رو شبیه سازی کنید!

نکته: کد نوشته شده برای PWM با دقت 8 بیت است یعنی حداقل PWM مقدار 0 و حداکثر آن 255 است!

نکته: مقدار دیوتی سایکل رو میتونید از قسمت DutyCycle تغییر بدید! (الان 128 از 255 هست یعنی 50 درصد)
نکته : برنامه رو طوری نوشتم که نیاز به دست کاری و تغییر مقادیر بیتی نباشه (غیر از اون سه مورد PWMFreq و Res و DutyCycle که برای تنظیم PWM باید بهش مقدار بدید) 

نکته: میتوانید با تغییر مقدار Res دقت PWM رو افزایش یا کاهش دهید! (مثلا الان 8 بیتی یعنی از 0 تا 255 است ( 256 = 8^2 ) میتوانید آنرا 4 بگذارید تا از 0 تا 15 باشد یعنی دقت PWM کاهش دهید)


4) ساخت ارسال کننده UART Transmitter

خوب توی این کد فقط قسمت فرستنده راه اندازی شده! این کد با باود ریت 19200 کار میکنه! بیت پریتی نداره و دیتاش 8 بیتی هست!

یه کتاب خیلی مفید و کاربردی هست که میتونید از اینجا دانلود کنید!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.Numeric_STD.ALL;
-- Baud Rate: 19200
entity UART is
generic (Data : std_logic_vector (7 downto 0) := "01000001" -- char Ascii 'A'
);
    Port ( 
TX  : out  STD_LOGIC;
CLK : in  STD_LOGIC);
end UART;
architecture Behavioral of UART is
signal UartClock : std_logic;
signal TxBuffer : std_logic_vector (15 downto 0);
begin
TxBuffer (0) <= '0'; -- start bit
TxBuffer (8 downto 1) <= Data ; -- 8 bit data
TxBuffer (9) <= '1'; -- stop bit
TxBuffer (15 downto 10)    <= "111111";   -- idle bits


process (CLK)
variable CounterPulse:integer range 0 to 3000;
begin
if rising_edge (CLK) then
CounterPulse := CounterPulse+1;
if ( CounterPulse = 1302 ) then -- 2604/2 = 1302
UartClock <= '0';
elsif (CounterPulse = 2604) then -- 50000000/19200 ~= 2604
CounterPulse:= 0;
UartClock <= '1';
end if;
end if;
end process;
process (UartClock)
variable CounterWord : integer range 0 to 15; 
begin
if rising_edge (UartClock) then
Tx <= TxBuffer(CounterWord);
CounterWord := CounterWord+1;
end if;
end process;
end Behavioral;

متاسفانه نتوسنتم براش یه کنترلر درست کنم که مثلا وقتی فلان کلید زده شده بعد دیتا رو ارسال کنه! بلکه توی کد بالا به طور پیوسته و دائما حرف A برای گیرنده فرستاده میشه! در تلاشم که بتونم کدی بنویسم که با سیگنال، ارسال رو کنترل کنم! اگه تونستم کدش رو میزارم! توی Generic کلمه Data داریم که دیتای ارسالی رو توش مینویسیم! من حرف A رو گذاشتم! فرکانس اسیلاتور برد هم 50 مگاهرتز فرض شده!


5) دریافت کننده RS232 UART Receiver

خوب کد جالبی هست با بود ریت 9600 کار میکنه بیت پریتی نداره و 8 بیت دیتا و 1 بیت استاپ همین! البته کدش رو من ننوشتم از این سایت برداشتم! سایت خوبیه...! توی کدش از ماشین حالت استفاده شده و خیلی لطیف نوشته شده!

یه کتاب خیلی مفید و کاربردی هست که میتونید از اینجا دانلود کنید! (همونیه که تو مثال قبل معرفی کردم)

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Receiver is
    Port ( clk     : in  STD_LOGIC;
           RXD     : in  STD_LOGIC;
 LED : out std_logic_vector (3 downto 0);
           wr_en   : out  STD_LOGIC
           ---clk_out : out  STD_LOGIC
 );
end Receiver;
architecture Behavioral of Receiver is
constant x:integer:=2600;  -- 5200/2 = 2600
type state is (idle,start,data,stop,w);
signal state_machine: state;
signal count:integer range 0 to 5200;
signal mode:integer range 0 to 8;
signal dout : STD_LOGIC_VECTOR (7 downto 0):=x"00";
begin
process(clk)
begin
if(clk'event and clk='1')then
case state_machine is
when idle=> wr_en<='0';
if(rxd='0')then
state_machine<=start;
end if;
when start=> count<=count+1;
if(count=x)then
count<=0;
state_machine<=data;
end if;
when data=>
count<=count+1;
if(count=5200)then
count<=0;
mode<=mode+1;
case mode is
when 0=>
dout(0)<=rxd;
when 1=>
dout(1)<=rxd;
when 2=>
dout(2)<=rxd;
when 3=>
dout(3)<=rxd;
when 4=>
dout(4)<=rxd;
when 5=>
dout(5)<=rxd;
when 6=>
dout(6)<=rxd;
when 7=>
dout(7)<=rxd;
when others=>
state_machine<=stop;
wr_en<='1';
mode<=0;
end case;
end if;
when stop=>
if(rxd='1')then
state_machine<=idle;
else
state_machine<=w;
end if;
when w=>
count<=count+1;
if(count=5200)then
count<=0;
state_machine<=data;
end if;
end case;
end if;
end process;
LED(0) <= dout(0);
LED(1) <= dout(1);
LED(2) <= dout(2);
LED(3) <= dout(3);
end Behavioral;

ولی خوب من وقتی شماتیک تولید شده اش رو میبینم خیلی فلیپ فلاپ و دیگر اجزاء داره! به نظر میرسه کدش بهینه نباشه ولی خوب بهتر از هیچی هست!


6) ارتباط باکارت SD با FPGA

خوب پروژه اش رو قرار میدم استفاده کنید! خیلی برنامه کاملیه ولی خودم ننوشتم! من یه توضیحاتی رو اینجا دادم میتونید بخونید!

کدش رو از این سایت گرفتم! سورس های جالبی داره!

برنامه کامل و تست شده رو میتونید از زیر دانلود کنید! (با کارت sd با حجم 2 گیگ تست کردم و احتمال میدم زیر 4 گیگ نیاز به تغییر نداره ولی برای بالای 4 گیگ باید یه کم توش تغییر بدید!- راهنماش رو توی خودش نوشته)


دریافت
حجم: 706 کیلوبایت



7) به زودی... (انشالله)


یا علی مدد...!