2014年5月14日 星期三

ML605 ipcore microblaze 筆記

microblaze也有簡化版的免錢ipcore,在此紀錄使用過程
板子是ml605

*建立專案並新增ipcore,注意ipcore的名子不可以設為mcs_0 ,不然之後下script的時候會找不到ipcore , 之前這個地方卡了半天 = =


進入設定以後會看到系統已經自動設Hierarchical Design Name mcs_0
clk 調成系統可以送進去的頻率
Memory size 可以先設大一點,免得之後在SDK隨便用uart印幾個字就說爆表了 = =

io bus打開




設定好uart gpio以後就可以開始generate code ,完了以後檢查一下ipcore_dir裡面的資料夾應該會有四個檔案
microblaze_mcs_sdk.xml
microblaze_mcs.bmm
microblaze_mcs_setup.tcl
mb_bootloop_le.elf

好了以後打開view-panel-tcl console,輸入
source ipcore_dir/microblaze_mcs_setup.tcl



成功的話會看到下列訊息
Command>source ipcore_dir/microblaze_mcs_setup.tcl
microblaze_mcs_setup: Found 1 MicroBlaze MCS core.
microblaze_mcs_setup: Added "-bm" option for "microblaze_mcs.bmm" to ngdbuild command line options.
microblaze_mcs_setup: Done.



開始寫top file mcs instance 進入code,並加上ucf ,注意mcsinstance


top level code
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

entity ml605_mcs_top is
    Port (
    CLK_N  : in  STD_LOGIC;
    CLK_P  : in  STD_LOGIC;
    RESET  : in  STD_LOGIC;
    DIP   : in  STD_LOGIC_VECTOR (7 downto 0);
    LED   : out  STD_LOGIC_VECTOR (7 downto 0);
    UART_Rx : in  STD_LOGIC;
    UART_Tx : out  STD_LOGIC);
end ml605_mcs_top;

architecture Behavioral of ml605_mcs_top is

COMPONENT microblaze_mcs
  PORT (
    Clk : IN STD_LOGIC;
    Reset : IN STD_LOGIC;
    IO_Addr_Strobe : OUT STD_LOGIC;
    IO_Read_Strobe : OUT STD_LOGIC;
    IO_Write_Strobe : OUT STD_LOGIC;
    IO_Address : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
    IO_Byte_Enable : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    IO_Write_Data : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
    IO_Read_Data : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
    IO_Ready : IN STD_LOGIC;
    UART_Rx : IN STD_LOGIC;
    UART_Tx : OUT STD_LOGIC;
    GPO1 : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
    GPI1 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
    GPI1_Interrupt : OUT STD_LOGIC
  );
END COMPONENT;

 signal   Clk :  std_logic; 
 signal    IO_Addr_Strobe :  std_logic;
 signal  IO_Read_Strobe :  std_logic;
 signal  IO_Write_Strobe :  std_logic;
 signal  IO_Address :  std_logic_vector(31 downto 0);
 signal  IO_Byte_Enable :  std_logic_vector(3 downto 0);
 signal  IO_Write_Data :  std_logic_vector(31 downto 0);         
 signal  IO_Read_Data :  std_logic_vector(31 downto 0);
 signal  IO_Ready :  std_logic;
 signal slv_reg0           : std_logic_vector(31 downto 0);
 signal slv_IO_Read_Data   : std_logic_vector(31 downto 0);
 signal slv_write_ack      : std_logic;
 signal IO_Ready_w         : std_logic;
 signal Read_rdy_w, Read_rdy : std_logic;
 signal Write_rdy_w, Write_rdy : std_logic;
 signal Data_Buffer_w, Data_Buffer : std_logic_vector(31 downto 0);
 signal IO_Write_Strobe_D, IO_Write_Strobe_D_w   : std_logic;
begin

  -- Input Clock Buffer
  clkin1_ibuf : IBUFGDS
  port map (
    I  => CLK_P,
    IB => CLK_N,
    O  => Clk);
 
