返回首頁 返回上一頁 組合邏輯實習 序向邏輯實習 其他實習                                   

亂數產生器  定時鬧鐘             步進馬達(一)   步進馬達(二)  PWM  

直流馬達    伺服機控制(一) 伺服機控制(二) RS-232接收器 RS-232串列傳輸 

-------------------------------------------------------------------
--實驗名稱:亂數產生器實習
--檔案名稱:random_mode9.vhd
--功        能:亂數產生號碼0~9
-------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

entity random_mode9 is
port(
clk :in std_logic;
rst :in std_logic;
sel :in std_logic;
q:out std_logic_vector(3 downto 0)
);
end random_mode9;

architecture a of random_mode9 is
type state_type is (S0,S1,S2,S3,S4,S5,S6,S7,S8,S9);
signal state: state_type;
signal qt: std_logic_vector(3 downto 0);
signal d, d0, d1: std_logic;
signal run : std_logic := '0';
begin
process(clk)
begin
if rst = '0' then
state <= S0;
elsif clk'event and clk = '1' then
d1<=d0; d0<=sel;
case state is
when S0 => if (run = '0') then state <= S1; end if;
when S1 => if (run = '0') then state <= S2; end if;
when S2 => if (run = '0') then state <= S3; end if;
when S3 => if (run = '0') then state <= S4; end if;
when S4 => if (run = '0') then state <= S5; end if;
when S5 => if (run = '0') then state <= S6; end if;
when S6 => if (run = '0') then state <= S7; end if;
when S7 => if (run = '0') then state <= S8; end if;
when S8 => if (run = '0') then state <= S9; end if;
when S9 => if (run = '0') then state <= S0; end if;
when others => null;
end case;
end if;
end process;
d<=d1 and not d0;
with state select
qt <= "0000" when S0,
"0001" when S1,
"0010" when S2,
"0011" when S3,
"0100" when S4,
"0101" when S5,
"0110" when S6,
"0111" when S7,
"1000" when S8,
"1001" when S9;

process(d, clk)
begin
if clk'event and clk='1' then
q<=qt;
if (d='1') then
run <= not run;
end if;
end if;
end process;
end a;

-------------------------------------------------------------------
--實驗名稱:定時鬧鐘實習
--檔案名稱:time_alarm.vhd
--功        能:定時鬧鐘主程式
-------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity time_alarm is
port(
clk : in std_logic;
btn : in std_logic_vector(3 downto 0);
seg_out : out std_logic_vector(6 downto 0);
seg_one_en: out std_logic;
seg_ten_en: out std_logic;
ring : out std_logic
);
end time_alarm;

architecture arch of time_alarm is
----- clk generate -----
component clk_gen
port(
clk_in : in std_logic;
clk_out1: out std_logic;
clk_out2: out std_logic;
clk_out3: out std_logic
);
end component;
----- alarm state machine -----
component alarm_state
port(
clk1 : in std_logic;
clk2 : in std_logic;
clk_ring: in std_logic;
sw1 : in std_logic; -- start
sw2 : in std_logic; -- set
sw3 : in std_logic; -- +1 or stop
sw4 : in std_logic; -- -1 or re_set
seg_en : out std_logic;
seg_one : out std_logic_vector(3 downto 0);
seg_ten : out std_logic_vector(3 downto 0);
ring : out std_logic
);
end component;
----- 7segment block -----
component bin2seg0_scan
port (
clk : in std_logic;
seg_en : in std_logic;
q_one : in std_logic_vector(3 downto 0);
q_ten : in std_logic_vector(3 downto 0);
seg_out : out std_logic_vector(6 downto 0);
seg_one_en: out std_logic;
seg_ten_en: out std_logic
);
end component;
signal clk1,clk2,clk_ring: std_logic;
signal sw1,sw2,sw3,sw4: std_logic;
signal seg_en: std_logic;
signal seg_one: std_logic_vector(3 downto 0);
signal seg_ten: std_logic_vector(3 downto 0);
begin
u1: clk_gen port map(clk,clk1,clk2,clk_ring);
u2: alarm_state port map(clk,clk1,clk_ring,btn(0),btn(1),btn(2),btn(3),seg_en,seg_one,seg_ten,ring);
u3: bin2seg0_scan port map(clk2,seg_en,seg_one,seg_ten,seg_out,seg_one_en,seg_ten_en);
end arch;

---------------------------------------------------------------------
--實驗名稱:步進馬達實習(一)
--檔案名稱:stepmotor_dirsel.vhd
--功        能:步進馬達轉向與全步半步選擇控制
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity stepmotor_dirsel is
port(
clk : in std_logic;
dir : in std_logic;
sel : in std_logic;
step: out std_logic_vector(3 downto 0)
);
end stepmotor_dirsel;

