天天看點

VLSI/SoC設計綜合實驗(Ⅰ)

VLSI/SoC設計綜合實驗(Ⅰ)

實驗一:交通燈的設計及FPGA實作

作者: Saint

掘金:https://juejin.im/user/5aa1f89b6fb9a028bb18966a

微網誌:https://weibo.com/5458277467/profile?topnav=1&wvr=6&is_all=1

GitHub:github.com/saint-000

一、實驗目的:

熟練使用VHDL進行RTL級代碼的編寫;熟練運用EDA工具(modelsim、ISE)和 FPGA 開發闆,完成較複雜的系統設計;鍛煉系統級的設計能力及原型驗證能力。完成模拟交通燈的設計及 FPGA 實驗驗證。

二、實驗原理:

(1)交通信号燈的基本轉換原理
           

本實驗要求模拟的交通信号燈的轉換原理如下圖所示:

VLSI/SoC設計綜合實驗(Ⅰ)

預設的初始狀态為紅燈狀态,做 30 秒減計時。當時間從 30 秒遞減到 0 秒後,紅燈狀态變為綠燈狀态;重新 30 秒減計時,遞減到 0 秒後,綠燈狀态變為黃燈狀态;做 5 秒減計時,遞減到 0 秒後,黃燈狀态變為紅燈狀态。如此循環進行轉換。

(2)共陽數位管
           

實驗主機闆上的 8 個數位管為共陽極型,即數位管的公共端接正極,顯示段碼信号接負極。8個數位管的顯示段碼信号複用,公共端則互相獨立。數位管和 LCD 子產品共用一組 IO 控制接口,使用者做這倆實驗時,注意數位管和 LCD 不要同時工作。通過數位管旁邊的J1 跳線控制。

VLSI/SoC設計綜合實驗(Ⅰ)

(3)撥碼開關

實驗主機闆上設計了一組8位的撥碼開關,ON為低電平,OFF為高電平。撥碼開關可供使用者 輸入一些高低電平。

VLSI/SoC設計綜合實驗(Ⅰ)

(4)LED燈電路(啟用需短接J4)

實驗主機闆上 LED 燈電路屬于闆内資源,要使用它,需把 J4 短接。LED 燈的陽極接電源, 陰級接 FPGA、CPLD 的 I/0 口,是以是低電平驅動,隻要由 FPGA、CPLD 在相應引腳給出 低電平,LED 就會發光。LED 燈電路原理圖如圖 1-6 所示,對應 FPGA 管腳如表 1-3 所示。

VLSI/SoC設計綜合實驗(Ⅰ)

三、實驗器材(裝置、元器件):

計算機、FPGA 開發闆、開發闆附件

四、實驗内容:

編寫 VHDL 代碼、生成下載下傳檔案,下載下傳設計到 FPGA 實作如下功能:模拟路口交通信号燈的紅、黃、綠燈的變化過程,分别用三個 LED 燈表示,并在數位管上動态顯示目前狀态剩餘時間。要求紅燈持續時間為 30 秒,黃燈 5 秒,綠燈 30秒。

五、實驗步驟:

(1)建立工程

1.打開 Xilinx ISE 7.1i。選擇 File-New Project 建立工程,根據需要設定工程名 稱和工程路徑。

2.點選下一步配置工程屬性, Device Family 選擇 Spartan2,Device 選擇 XC2S50, Package 選擇 TQ144,Speed Grade 選擇-6。

3.直到完成工程的建立。

(2)建立和編寫源檔案

1.在 Sources in Project 中點右鍵,選擇 New Source。在彈出的對話框中選擇 VHDL Module,自己設定 File Name,一路下一步,建立一個新的源檔案。

2.在新的源檔案中錄入設計,完成數字時鐘的功能。

(3)設計的仿真

編寫 test_bench,用 Modelsim 對設計進行仿真,驗證功能正确性。

(4)上闆調試

将設計下載下傳到闆上進行調試,驗證設計的正确性。

六、實驗資料及結果分析:

一.分頻子產品(将40MHZ的時鐘頻率變成1HZ的頻率):

process(clr,clk_40Mhz)
 begin
  if(clr='0')then
   count_25<="0000000000000000000000000";
  elsif(rising_edge(clk_40Mhz))then
   if(count_25="1111111111111111111111111")then
    count_25<="0000000000000000000000000";
   else
    count_25<=count_25+'1';
   end if;
   end if;
   end process;
   clk_1hz<=count_25(24);(計數分頻1hz)
           

通過分頻子產品可以得到一秒鐘的時鐘信号。