mcs_0 : microblaze_mcs
  PORT MAP (
    Clk => Clk,
    Reset => Reset,
    IO_Addr_Strobe => IO_Addr_Strobe,
    IO_Read_Strobe => IO_Read_Strobe,
    IO_Write_Strobe => IO_Write_Strobe,
    IO_Address => IO_Address,
    IO_Byte_Enable => IO_Byte_Enable,
    IO_Write_Data => IO_Write_Data,
    IO_Read_Data => IO_Read_Data,
    IO_Ready => IO_Ready,
    UART_Rx => UART_Rx,
    UART_Tx => UART_Tx,
    GPO1 => open,
    GPI1 => DIP,
    GPI1_Interrupt => OPEN
  );
  ------------------ test iobuf ---------------------------
  LED  <= slv_reg0(7 downto 0);

   process ( IO_Write_Strobe, IO_Addr_Strobe) is    -- write
 begin
  if( IO_Write_Strobe = '1' and IO_Addr_Strobe = '1') then
   Write_rdy_w <= '1';
  else
   Write_rdy_w <= '0';
  end if;
 end process; 


 process ( IO_Addr_Strobe, IO_Read_Strobe  ) is    -- read
 begin
  if(  IO_Read_Strobe = '1' and IO_Addr_Strobe = '1') then
   Read_rdy_w <= '1';
  else
   Read_rdy_w <= '0';
  end if;
 end process; 
 
 process( IO_Write_Data, IO_Write_Strobe,Data_Buffer)
 begin
  if(IO_Write_Strobe = '1') then
   Data_Buffer_w <= IO_Write_Data;
   IO_Write_Strobe_D_w <= '1';
  else
   Data_Buffer_w <= Data_Buffer;
   IO_Write_Strobe_D_w <= '0';
  end if;
 end process;
 
   IO_Ready  <= '1' when Write_rdy = '1' or Read_rdy = '1' else '0';
 IO_Read_Data <= slv_IO_Read_Data when Read_rdy = '1' else (others => '0');
  
 process(Clk,reset)
 begin
 if reset = '1' then
  Write_rdy <= '0';
  Read_rdy  <= '0';
  Data_Buffer <=  (others => '0');
  IO_Write_Strobe_D <= '0';
 elsif CLK'event and CLK = '1' then 
  Write_rdy <= Write_rdy_w;
  Read_rdy  <= Read_rdy_w;
  Data_Buffer <= Data_Buffer_w;
  IO_Write_Strobe_D <= IO_Write_Strobe_D_w;
 end if;
 end process;
 
 
process( Clk,reset ) is
  begin
  if reset = '1' then
        slv_reg0 <= (others => '0');
      elsif Clk'event and Clk = '1' then
  if(IO_Write_Strobe_D = '1') then
        case IO_Address is
          when "11000000000000000000000000000000" =>                   -- C0000000
                slv_reg0(31 downto 0) <= Data_Buffer(31 downto 0); 
          when others => null;
        end case;
      end if;
    end if;
  end process;

  -- implement slave model software accessible register(s) read mux
process( IO_Address, IO_Addr_Strobe, slv_reg0 ) is
  begin
 if( IO_Addr_Strobe = '1' and IO_Read_Strobe = '1') then
      case IO_Address is
      when "11000000000000000000000000000000" => slv_IO_Read_Data <= slv_reg0;
      when others => slv_IO_Read_Data <= (others => '0');
        end case;
     end if;
  end process;

end Behavioral;
ucf file
 
NET "CLK_N" LOC = H9 | DIFF_TERM = "TRUE" | IOSTANDARD = "LVDS_25";
NET "CLK_P" LOC = J9 | DIFF_TERM = "TRUE" | IOSTANDARD = "LVDS_25";
NET "RESET" LOC = H10 | IOSTANDARD = "SSTL15" | TIG;


