7-1の応用として、複数のレジスタを使用してみました
・前回、PSからPLのポートを操作するには、vivadoで生成したIPのベースアドレスにアクセスする必要があることがわかりました。
・大全の課題では、reg0のみの使用でしたが、その応用として複数のレジスタを使ってみます。
EBAZ拡張基板をフル活用
・EBAZ に下の拡張基板をつけています。特に課題に無かった、「PLにつながった入力情報をPSから取得」したかったため、拡張基板の5つのSWを活用します。 ➡srv_reg2
・またLEDも3つあり、こちらも使用します。➡srv_reg0
・最後はEBAZ本体に搭載の赤と緑のLEDを使用します。➡srv_reg1
自作IPに記述を追加
・自作IPを再度変更する場合は、myipを右クリックして「Edit IP Packager」を押します。
・別のvivadoが立ち上がり、その画面でIPの再編集を行います。verilogファイルに変更を加えます。
・myip_slave_lite_v1_0_S00_AXI.v と myip.v に新たなポートを記述します。
・大全の記載の場所に、加えていきます。SWの入力読み取りだけは、途中の順序回路に記載します。
・EBAZボード内蔵のLED2個はreg1で、拡張基板のSW5個はreg2で処理します。
・以下が、変更点になります。
myip.v
変更1か所目
// Users to add ports here
output wire [2:0] LED_123,
output wire [1:0] LED,
input wire [4:0] PUSH,
// User ports ends
変更2か所目
myip_slave_lite_v1_0_S00_AXI_inst (
.LED_123(LED_123),
.LED(LED),
.PUSH(PUSH),
.S_AXI_ACLK(s00_axi_aclk),
・myip_slave_lite_v1_0_S00_AXI.v
変更1か所目
// Users to add ports here
output wire [2:0] LED_123,
output wire [1:0] LED,
input wire [4:0] PUSH,
// User ports ends
変更2か所目
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
slv_reg0 <= 0;
slv_reg1 <= 0;
slv_reg2 <= 0;
slv_reg3 <= 0;
end
else begin
slv_reg2[4:0] <= PUSH; // PUSH の5ビットを slv_reg2 の下位5ビットに常に反映
slv_reg2[31:5] <= 27'h0; //残りは0クリア
変更3か所目
// Add user logic here
assign LED_123 = slv_reg0[2:0];/*@yaku*/
assign LED = slv_reg1[1:0];
// User logic ends
変更後は、PackageIPの各項目のチェックを行い、最後Re-PackageIPを行います。
該当するポートの制約ファイルです
# LED123
set_property -dict { PACKAGE_PIN H18 IOSTANDARD LVCMOS33 } \
[get_ports { LED_123[2] }]; # LED3
set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } \
[get_ports { LED_123[1] }]; # LED2
set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } \
[get_ports { LED_123[0] }]; # LED1
# Green LED
set_property IOSTANDARD LVCMOS33 [get_ports {LED[1]}]
set_property PACKAGE_PIN W13 [get_ports {LED[1]}]
# Red LED
set_property IOSTANDARD LVCMOS33 [get_ports {LED[0]}]
set_property PACKAGE_PIN W14 [get_ports {LED[0]}]
# SW
set_property -dict { PACKAGE_PIN T19 IOSTANDARD LVCMOS33 } \
[get_ports { PUSH[0] }];
set_property -dict { PACKAGE_PIN P19 IOSTANDARD LVCMOS33 } \
[get_ports { PUSH[1] }];
set_property -dict { PACKAGE_PIN U20 IOSTANDARD LVCMOS33 } \
[get_ports { PUSH[2] }];
set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } \
[get_ports { PUSH[3] }];
set_property -dict { PACKAGE_PIN V20 IOSTANDARD LVCMOS33 } \
[get_ports { PUSH[4] }];
・最終的なブロックデザインです。
・PUSH(SW)5bit と LED 2bit が追加されました。
・Validate Design を行ってから Generate Bitstream を行います。
vitis のコード説明
・PS側のコードで追加した2つのレジスタ、reg1(EBAZ内蔵の赤緑のLED)、reg2(拡張基板の5個のSW)は
4バイトずつオフセットされます。
・LEDの点滅パターンを1秒周期で変更しながら、SWの状態をログに出力するようにしました。
#include "xparameters.h"
#include "xil_printf.h"
//4バイトずつオフセット
#define LED *((volatile unsigned int*) XPAR_MYIP_0_S00_AXI_BASEADDR)
#define LED1 *((volatile unsigned int*) (XPAR_MYIP_0_S00_AXI_BASEADDR+0x4))
#define READ_SW_STATE *((volatile unsigned int*) (XPAR_MYIP_0_S00_AXI_BASEADDR+0x8))
int main()
{
int i, j;
unsigned int sw_state[5]={0};
xil_printf("Hello FPGA World!\n\r");
xil_printf("BASE_ADDR %X\n\r",XPAR_MYIP_0_S00_AXI_BASEADDR);
while(1) {
for ( i=0; i<4; i++ ) {
for (int i = 0; i < 5; i++) {
sw_state[i] = (READ_SW_STATE & (1 << i)) >> i;
}
xil_printf("i=%d sw_state=%d %d %d %d %d \n\r"
, i,sw_state[0],sw_state[1],sw_state[2],sw_state[3],sw_state[4]);
switch ( i ) {
case 0: LED = 0x1; LED1 = 0x1; break;
case 1: LED = 0x2; LED1 = 0x2;break;
case 2: LED = 0x4; LED1 = 0x0;break;
case 3: LED = 0x0; LED1 = 0x3;break;
default: LED = 0x0; LED1 = 0x3; break;
}
for ( j=0; j<40000000; j++);
}
}
return 0;
}
意図通り動作することが確認できました。
今日はここまで。