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的人使用