architecture arch of stepmotor_dirsel is
signal cnt : std_logic_vector(2 downto 0);
begin

process(clk)
begin
if clk'event and clk='1' then
if dir='1' then
cnt <= cnt+1;
else
cnt <= cnt-1;
end if;
end if;
end process;

process(cnt,sel)
begin
if sel = '1' then
case cnt is
when "000"=>step<="1100";
when "001"=>step<="0110";
when "010"=>step<="0011";
when "011"=>step<="1001";
when "100"=>step<="1100";
when "101"=>step<="0110";
when "110"=>step<="0011";
when "111"=>step<="1001";
when others => null;
end case;
else
case cnt is
when "000"=>step<="1000";
when "001"=>step<="1100";
when "010"=>step<="0100";
when "011"=>step<="0110";
when "100"=>step<="0010";
when "101"=>step<="0011";
when "110"=>step<="0001";
when "111"=>step<="1001";
when others => null;
end case;
end if;
end process;
end arch;


-------------------------------------------------------------------
--實驗名稱:步進馬達實習(二)
--檔案名稱:stepmotor_speed.vhd
--功        能:步進馬達轉速控制
-------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity stepmotor_speed is
port(
clk : in std_logic;
spd : in std_logic_vector(3 downto 0);
step: out std_logic_vector(3 downto 0)
);
end stepmotor_speed;

architecture arch of stepmotor_speed is
signal buf: std_logic_vector (4 downto 0);
signal dly : std_logic;
signal clk_new: std_logic;
signal cnt : std_logic_vector(1 downto 0);
begin
---------- process ---------
process(clk)
begin
if clk'event and clk='1' then
dly <= buf(4);
buf <= buf +('0' & spd);
end if;
end process;

clk_new<=buf(4) xor dly;

process(clk_new)
begin
if clk_new'event and clk_new='1' then
cnt <= cnt+1;
end if;
end process;

step <= "1000" when cnt=0 else
"0100" when cnt=1 else
"0010" when cnt=2 else
"0001";
end arch;


---------------------------------------------------------------------
--實驗名稱:PWM實習
--檔案名稱:pwm.vhd
--功        能:以指撥開關來調整PWM訊號輸出
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity pwm is
port(
clk : in std_logic; --系統頻率
A : in std_logic_vector(7 downto 0); --PWM控制訊號
pwm : out std_logic --PWM訊號輸出
);
end pwm;

architecture a of pwm is
signal B:std_logic_vector(7 downto 0);
begin

----- 下數計數器 -----
process(clk)
begin
if clk'event and clk='1' then
B <= B-1;
end if;
end process;

--比較器
pwm<='1' when A > B else '0';

end a;

----------------------------------------------------------------------------------------------------------
--實驗名稱:直流馬達轉速與轉向控制實習
--檔案名稱:dcmotor.vhd
--功        能:以指撥開關來調整直流馬達轉速,以彈跳開關控制直流馬達轉向
----------------------------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity dcmotor is
port(
clk : in std_logic; --系統頻率
DIP : in std_logic_vector(7 downto 0); --指撥開關輸入
BTN : in std_logic_vector(3 downto 0); --彈跳開關輸入
VREF : out std_logic; --PWM訊號
DIR : out std_logic_vector(1 downto 0) --TA7291模式選擇訊號
);
end dcmotor;

architecture a of dcmotor is
signal B:std_logic_vector(7 downto 0);
begin

----- 下數計數器 -----
process(clk)
begin
if clk'event and clk='1' then
B <= B-1;
end if;
end process;

----- 比較器 -----
VREF <= '1' when DIP > B else '0';

----- TA7291模式選擇 -----
process(BTN)
begin
case BTN is
when "1110" => DIR <= "00";
when "1101" => DIR <= "01";
when "1011" => DIR <= "10";
when "0111" => DIR <= "11";
when others => DIR <= "00";
end case;
end process;
end a;

 ---------------------------------------------------------------------
--實驗名稱:伺服機控制實習
--檔案名稱:servo_control.vhd
--功        能:以4個按鍵控制伺服機轉動角度
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity servo_control is
generic (divisor: integer :=18);
port(
clk : in std_logic;
BTN : in std_logic_vector(3 downto 0);
pwm : out std_logic
);
end servo_control;

architecture a of servo_control is
signal clk1 : std_logic; --new clk : 100000Hz
signal cnt2 : std_logic;
signal data : integer range 0 to 230;
signal period : integer range 0 to 1999; --2000 x 0.01ms = 20ms
begin

