Spartan6でmicroblaze mcs  を動かす①ISE編

Spartan6 FPGAを搭載したATLYSボードを使用してソフトコアCPU(microblaze_mcs)を動作させる手順。

# ハードウェアプロジェクトの生成


# CORE Generatorプロジェクトの追加
`New Source`よりCPUを追加

![mcs1.jpg](https://qiita-image-store.s3.amazonaws.com/0/204268/c93ec4f6-a0bd-7e04-7b05-d9e2eef64770.jpeg)

ソースタイプを`IP(CORE Generator...)`にする。
`File name`は任意の名前でOK
`Location`も任意のディレィクトリでOK
![mcs2.jpg](https://qiita-image-store.s3.amazonaws.com/0/204268/f95f012a-a041-db02-8218-2bb6956b9dde.jpeg)

IPから`MicroBlaze MCS`を選択しNextへ
![mcs3.jpg](https://qiita-image-store.s3.amazonaws.com/0/204268/8e937432-7d74-58d7-f40c-2f326392614d.jpeg)

# CPU(microblaze_mcs)の設定
## MCS
設定項目|内容|説明
---|---|---
Insrance Hierarchical Design Name|インスタンス名|任意の名前でOK<br>ただしインスタンス名は後で使用する
Input Clock Freqency|CPUの処理クロック周波数|ATLYSボードには100MHzのオシレータがのっているので100にする<br>(周波数は使用環境に合わせて設定する。ここの設定と実態のクロック周波数があっていないと、シリアルポートのボーレートと不整合がおき、シリアル通信で文字化けする)
Memory Size|CPUの１時メモリサイズ|大きくするほどプログラムサイズに余裕は出る<br>しかしBlockRAMを消費するのでシステム全体でバランスをとる必要がある<br>※今回は最大の64KBにする。
Enable IO Bus|汎用バスを付けるか否か|汎用バスをつけることで自作IP（モジュール）にアクセス可能になる<br>今後IPを増設するのでONにしておく
Enable Debug Support|デバッグ機能|Onにしておくと、プログラムをブレーク（途中で止める）したりデバッグが可能になる

![mcs4.jpg](https://qiita-image-store.s3.amazonaws.com/0/204268/63417992-a5db-f665-6165-f28f882ecbe5.jpeg)

## UART
*UARTを使用するので`Receiver` `Transmitter`ともにONにする。
*ボーレートは任意（今回は115200とする）
*8bitのパリティ無しにする
*__![mcs6.jpg](https://qiita-image-store.s3.amazonaws.com/0/204268/2c4c0399-9984-6623-283c-0791aa9bac36.jpeg)
受信したときに割り込み処理をかけたいので`Implement Receive Interrrupt`をONにしておく__

##GPO
ATLYSボードの8個のLEDをGPOにつなげるので今回は8個とする。
![mcs5.jpg](https://qiita-image-store.s3.amazonaws.com/0/204268/ee02cd53-9936-f4f1-7a24-95a6de5508b2.jpeg)

##GPI
ATLYSボードの8個のスライドスイッチをGPIにつなげるので今回は8個とする。
![mcs7.jpg](https://qiita-image-store.s3.amazonaws.com/0/204268/d4dac8bc-3ce4-fd97-6732-de0d57909f03.jpeg)

CPUコアの生成は以上。
プロジェクトにCPUが追加されていればOK
`Dessign`タブの`View HDL Instantiation Template`をダブルクリックすると、インスタンスする際のひな形が出てくるので、これをコピーしてアレンジします。
![mcs8.jpg](https://qiita-image-store.s3.amazonaws.com/0/204268/84ffe8cd-fa7c-ac47-489e-7dc3173e6618.jpeg)


# トップモジュールへの組み込み
CPUをFPGAのトップモジュールの配下へ組み込みます

```VHDL:TOP.vhd
	library	ieee;
	use	ieee.std_logic_1164.all;
	
	entity ATLYS_TOP is
		port(
		i_clk100m	:in		std_logic						;--クロック
		i_rst_sw_n	:in		std_logic						;--リセット
		i_UART_RX	:in		std_logic						;--シリアルポート受信
		o_UART_TX	:out	std_logic						;--シリアルポート送信
		i_DIP_SW	:in		std_logic_vector(7 downto 0)	;--ＤＩＰスイッチ
		o_LED		:out	std_logic_vector(7 downto 0)	);--ＬＥＤ
	end	entity;
	
architecture RTL of ATLYS_TOP is
	
	component CPU
		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						;
		UART_Interrupt	:out	std_logic						;
		GPO1			:out	std_logic_vector(7 downto 0)	;
		GPI1			:in		std_logic_vector(7 downto 0)	;
		GPI1_Interrupt	:out	std_logic						;
		INTC_IRQ		:out	std_logic						);
	end component;
	
	signal	clk		:std_logic						;
	signal	rst		:std_logic						;
	signal	uart_rx	:std_logic						;
	signal	uart_tx	:std_logic						;
	signal	gpi		:std_logic_vector(7 downto 0)	;
	signal	gpo		:std_logic_vector(7 downto 0)	;
	
	--***************************************
	begin
	--***************************************
	
	-----------------------------
	--Input port
	-----------------------------
	clk		<=i_clk100m			;
	rst		<=not i_rst_sw_n	;
	uart_rx	<=i_UART_RX			;
	gpi		<=i_DIP_SW			;
	
	-----------------------------
	--Output port
	-----------------------------
	o_UART_TX	<=uart_tx		;
	o_LED		<=gpo			;
	
	
	--CPU
	mcs_0 :CPU
	port map
	(Clk			=>clk			--100MHz
	,Reset			=>rst			--High Reset
	,IO_Addr_Strobe	=>open			--not use
	,IO_Read_Strobe	=>open			--not use
	,IO_Write_Strobe=>open			--not use
	,IO_Address		=>open			--not use
	,IO_Byte_Enable	=>open			--not use
	,IO_Write_Data	=>open			--not use
	,IO_Read_Data	=>x"00000000"	--not use
	,IO_Ready		=>'0'			--not use
	,UART_Rx		=>uart_rx		--UART port
	,UART_Tx		=>uart_tx		--UART port
	,UART_Interrupt	=>open			--not use
	,GPO1			=>gpo			--LED
	,GPI1			=>gpi			--DIP-SW
	,GPI1_Interrupt	=>open			--not use
	,INTC_IRQ		=>open			--not use
	);
	
end	architecture;
```

# UCFファイル
ATLYSボードに合わせたピン配置及び電気的をUCFファイルに記述します。
このときにCPUのメモリであるBlockRAMの配置を指定します。
(プログラムをアップロードする際にBlockRAMの位置情報が必要になるため、予め固定しておく)

```:PIN.ucf
CONFIG VCCAUX = 3.3;

NET "i_clk100m"   LOC = "L15" | IOSTANDARD = LVCMOS33;
TIMESPEC TS_clk100 = PERIOD "clk100" 100 MHz HIGH 50%;

NET "i_rst_sw_n"  LOC = "T15" | IOSTANDARD = LVCMOS33;

NET "i_DIP_SW<0>"   LOC = "A10" | IOSTANDARD = LVCMOS33;
NET "i_DIP_SW<1>"   LOC = "D14" | IOSTANDARD = LVCMOS33;
NET "i_DIP_SW<2>"   LOC = "C14" | IOSTANDARD = LVCMOS33;
NET "i_DIP_SW<3>"   LOC = "P15" | IOSTANDARD = LVCMOS33;
NET "i_DIP_SW<4>"   LOC = "P12" | IOSTANDARD = LVCMOS33;
NET "i_DIP_SW<5>"   LOC = "R5"  | IOSTANDARD = LVCMOS33;
NET "i_DIP_SW<6>"   LOC = "T5" | IOSTANDARD = LVCMOS33;
NET "i_DIP_SW<7>"   LOC = "E4" | IOSTANDARD = LVCMOS33;

NET "o_LED<0>"  LOC = "U18" | IOSTANDARD = LVCMOS33;
NET "o_LED<1>"  LOC = "M14" | IOSTANDARD = LVCMOS33;
NET "o_LED<2>"  LOC = "N14" | IOSTANDARD = LVCMOS33;
NET "o_LED<3>"  LOC = "L14" | IOSTANDARD = LVCMOS33;
NET "o_LED<4>"  LOC = "M13" | IOSTANDARD = LVCMOS33;
NET "o_LED<5>"  LOC = "D4"  | IOSTANDARD = LVCMOS33;
NET "o_LED<6>"  LOC = "P16" | IOSTANDARD = LVCMOS33;
NET "o_LED<7>"  LOC = "N12" | IOSTANDARD = LVCMOS33;

NET "i_UART_RX"	LOC ="A16" | IOSTANDARD = LVCMOS33;
NET "o_UART_TX"	LOC ="B16" | IOSTANDARD = LVCMOS33;


INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[0].RAMB16_S1_1" LOC = RAMB16_X0Y30;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[1].RAMB16_S1_1" LOC = RAMB16_X1Y30;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[2].RAMB16_S1_1" LOC = RAMB16_X2Y30;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[3].RAMB16_S1_1" LOC = RAMB16_X3Y30;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[4].RAMB16_S1_1" LOC = RAMB16_X0Y28;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[5].RAMB16_S1_1" LOC = RAMB16_X1Y28;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[6].RAMB16_S1_1" LOC = RAMB16_X2Y28;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[7].RAMB16_S1_1" LOC = RAMB16_X3Y28;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[8].RAMB16_S1_1" LOC = RAMB16_X0Y26;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[9].RAMB16_S1_1" LOC = RAMB16_X1Y26;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[10].RAMB16_S1_1" LOC = RAMB16_X2Y26;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[11].RAMB16_S1_1" LOC = RAMB16_X3Y26;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[12].RAMB16_S1_1" LOC = RAMB16_X0Y24;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[13].RAMB16_S1_1" LOC = RAMB16_X1Y24;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[14].RAMB16_S1_1" LOC = RAMB16_X2Y24;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[15].RAMB16_S1_1" LOC = RAMB16_X3Y24;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[16].RAMB16_S1_1" LOC = RAMB16_X0Y22;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[17].RAMB16_S1_1" LOC = RAMB16_X1Y22;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[18].RAMB16_S1_1" LOC = RAMB16_X2Y22;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[19].RAMB16_S1_1" LOC = RAMB16_X3Y22;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[20].RAMB16_S1_1" LOC = RAMB16_X0Y20;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[21].RAMB16_S1_1" LOC = RAMB16_X1Y20;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[22].RAMB16_S1_1" LOC = RAMB16_X2Y20;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[23].RAMB16_S1_1" LOC = RAMB16_X3Y20;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[24].RAMB16_S1_1" LOC = RAMB16_X0Y18;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[25].RAMB16_S1_1" LOC = RAMB16_X1Y18;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[26].RAMB16_S1_1" LOC = RAMB16_X2Y18;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[27].RAMB16_S1_1" LOC = RAMB16_X3Y18;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[28].RAMB16_S1_1" LOC = RAMB16_X0Y16;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[29].RAMB16_S1_1" LOC = RAMB16_X1Y16;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[30].RAMB16_S1_1" LOC = RAMB16_X2Y16;
INST "mcs_0/U0/lmb_bram_I/RAM_Inst/Using_B16_S1.The_BRAMs[31].RAMB16_S1_1" LOC = RAMB16_X3Y16;
```

# 書き込みファイルの生成
ISEにて`Synthsize-XST`⇒`Implement Design`⇒`Generate Programming File`の順に実行し書き込みデータ(bitファイル)を生成する。

ISEでの作業はここまでです。
SDKでの作業に続きます。