二.計數子產品(紅燈30秒,黃燈5秒,綠燈30秒):

1.綠燈30秒:

when s0 =>          --
   if(high = "0000" and low = "0000") then  --黃燈時間結束
      current_state <= s1;      --
      green <= '0'; 
      red <= '1';   
      yellow <= '1';
       high <= "0010"; low <= "1001";  --綠燈顯示時間為30
     end if;
           

2.黃燈5秒

when s1 =>           --
       if(high = "0000" and low = "0000") then  --綠燈時間結束
        current_state <= s2;      --
        yellow <= '0';
        green <= '1'; 
        red <= '1';           
        high <= "0000"; low <= "0100";  --黃燈時間為5
       end if;
           

3.紅燈30秒

when s2 =>   
      if(high = "0000" and low = "0000") then  --黃燈時間結束
       current_state <= s3;     
       red <= '0';   
       green <= '1'; 
       yellow <= '1';         
       high <= "0010"; low <= "1001";   --紅燈時間為30
       end if;
           

三.動态顯示子產品

begin
 case he is
	when "0000"=>xianshi_z<="11000000";
	when "0001"=>xianshi_z<="11111001";
	when "0010"=>xianshi_z<="10100100";
	when "0011"=>xianshi_z<="10110000";
	when "0100"=>xianshi_z<="10011001";
	when "0101"=>xianshi_z<="10010010";
	when "0110"=>xianshi_z<="10000010";
	when "0111"=>xianshi_z<="11111000";
	when "1000"=>xianshi_z<="10000000";
	when "1001"=>xianshi_z<="10010000";
	when "1011"=>xianshi_z<="11000001";
	when "1100"=>xianshi_z<="01100011";
	when "1101"=>xianshi_z<="10000101";
	when "1110"=>xianshi_z<="01100001";
	when "1111"=>xianshi_z<="01110001";
	when others=>xianshi_z<="00000011";
end case;
end process; 
xianshi<=xianshi_z;
end BEHAVIORAL;
           

四.源碼:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity TrafficLight is
 Port(reset: in std_logic;
 led_r,led_y,led_g:out std_logic;
 xianshi:out std_logic_vector(7 downto 0);
  clr:in std_logic;
  clk_40Mhz:in std_logic;
  EN:out std_logic_vector(7 downto 0)
  );
end TrafficLight;

architecture BEHAVIORAL of TrafficLight is
 type mmp is(s0,s1, s2,s3); 
 signal current_state: mmp;   
 signal red, yellow, green: std_logic;
 signal high: std_logic_vector(3 downto 0); --倒計時顯示的高位數
 signal low: std_logic_vector(3 downto 0); --倒計時顯示的低位數
 signal xianshi_z,xianshi_h_z:std_logic_vector(7 downto 0);
 signal he:std_logic_vector(3 downto 0);
 
 
 signal count_25:std_logic_vector(24 downto 0);
 signal s:std_logic_vector(7 downto 0); 
 signal clk_1hz,clk_sm:std_logic;
 
begin
 p1:
 process(clr,clk_40Mhz)
 begin
  if(clr='0')then
   count_25<="0000000000000000000000000";
  elsif(rising_edge(clk_40Mhz))then
   if(count_25="1111111111111111111111111")then
    count_25<="0000000000000000000000000";
   else
    count_25<=count_25+'1';
   end if;
   end if;
   end process;
   
   clk_1hz<=count_25(24);
   clk_sm<=count_25(14);  --分頻


   p2:
   process(clk_sm,clr)
   begin
    if(clr='0')then
     s<="11111110";
    elsif(rising_edge(clk_sm))then
    s(1)<= not s(1);
    s(0)<= not s(0);
	end if;
	EN<=s;
 end process;
   
 p3:
 process(s,he,low,high)
 begin
  if(s="11111110")then
   he<=low;
 else
	 he<=high;
	 end if;					 
