Ml605 microblaze with your own IP
無可避免的還是用microblaze比較威,先來建立一個自己的IP放在AXI,方便接來下用UART進來的資料可以一起經由bus進入IP內部的邏輯
前兩年做過的東西早就忘光了,今天又依照tutorial
做了一次,趕快來紀錄一下,這樣下次複習比較快XDDDD
Tutorial 原版
EDK
Concepts, Tools, and Techniques
A
Hands-On Guide to EffectiveEmbedded System Design
UG683
(v13.4) January 18, 2012
建立一個專案,新增processer
選擇讓processor先預選基本的配備,然後在刪掉不需要的
把local
memory size 調大一點
把timer新增進來,並加上interrupt
LED之後要做測試用所以不加進來
完成了以後可以看到大致的結構
接下來新增一個自己的IP
依照tutorial
新增一個blink
ip,然後一直按到finish
打開\system\pcores\blink_v1_00_a\hdl\vhdl
裡面的兩個vhdl檔來新增port與寫入功能
在blink.vhdl裡
在user_logic.vhdl裡,利用輸入address的data來決定讓led閃爍或是停止
在打開\system\pcores\blink_v1_00_a\data
裡面的
blink_v2_1_0.mpd
將LEDs加入port
改完了以後按
就會在左側的ip列表裡面看到剛剛的blink,按兩下加入bus
base_address 先不用改,稍後系統會自動分配
按port把leds拉到外面的pin
在addresses可以看到我們新增的ip的address為0x7c600000
接下來按hardware-
generate netlist
成功了以後來寫top
level與ucf,注意blink_0_LEDs_pin
是否出現在output
pin
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_microblaze_top is Port ( osc_200m_p : in STD_LOGIC; osc_200m_n : in STD_LOGIC; reset : in STD_LOGIC; uart_tx : out STD_LOGIC; uart_rx : in STD_LOGIC; gpio_led : out STD_LOGIC_VECTOR (3 downto 0); gpio_dip : in STD_LOGIC_VECTOR (7 downto 0)); end ml605_microblaze_top; architecture Behavioral of ml605_microblaze_top is component system is port ( RS232_Uart_1_sout : out std_logic; RS232_Uart_1_sin : in std_logic; RESET : in std_logic; blink_0_LEDs_pin : out std_logic_vector(3 downto 0); DIP_Switches_8Bits_TRI_I : in std_logic_vector(7 downto 0); CLK_P : in std_logic; CLK_N : in std_logic ); end component; begin microblaze_i : system port map ( RS232_Uart_1_sout => uart_tx, RS232_Uart_1_sin => uart_rx, RESET => reset, blink_0_LEDs_pin => gpio_led, DIP_Switches_8Bits_TRI_I => gpio_dip, CLK_P => osc_200m_p, CLK_N => osc_200m_n ); end Behavioral;
NET osc_200m_n LOC = "H9" | DIFF_TERM = "TRUE" | IOSTANDARD = "LVDS_25"; NET osc_200m_p LOC = "J9" | DIFF_TERM = "TRUE" | IOSTANDARD = "LVDS_25"; NET gpio_dip[0] LOC = "D22" | IOSTANDARD = "LVCMOS15"; NET gpio_dip[1] LOC = "C22" | IOSTANDARD = "LVCMOS15"; NET gpio_dip[2] LOC = "L21" | IOSTANDARD = "LVCMOS15"; NET gpio_dip[3] LOC = "L20" | IOSTANDARD = "LVCMOS15"; NET gpio_dip[4] LOC = "C18" | IOSTANDARD = "LVCMOS15"; NET gpio_dip[5] LOC = "B18" | IOSTANDARD = "LVCMOS15"; NET gpio_dip[6] LOC = "K22" | IOSTANDARD = "LVCMOS15"; NET gpio_dip[7] LOC = "K21" | IOSTANDARD = "LVCMOS15"; NET gpio_led[0] LOC = "AC22" | IOSTANDARD = "LVCMOS25"; NET gpio_led[1] LOC = "AC24" | IOSTANDARD = "LVCMOS25"; NET gpio_led[2] LOC = "AE22" | IOSTANDARD = "LVCMOS25"; NET gpio_led[3] LOC = "AE23" | IOSTANDARD = "LVCMOS25"; NET reset LOC = "H10" | IOSTANDARD = "SSTL15" | TIG; NET uart_rx LOC = "J24" | IOSTANDARD = "LVCMOS25"; NET uart_tx LOC = "J25" | IOSTANDARD = "LVCMOS25";
接下來在ISE
geberate programming file
新增一個workspace資料夾
之後在XPS上直接連到SDK,指向剛剛新增的workspace
可以看到SDK上已經有Processor的資料
file-new-application project
新增一個hello
world project
然後programm
FPGA
接下來可以用兩種方法來玩一下UART
- hello world 不用改,用XMD Console
XMD% Accepted a new TCLSock connection from 127.0.0.1 on port 53775 Programming Bitstream -- D:/ml605_microblaze/workspace/system_hw_platform/download.bit Fpga Programming Progress ......10....20....30....40....50....60....70....80....90.....Done mb JTAG chain configuration -------------------------------------------------- Device ID Code IR Length Part Name 1 0a001093 8 System_ACE_CF 2 64250093 10 XC6VLX240T MicroBlaze Processor Configuration : ------------------------------------- Version............................8.40.b Optimization.......................Performance Interconnect.......................AXI-LE MMU Type...........................No_MMU No of PC Breakpoints...............1 No of Read Addr/Data Watchpoints...0 No of Write Addr/Data Watchpoints..0 Instruction Cache Support..........off Data Cache Support.................off Exceptions Support................off FPU Support.......................off Hard Divider Support...............off Hard Multiplier Support............on - (Mul32) Barrel Shifter Support.............on MSR clr/set Instruction Support....on Compare Instruction Support........on Data Cache Write-back Support......off Fault Tolerance Support............off Stack Protection Support...........off Connected to MicroBlaze "mdm" target. id = 0 Starting GDB server for "mdm" target (id = 0) at TCP port no 1234 Note:: "mbconnect" command is Deprecated. Use "connect mb" command XMD% stop Processor stopped XMD% mwr 0x7c600000 0x1 XMD% mrd 0x7c600000 7C600000: 00000001 XMD% mwr 0x7c600000 0x0 XMD%
第二種方法新增peripheral_tests_0
application project , 讓我們用c來控制uart
可以看到在左欄已經產了一些與周邊相關的程式,但這不是全部我需要的XD
我需要可以一個可以從UART搜集資料進來變成hex,好讓我可以把資料送入microblaze的axi
bus,進而控制自創IP的LED
裡面的reference code中的xlib_string.h與xil_string.c,人家寫好的函式總是比較好用阿XD
\xapp493_DisplayPort_SPM\XAPP493\v6\ML605\sdk_workspace\dp_source_policy_maker_0\src
xlib_string.h
//#define SIMULATION #define DEBUG_LEVEL 1 #include "xil_types.h" #define PRINT_TS 0 #define PRINT_EDID 1 #define LLC_TEST_MODE 0 #if (DEBUG_LEVEL >= 4) #define dbg4_printf xil_printf #else #define dbg4_printf do_nothing #endif #if (DEBUG_LEVEL >= 3) #define dbg3_printf xil_printf #else #define dbg3_printf do_nothing #endif #if (DEBUG_LEVEL >= 2) #define dbg2_printf xil_printf #else #define dbg2_printf do_nothing #endif #if (DEBUG_LEVEL >= 1) #define dbg_printf xil_printf #define dbg1_printf xil_printf #else #define dbg_printf do_nothing #define dbg1_printf do_nothing #endif #if (DEBUG_LEVEL == 0) #define dbg_printf do_nothing #endif #define dbg_llc_printf do_nothing //xil_printf #define dbg1_llc_printf do_nothing //xil_printf #define dbg2_llc_printf do_nothing void do_nothing(); char xil_getc(u32 timeout_ms); u32 xil_gethex(u8 num_chars);
xil_string.c
#include "xlib_string.h" #include "stdio.h" #include "xlib_string.h" #include "xuartlite_l.h" #include "xparameters.h" #include "xtmrctr.h" char xil_getc(u32 timeout_ms){ char c; u32 timeout = 0; extern XTmrCtr TimerCounter; //dbg_printf ("timeout_ms = %x\n\r",timeout_ms); // Reset and start timer if ( timeout_ms > 0 && timeout_ms != 0xff ){ XTmrCtr_Start(&TimerCounter, 0); //dbg_printf ("timeout_ms = %x\n\r",timeout_ms); } while(XUartLite_IsReceiveEmpty(STDIN_BASEADDRESS) && (timeout == 0)){ if ( timeout_ms == 0 ){ // no timeout - wait for ever timeout = 0; } else if ( timeout_ms == 0xff ) { // no wait - special case timeout = 1; } else if(timeout_ms > 0){ if(XTmrCtr_GetValue(&TimerCounter, 0) > ( timeout_ms * (XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ / 1000) )){ timeout = 1; } } } if(timeout == 1){ c = 0; } else { c = XUartLite_RecvByte(STDIN_BASEADDRESS); } return c; } u32 xil_gethex(u8 num_chars){ u32 data; u32 i; u8 term_key; data = 0; for(i=0;i= 'a') { term_key = term_key - 'a' + 10; } else if(term_key >= 'A') { term_key = term_key - 'A' + 10; } else { term_key = term_key - '0'; } data = (data << 4) + term_key; } return data; } void do_nothing(){ }
將這兩個檔案加入我們建立的peripheral
project中,因為要init
platform, 所以也把hello_world_0
裡面的platform.c,
platform.h, platform_config.h 加入
peripheral project
將原本的testperiph.c
的main()拿掉,加入剛剛的h
file
#include#include "xparameters.h" #include "xil_cache.h" #include "xintc.h" #include "intc_header.h" #include "uartlite_header.h" #include "xbasic_types.h" #include "xgpio.h" #include "gpio_header.h" #include "xtmrctr.h" #include "tmrctr_header.h" #include "tmrctr_intr_header.h" //------------------ ADD CODE --------------------- #include "xlib_string.h" #include "platform.h" void reg_write(u32 reg_address, u32 data); u32 reg_read(u32 reg_address); XTmrCtr TimerCounter; int main() { init_platform(); while(1){ dbg_printf(" TEST "); u32 addr = xil_gethex(8); u32 data = xil_gethex(8); reg_write(addr,data); }//end while cleanup_platform(); return 0; } void reg_write(u32 reg_address, u32 data) { dbg_printf("reg_write (0x%08x) 0x%08x\n\r", reg_address, data); *(volatile u32*)reg_address = data; } u32 reg_read(u32 reg_address) { dbg_printf("reg_read (0x%08x) ", reg_address); u32 data = *(volatile u32*)reg_address; dbg_printf(" 0x%08x\n\r", data); return data; }
在將產生的elf檔燒入版子,打開tera
term,連續寫入address與data就可以看到板子上的LED已經開始閃耀搂!
要注意一下microblaze的baudrate跟
teraterm的是否一致
如果之後不會再改sdk或是下次懶得再開sdk的話也可以直接把download.bit
燒進去板子裡面,
programm FPGA後的console下方寫著
data2mem -bm D:/ml605_microblaze/edkBmmFile_bd.bmm -bt \ D:/ml605_microblaze/ml605_microblaze_top.bit -bd \ D:/ml605_microblaze/workspace/peripheral_tests_0/Debug/peripheral_tests_0.elf tag \ microblaze_0 -o b D:/ml605_microblaze/workspace/system_hw_platform/download.bit
系統已經自動幫你下command再
workspace/system_hw_platform/download.bit
結論有錢的真的是大爺,系統都幫你做好了,如果用免錢的microblaze就是童養媳的命運阿阿阿阿!!!!
這篇寫得太囉嗦了,後記下一篇用wxpython的serial來寫一個簡單的小介面來跟板子溝通,並產生exe檔方便其他沒有灌python的人使用
沒有留言:
張貼留言