---------- clk divider, generate 100000Hz frequence, 0.01ms----------
process (clk)
variable cnt1 : integer range 0 to divisor;
variable divisor2 : integer range 0 to divisor;
begin
divisor2 := divisor/2;
if (clk'event and clk='1') then
if cnt1=divisor then
cnt1 := 1;
else
cnt1 := cnt1 + 1;
end if;
end if;

if (clk'event and clk='1') then
if (( cnt1=divisor2) or (cnt1=divisor)) then
cnt2 <= not cnt2;
end if;
end if;
clk1<= cnt2 ;
end process;
---------------------------------------------------------------
-- 70(0.7ms) => 0 degree ; 110(1.1ms) => 45 degree
-- 150(1.5ms) => 90 degree; 190(1.9ms) => 135 degree
-- 230(2.3ms) => 180 degree
---------------------------------------------------------------
process(clk1)
begin
case BTN is
when "1110" => data <= 70;
when "1101" => data <= 110;
when "1011" => data <= 150;
when "0111" => data <= 190;
when others => null;
end case;
end process;
-------------------------------------------------------------------------------
process(clk1,period)
begin
if clk1'event and clk1= '1' then
period <= period + 1;
end if;
end process;

pwm <= '1' when period < data else '0';

end a;

-------------------------------------------------------------------
--實驗名稱:伺服機控制實習
--檔案名稱:sv_trans.vhd
--功        能:伺服機轉角控制信號產生模組
-------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity servo_trans is
generic (divisor: integer :=18);
port(
clk : in std_logic;
xout: in std_logic_vector(7 downto 0);
pwm : out std_logic
);
end servo_trans;

architecture a of servo_trans is
signal clk1 : std_logic;
signal cnt2 : std_logic;
signal data : integer range 0 to 230;
signal period : integer range 0 to 1999;
begin

----- clk divider -----
process (clk)
variable cnt1,divisor2 : integer range 0 to divisor;
begin
divisor2 := divisor/2;
if (clk'event and clk='1') then
if cnt1=divisor then
cnt1 := 1;
else
cnt1 := cnt1 + 1;
end if;
end if;

if (clk'event and clk='1') then
if (( cnt1=divisor2) or (cnt1=divisor)) then
cnt2 <= not cnt2;
end if;
end if;
clk1<= cnt2 ;
end process;
----- data transfer -----
process(clk1)
begin
if clk1'event and clk1='1' then
data <= CONV_integer(xout) + 70;
end if;
end process;
-------------------------------------------------------------------------------
process(clk1)
begin
if clk1'event and clk1= '1' then
period <= period + 1;
end if;
end process;

pwm <= '1' when period < data else '0';

end a;

-------------------------------------------------------------------
--實驗名稱:RS-232實習
--檔案名稱:uart_receiver.vhd
--功        能:串列傳輸接收器;1 start bit, 8 data bits, 1 stop bit
-------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity uart_receiver is
port(
sysclk :in std_logic; --system clock
rst_n :in std_logic; --system rest
bclkx8 :in std_logic; --detection baud rate
rxd :in std_logic; --rx of uart
rxd_readyH:out std_logic; --rxd_readyH; rising edge
RDR :out std_logic_vector(7 downto 0)--receive data 1
);
end uart_receiver;

architecture arch of uart_receiver is
type statetype is (idle,start_detected,recv_data);
signal state,nextstate:statetype;
signal inc1,inc2,clr1,clr2:std_logic; --increse and clear
signal shftRSR,load_RDR:std_logic; --load data signal
signal bclkx8_dlayed,bclkx8_rising:std_logic; --baud rate message
signal RSR:std_logic_vector(7 downto 0); --receive shift register
signal ct1:integer range 0 to 7; --detect the determination clk
signal ct2:integer range 0 to 8; --detect receivability #data bit
signal ok_en: std_logic;
begin
bclkx8_rising<=bclkx8 and(not bclkx8_dlayed);
---------- FSM of UART receiver ---------
process(state,rxd,ct1,ct2,bclkx8_rising)
begin
----- initial value -----
inc1<='0';inc2<='0';clr1<='0';clr2<='0';
shftRSR<='0';load_RDR<='0';ok_en<='0';
----- state machine -----
case state is
----- idle state; standby, wait until rxd='0' -----
when idle=>
if (rxd='0') then --detect start bit signal '0'
nextstate<=start_detected;
else
nextstate<=idle;
end if;
----- start_detected state; determine whether start bit -----
when start_detected=>
if (bclkx8_rising='0') then
nextstate<=start_detected;
elsif (rxd='1') then --not start bit;
clr1<='1'; --clear counter 1
nextstate<=idle; --back to idle state
elsif (ct1=3) then --after 3 bclkx8; confirm it be the start bit
clr1<='1'; --clear counter 1
nextstate<=recv_data; --go on receive data
else
inc1<='1'; --cnt+1
nextstate<=start_detected; --go on confirm the start bit
end if;
----- receive data state; receive series data from rxd -----
when recv_data=>
if (bclkx8_rising='0') then
nextstate<=recv_data;
else
inc1<='1';
if (ct1/=7) then --detect data every 8 times of bclkx8
nextstate<=recv_data;
elsif (ct2/=8) then --receive 8 times
shftRSR<='1'; --receive 1bit data
inc2<='1'; --ct2+1
clr1<='1'; --ct1=0
nextstate<=recv_data;
elsif (rxd='0') then --error
nextstate<=idle; --do nothing and back
clr1<='1'; --ct1=0
clr2<='1'; --ct2=0
else --detect end bit '1'
load_RDR<='1'; --RDR<=RSR ; receive 1bytes data finished
ok_en<='1';
clr1<='1'; --ct1=0
clr2<='1'; --ct2=0
nextstate<=idle; --finish receive 1 bytes data
end if;
end if;
end case;
end process;
---------- update state and value of register ----------
process(sysclk,rst_n)
begin
if (rst_n='0') then
state<=idle;
bclkx8_dlayed<='0';
ct1<=0;
ct2<=0;
RDR<="00000000";
elsif (sysclk'event and sysclk='1') then
state<=nextstate;

if(clr1='1')then ct1<=0;elsif(inc1='1')then ct1<=ct1+1;end if;

if(clr2='1')then ct2<=0;elsif(inc2='1')then ct2<=ct2+1;end if;

if(shftRSR='1')then RSR<=rxd & RSR(7 downto 1);end if;

if(load_RDR='1')then RDR<=RSR;end if;

if(ok_en='1')then rxd_readyH<='1';else rxd_readyH<='0';end if;
----- generator bclk delay signal for determine bclkx8 rising -----
bclkx8_dlayed<=bclkx8;
end if;
end process;
end arch;

--------------------------------------------------------------------------
--實驗名稱:RS-232實習
--檔案名稱:uart_transmitter.vhd
--功        能:串列傳輸;1 start bit, 8 data bits, 1 stop bit
--------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

entity uart_transmitter is
port(
sysclk : in std_logic; --system clock
rst_n : in std_logic; --system reset;
bclk : in std_logic; --baud rate clock
txd_startH : in std_logic; --rxd start; active high
DBUS : in std_logic_vector(7 downto 0);--Data Bus
txd_doneH : out std_logic; --transmmit finished
txd : out std_logic --txd
);
end uart_transmitter;

architecture arch of uart_transmitter is
type statetype is (idle, synch, tdata);
signal state, nextstate : statetype;
signal tsr : std_logic_vector (8 downto 0); -- Transmit Shift Register
signal bct: integer range 0 to 9; -- counts number of bits sent
signal inc, clr, loadTSR, shftTSR, start: std_logic;
signal bclk_rising, bclk_dlayed, txd_done: std_logic;
begin
txd <= tsr(0);
txd_doneH <= txd_done;
bclk_rising <= bclk and (not bclk_dlayed);
process(state,txd_startH, bct, bclk_rising)
begin
inc <= '0';
clr <= '0';
loadTSR <= '0';
shftTSR <= '0';
start <= '0';
txd_done <= '0';
case state is
----- idle state; wait until txd_startH = '1' -----
when idle =>
if (txd_startH = '1' ) then
loadTSR <= '1';
nextstate <= synch;
else
nextstate <= idle;
end if;
----- synch state; synchronize with the bit clock -----
when synch =>
if (bclk_rising = '1') then
start <= '1';
nextstate <= tdata;
else
nextstate <= synch;
end if;
----- transmit data state -----
when tdata =>
if (bclk_rising = '0') then
nextstate <= tdata;
elsif (bct /= 9) then
shfttsr <= '1';
inc <= '1';
nextstate <= tdata;
else
clr <= '1';
txd_done <= '1';
nextstate <= idle;
end if;
end case;
end process;
----- update data -----
process (sysclk, rst_n)
begin
if (rst_n = '0') then
TSR <= "111111111";
state <= idle;
bct <= 0;
bclk_dlayed <= '0';
elsif (sysclk'event and sysclk = '1') then
state <= nextstate;
--counter of transmit bit
if (clr = '1') then
bct <= 0;
elsif (inc = '1') then
bct <= bct + 1;
end if;
--TSR assignment
if (loadTSR = '1') then
TSR <= DBUS & '1';
elsif (start = '1') then
TSR(0) <= '0';
elsif (shftTSR = '1') then
TSR <= '1' & TSR(8 downto 1);
end if;
-- Bclk delayed by 1 sysclk
bclk_dlayed <= bclk;
end if;
end process;
end arch;