end  process; 					  --位選
 
  p4: process(reset, clk_1hz, current_state)
  begin
   if(clk_1hz = '1' and clk_1hz'event) then  --當clk_1hz處于上升沿
    if reset = '0' then
     current_state <= s0;  --複位時強行進入s0狀态
     low <= "0000";
     high <= "0000";
    else
     if(low = "0000" and not(high = "0000")) then  --如果低位不夠減,則高位減一,低位置9
      low <= "1001";
      high <= high - 1;
     else                                           --每掃描一次,時間減一,如果低位夠減,則隻需低位減一,高位不變
      low <= low - 1;
      high <= high;
     end if;
   
     case current_state is  --檢測目前狀态
     
      when s0 =>          --
       if(high = "0000" and low = "0000") then  --黃燈時間結束
        current_state <= s1;      --
        green <= '0'; 
        red <= '1';   
        yellow <= '1';
        high <= "0010"; low <= "1001";  --綠燈顯示時間為30
       
       end if;
      when s1 =>           --
       if(high = "0000" and low = "0000") then  --綠燈時間結束
        current_state <= s2;      --
        yellow <= '0';
        green <= '1'; 
        red <= '1';           
        high <= "0000"; low <= "0100";  --黃燈時間為5
       end if;
      when s2 =>           --
          if(high = "0000" and low = "0000") then  --黃燈時間結束
           current_state <= s3;     --
        red <= '0';   
        green <= '1'; 
        yellow <= '1';         
        high <= "0010"; low <= "1001";   --紅燈時間為30
       end if;
	   when s3 =>           --
       if(high = "0000" and low = "0000") then  --綠燈時間結束
        current_state <= s0;      --
        yellow <= '0';
        green <= '1'; 
        red <= '1';           
        high <= "0000"; low <= "0100";  --黃燈時間為5
       end if;
	   
     end case;
    end if;
   end if;
  end process;	 
    led_r<=red;
    led_g<=green;
    led_y<=yellow;
   
p5:	process(he)
 begin
 case he is
	when "0000"=>xianshi_z<="11000000";
	when "0001"=>xianshi_z<="11111001";
	when "0010"=>xianshi_z<="10100100";
	when "0011"=>xianshi_z<="10110000";
	when "0100"=>xianshi_z<="10011001";
	when "0101"=>xianshi_z<="10010010";
	when "0110"=>xianshi_z<="10000010";
	when "0111"=>xianshi_z<="11111000";
	when "1000"=>xianshi_z<="10000000";
	when "1001"=>xianshi_z<="10010000";
	when "1011"=>xianshi_z<="11000001";
	when "1100"=>xianshi_z<="01100011";
	when "1101"=>xianshi_z<="10000101";
	when "1110"=>xianshi_z<="01100001";
	when "1111"=>xianshi_z<="01110001";
	when others=>xianshi_z<="00000011";
end case;
end process; 
xianshi<=xianshi_z;

end BEHAVIORAL;
           

五.闆上的顯示結果:

VLSI/SoC設計綜合實驗(Ⅰ)
VLSI/SoC設計綜合實驗(Ⅰ)

七、實驗結論:

起始狀态黃燈熄滅,綠燈點亮,數位管數值顯示跳變到30并每一秒鐘遞減一位。當數位管數值顯示變為零0的時候,綠燈熄滅,紅燈點亮,數位管數值顯示跳變到30并每一秒鐘遞減一位。當數位管數值顯示變為零0的時候,紅燈熄滅,黃燈點亮,數位管數值顯示跳變到5并每一秒鐘遞減一位,當數位管數值顯示變為零0的時候回到起始狀态。

八、總結及心得體會:

1.此次實驗一開始我們想用狀态機來控制紅黃綠燈的顯示,用一個總時間為75秒的計數器來顯示紅黃綠燈的秒數,并在其基礎上分出兩個30秒和一個5秒的計數器,但最後編寫程式的時候發現程式太過複雜,程式編譯時也存在許多錯誤,并且修改難度太大于是我們就換了另外一種方法。

2.第二種方法:我們把狀态機取消,同時也把75秒的計數器給取消掉,在此基礎上的兩個30秒和一個5秒的計數器保持不變,然後把控制不同LED燈亮滅的代碼放在計數器清零的末端,進而實作了數位管顯示變為零的時候,一個LED燈亮,一個LED燈滅。

3.實驗過程中最大的問題就是數位管的動态掃描子產品(因為不太了解相關的代碼及原理);我們把代碼下載下傳到闆子時,LED的顯示正常但是數位管的顯示是亂碼,然後反複修改動态掃描子產品,直到最後得正确的數位管顯示。

4.通過此次實驗我們掌握了用VHDL進行RTL級代碼的編寫,并學會了如何用彙編語言編寫分屏子產品,計數子產品,動态掃描子產品的代碼,同時也學會了FPGA實驗驗證和調試。

九、對本實驗過程及方法、手段的改進建議:

1.外部可以設計一個中斷源,當出現緊急情況時可以暫停交通燈的運作;

2.可以将1HZ的分頻信号放加法器内(在交通燈燈的基礎上添加一數字時鐘顯示功能)