NET "LED<0>" LOC = AC22 | IOSTANDARD = "LVCMOS25";
NET "LED<1>" LOC = AC24 | IOSTANDARD = "LVCMOS25";
NET "LED<2>" LOC = AE22 | IOSTANDARD = "LVCMOS25";
NET "LED<3>" LOC = AE23 | IOSTANDARD = "LVCMOS25";
NET "LED<4>" LOC = AB23 | IOSTANDARD = "LVCMOS25";
NET "LED<5>" LOC = AG23 | IOSTANDARD = "LVCMOS25";
NET "LED<6>" LOC = AE24 | IOSTANDARD = "LVCMOS25";
NET "LED<7>" LOC = AD24 | IOSTANDARD = "LVCMOS25";


NET "DIP<7>" LOC = K21;
NET "DIP<6>" LOC = K22;
NET "DIP<5>" LOC = B18;
NET "DIP<4>" LOC = C18;
NET "DIP<3>" LOC = L20;
NET "DIP<2>" LOC = L21;
NET "DIP<1>" LOC = C22;
NET "DIP<0>" LOC = D22;


NET "UART_Rx" LOC = J24 | IOSTANDARD = "LVCMOS25";
NET "UART_Tx" LOC = J25 | IOSTANDARD = "LVCMOS25"; 
接下來 generate programming file



在目錄裡面建立一個workspace 資料夾
打開SDK指向這個workspace

file-new-project-xilinx-hardware platform specification  



new-board support package

  
file-new-project-application project

  


elf file 已經產生,每次修改code以後儲存便會自動compile產生elf file

回到 ISE tcl console
Command>microblaze_mcs_data2mem workspace/hello_world_0/debug/hello_world_0.elf
microblaze_mcs_data2mem: Found 1 MicroBlaze MCS core.
microblaze_mcs_data2mem: Using "hello_world_0.elf" for microblaze_mcs
microblaze_mcs_data2mem: Added "-bd" options to bitgen command line.
microblaze_mcs_data2mem: Running "data2mem" to create simulation files.
microblaze_mcs_data2mem: Running "data2mem" to update bitstream with software.
microblaze_mcs_data2mem: Done.



基本上可以在ise上面用fpga program 燒入bit file然後,run sdk 看結果,但是我常常燒不進去,不知道是我頭腦有問題還是eclips實在是寫太爛了,我想應該是前者 = =




所以我比較喜歡把bit file elf 合在一起再用impact燒入
可以在ISE 上面command合併bmm,bit,elf 成一個全新的download.bit
Command>data2mem -bm ipcore_dir/microblaze_mcs_bd.bmm -bd workspace/hello_world_0/Debug/hello_world_0.elf -bt ml605_mcs_top.bit -o b download.bit
再燒入之前打開 tera term 觀察uart




hello world . nice to see you !


再原本的microblaze所用的uart lite 可以使用函數XUartLite_IsReceiveEmpty,XUartLite_RecvByte

但是這個ipcore似乎沒有這種support的函式,表示又要回去使用大魔頭!!!!!

收集uart的範例函式可以再xapp493 DisplayPort Source Core Reference Design
裡面的程式 xlib_string.h,xlib_string.c裡面找到

ipcore裡面有打開 io
IO_Addr_Strobe
IO_Read_Strobe
IO_Write_Strobe
IO_Address
IO_Byte_Enable
IO_Write_Data
IO_Read_Data
IO_Ready

top level裡面將 address 0xc0000000 送入的資料slv_reg0LED
SDK裡面可以寫入測試,可以看到板子上LED全亮

#include "stdio.h"
#include "platform.h"
#include "xparameters.h"
#include "xiomodule.h"
#include "xiomodule_l.h"
#include "xdebug.h"
#include "xio.h"

u32 volatile *LED = (u32 volatile *)(0xC0000000); // slv_reg0
void print(char *str);
int main()
{
   init_platform();
   print("HELLO LED \n\r");
   *LED = 0x000000ff;

   cleanup_platform();
   return 0;

}

如果改變 C 或是 VHDL 都會重新產生ELF或是BIT 所以都要重新下COMMAND
Command>data2mem -bm ipcore_dir/microblaze_mcs_bd.bmm -bd workspace/hello_world_0/Debug/hello_world_0.elf -bt ml605_mcs_top.bit -o b download.bit

,再燒入版子才看的到結果


沒有留言:

張貼留言