01signal.com

Smart Zynq로 8개의 서보 모터 제어

이 웹 페이지는 Smart Zynq board의 기능을 탐색하는 소규모 프로젝트 그룹 에 속합니다.

소개

시중에는 SG90, MG90S, MG995 , MG996R와 같은 간단하고 저렴한 DC 서보 모터가 여러 개 있습니다. 이러한 모터는 취미 프로젝트, 특히 간단한 로봇을 만드는 데 사용됩니다. 이러한 모터는 단일 PWM signal로 제어됩니다.

일부 모터는 일반적으로 180도인 제한된 각도 범위 내에서 회전합니다. 이러한 모터의 경우 PWM signal은 모터의 각도 위치를 제어합니다. 다른 모터(종종 "360도 모터"라고 함)는 지속적으로 회전할 수 있습니다. 이러한 모터의 경우 PWM signal은 회전 속도와 방향을 제어합니다. 모터 모델은 종종 두 가지 변형으로 제공됩니다. 각도가 제한된 한 가지 변형과 지속적으로 회전할 수 있는 두 번째 변형이 있습니다. 이런 종류의 모터를 구매할 때 이 차이점에 주의하는 것이 중요합니다.

이 튜토리얼은 최대 8개의 서보 모터를 Smart Zynq board 에 연결하고 간단한 Linux command의 도움으로 이러한 모터를 제어하는 방법을 보여줍니다. 이 튜토리얼은 또한 FPGA내부에 register 인터페이스를 구현하기 위해 Xillybus의 seekable streams를 사용하는 방법을 보여줍니다.

이 튜토리얼에 표시된 전기 배선은 설명과 사진을 간단하게 유지하기 위해 하나의 모터에만 적합합니다. 여기에 표시된 것과 같은 구성 요소에 전선을 추가하는 것만으로 더 많은 모터를 추가할 수 있습니다.

모터의 전기 인터페이스

해당 유형의 서보 모터에 대한 연결은 3개의 전선으로 구성됩니다.

PWM signal은 20ms (50Hz)의 주기 시간을 가져야 합니다. pulse가 높은 지속 시간은 모터의 위치 또는 각속도를 제어합니다.

대부분의 datasheets에 따르면 pulse의 지속 시간은 1ms 와 2ms사이여야 합니다. 이 정보는 일부 모터에 대해 부정확합니다. 예를 들어, Tower Pro의 SG90 (180도 회전 한계 있음)에 대한 올바른 범위는 대략 500μs 에서 2450μs사이입니다. 이 범위는 180도 회전에 해당합니다. pulse 에서 최대 2560μs까지 모터를 약간 더 회전할 수 있습니다. 이 모터는 이보다 긴 pulse를 무시합니다.

따라서 모터가 반응하는 pulse 지속 시간 범위를 탐색하기 위해서는 datasheet에 의존하기보다는 모터를 실험하는 것이 더 좋습니다. 이러한 모터는 취미 프로젝트를 위한 것이므로 사양 데이터가 정확하지 않을 수 있습니다.

전기 연결

우선, 서보 모터는 기계 모터에 에너지를 공급하기 위해 별도의 전원 공급 장치가 필요합니다. 이 전원 공급 장치의 전압은 +5V입니다. Smart Zynq board에 전원을 공급하는 전원 공급 장치는 사용하지 않는 것이 좋습니다. 모터는 종종 전압 레벨에 급격한 변화를 일으키기 때문입니다. Smart Zynq board는 전원 공급 장치 전압이 불안정하면 신뢰할 수 없게 작동할 수 있습니다.

오렌지색 전선의 PWM signal은 이 신호가 높을 때 전원 공급 장치와 거의 같은 전압을 가져야 합니다. 즉, 오렌지색 전선과 ground 사이의 전압은 0 또는 대략 +5V여야 합니다.

하지만 Smart Zynq board의 output voltage는 높을 때만 3.3V 입니다. 이러한 output이 모터의 오렌지색 전선에 직접 연결되면 모터가 올바르게 응답할 가능성이 높습니다. 그 이유는 5V 전원 공급 장치를 기반으로 하는 디지털 회로는 일반적으로 2.5V 이상의 전압을 logic '1'로 간주하기 때문입니다.

즉, PWM signal에 3.3V 전압을 인가했을 때 모터가 안정적으로 작동할지 여부는 불확실합니다. 권장되는 해결책은 Smart Zynq board를 0V 또는 5V로 변환하는 voltage level shifter를 사용하는 것입니다. 이 튜토리얼에서는 TXS0108E chip이 있는 작은 board를 사용합니다. 이 board는 chip의 pins를 노출시킬 뿐이므로 일반 전선을 chip에 연결할 수 있습니다.

이 그림은 하나의 서보 모터를 제어하기 위해 전기 연결이 어떻게 배열되는지 보여줍니다. 그림 하단의 Smart Zynq board는 Dupont wires의 도움으로 TXS0108E Board 에 연결됩니다. 이 board 의 다른 쪽은 서보 모터의 PWM input 와 모터의 별도 전원 공급 장치(표준 전원 공급 플러그용 어댑터를 통해)에 연결됩니다. 모터의 빨간색과 갈색 전선도 이 board에 납땜되어 모터에 전원 공급 전압을 제공합니다.

Connecting the Smart Zynq board with a servo motor with the help of a TXS0108E voltage level shifter

이 그림은 TXS0108E Board 와 그 연결에 대한 자세한 모습을 보여줍니다.

Connections to the TXS0108E voltage level shifter, in detail

OE 와 VA사이의 빨간색 전선에 주의하세요. 이렇게 하면 chip의 output enable이 높은지 확인할 수 있습니다.

Smart Zynq의 pin header 에 대한 연결은 다음 그림에 나와 있습니다. 모터는 여기에 연결된 J6/1 에 의해 제어됩니다.

Dupont wire connections with the Smart Zynq board for controlling a servo motor

이 표는 관련된 네 부분 간의 연결을 요약한 것입니다.

TXS0108E Board pin Smart Zynq pin 모터의 전선 +5V 전원 공급 장치 논평
VA J6/37 (3.3V) -- -- OE에도 연결됨
A4 J6/1 -- --
OE -- -- -- VA에 연결됨
GND J6/35 (GND) 브라운 wire GND
VB -- 레드 wire +5V
B4 -- 오렌지 wire --

TXS0108E chip은 A4 input 에서 B4 output까지 voltage level shift를 수행합니다. chip에는 pins 의 추가 쌍이 7개 있습니다. A4/B4 쌍은 이 튜토리얼에서 임의로 선택되었습니다. 8개의 모터를 제어하기 위해 이 chip 의 모든 8개의 pin 쌍을 사용할 수 있습니다. 여기에는 표시되지 않습니다. 8개의 모터를 제어하는 데 필요한 전선의 양이 그림을 이해하기 어렵게 만들기 때문입니다.

J6 pin header를 찾으려면 Smart Zynq board뒷면에 "Bank 33 VCCIO Vadj"라고 쓰여 있는 곳을 찾으세요. 이 표시에 가까운 pins 행이 이 튜토리얼에서 사용되는 pin header 입니다. 따라서 J6/1은 HDMI 커넥터에 가장 가까운 pin 입니다.

Smart Zynq board는 USB ports중 하나를 통해 별도의 전원 공급 장치에 연결되어 있다는 점에 유의하세요. 또한 J6 pin header의 마지막 pin은 5V가 므로 이 pin에 전선을 연결하지 마세요.

Vivado 프로젝트 준비

demo bundle의 zip 파일( boot partition kit)에서 새 Vivado 프로젝트를 만듭니다. 텍스트 편집기에서 verilog/src/xillydemo.v를 엽니다. "PART 4"라는 레이블이 붙은 code 부분을 삭제합니다. 그 부분 대신 다음을 삽입합니다.

assign  user_r_mem_8_empty = 0;
   assign  user_r_mem_8_eof = 0;
   assign  user_w_mem_8_full = 0;

   reg [7:0] reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;

   always @(posedge bus_clk)
     if (user_w_mem_8_wren)
       case (user_mem_8_addr[2:0])
	 0: reg0 <= user_w_mem_8_data;
	 1: reg1 <= user_w_mem_8_data;
	 2: reg2 <= user_w_mem_8_data;
	 3: reg3 <= user_w_mem_8_data;
	 4: reg4 <= user_w_mem_8_data;
	 5: reg5 <= user_w_mem_8_data;
	 6: reg6 <= user_w_mem_8_data;
	 7: reg7 <= user_w_mem_8_data;
       endcase

   reg [7:0] mem_8_data_reg;
   assign user_r_mem_8_data = mem_8_data_reg;

   always @(posedge bus_clk)
     if (user_r_mem_8_rden)
       case (user_mem_8_addr[2:0])
	 0: mem_8_data_reg <= reg0;
	 1: mem_8_data_reg <= reg1;
	 2: mem_8_data_reg <= reg2;
	 3: mem_8_data_reg <= reg3;
	 4: mem_8_data_reg <= reg4;
	 5: mem_8_data_reg <= reg5;
	 6: mem_8_data_reg <= reg6;
	 7: mem_8_data_reg <= reg7;
       endcase

   servo_pwm servo_pwm_i [7:0]
     (
      .clk(bus_clk),
      .rst(quiesce),
      .pwm_signal(J6[7:0]),
      .pwm_width( { reg7, reg6, reg5, reg4, reg3, reg2, reg1, reg0 } )
      );

이 링크 에서 업데이트된 xillydemo.v를 다운로드할 수도 있습니다.

프로젝트의 verilog/src/ directory에 다음을 포함하는 새 파일 servo_pwm.v를 만듭니다( copy-paste를 사용하거나 이 링크 에서 다운로드).

module servo_pwm
  (
   input clk,
   input rst,

   output reg pwm_signal,
   input [7:0] pwm_width
  );

   reg [9:0]  enable_count;
   reg 	      enable;

   reg [10:0] pwm_count;
   reg [8:0]  threshold;

   always @(posedge clk)
     begin
	if (enable_count == 999)
	  begin
	     enable_count <= 0;
	     enable <= 1;
	  end
	else
	  begin
	     enable_count <= enable_count + 1;
	     enable <= 0;
	  end

	threshold <= pwm_width + 50; // Add 0.5 ms to PWM width

	if (enable)
	  begin
	     if (pwm_count == 1999)
	       pwm_count <= 0;
	     else
	       pwm_count <= pwm_count + 1;

	     pwm_signal <= (pwm_count < threshold);
	  end

	if (rst)
	  begin
	     enable_count <= 0;
	     pwm_count <= 0;
	     pwm_signal <= 0;
	  end
     end
endmodule

그런 다음 Vivado 프로젝트에 파일을 추가합니다. File > Add Sources…를 클릭하고 "Add or create design sources"를 선택합니다. 그런 다음 Next를 클릭합니다. "Add Files" button을 클릭하고 verilog/src/ directory에서 "servo_pwm.v"라는 파일을 선택합니다. 그런 다음 "Finish" button을 클릭합니다.

demo bundle용 bitstream 파일을 생성한 것과 동일한 방법으로 업데이트된 프로젝트에서 bitstream 파일을 생성합니다. 또한 동일한 방법으로 bitstream 파일을 TF card 에 복사합니다(기존 xillydemo.bit 파일을 이 프로젝트로 생성된 파일로 덮어쓰기).

서보 모터 제어

이 섹션에 표시된 단계는 Smart Zynq board의 shell prompt 에서 수행해야 합니다.

먼저 directory를 변경하고 Xillybus에 대한 데모 애플리케이션의 compilation을 수행합니다.

# cd ~/xillybus/demoapps/
# make
gcc  -g -Wall -O3 memwrite.c -o memwrite
gcc  -g -Wall -O3 memread.c -o memread
gcc  -g -Wall -O3 streamread.c -o streamread
gcc  -g -Wall -O3 streamwrite.c -o streamwrite
gcc  -g -Wall -O3 -pthread fifo.c -o fifo

FPGA 에는 서보 모터를 제어하기 위한 8개의 registers가 있습니다. 처음에는 값이 모두 0입니다. 이 값을 10진수 형식으로 출력하는 방법은 다음과 같습니다.

# hexdump -v -n 8 -e '8/1 "%u " "\n" ' /dev/xillybus_mem_8
0 0 0 0 0 0 0 0

더 간단한 hexdump command를 사용하면 16진수 형식으로 동일한 값을 출력할 수 있습니다.

# hexdump -v -n 8 -C /dev/xillybus_mem_8
00000000  00 00 00 00 00 00 00 00                           |........|
00000008

memwrite program ( xillybus/demoapps/ directory내부)를 사용하여 모터를 제어할 수 있습니다. 예를 들어, 이 command는 register 0 의 값을 120로 변경합니다.

# ./memwrite /dev/xillybus_mem_8 0 120

이렇게 하면 J6/1 에 연결된 모터의 회전 위치나 속도가 변경됩니다(위 사진 참조).

PWM pulse 의 너비는 다음 공식에 따라 register 의 값에 따라 달라집니다.

t = 500 + (x * 10)

이 공식에서 t는 마이크로초로 주어지고, x는 관련된 register의 값입니다. 따라서 pulse 의 기본 너비는 500μs (즉, x=0)입니다. 위의 command는 register 의 값을 120로 변경했습니다. 결과적으로 pulse의 너비는 1700μs로 변경되었습니다.

각 register는 하나의 byte로 구성되어 있으므로 값의 범위는 0 에서 255까지입니다. 따라서 각 모터의 pulse는 500μs 와 3050μs사이의 폭을 갖도록 수정할 수 있습니다. 이 값 범위의 일부는 대부분 모터에서 불법으로 간주됩니다. 각 모터로 다양한 가능성을 시도하고 어떻게 반응하는지 확인하는 것이 가장 좋습니다.

다른 pin에 연결된 모터를 제어하려면 다른 register에 쓰세요. 예를 들어, 모터가 Smart Zynq의 J6/4에 연결된 경우 이 command를 사용할 수 있습니다. 예:

# ./memwrite /dev/xillybus_mem_8 3 50

이 command는 pulse 의 너비를 1000μs (즉, 1 ms)로 변경합니다.

이 두 commands다음에 값을 다시 읽어 보면 변경 사항을 확인할 수 있습니다.

# hexdump -v -n 8 -e '8/1 "%u " "\n" ' /dev/xillybus_mem_8
120 0 0 50 0 0 0 0

이것은 10진수 형식의 값을 보여줍니다. 16진수 형식의 경우:

# hexdump -v -n 8 -C /dev/xillybus_mem_8
00000000  78 00 00 32 00 00 00 00                           |x..2....|
00000008

memwrite 작동 방식

memwrite 의 source code는 ~/xillybus/demoapps/ directory의 memwrite.c 라는 파일입니다. 이 program은 Xillybus의 seekable streams를 사용하여 registers 에 액세스하는 방법을 보여줍니다. 이 program이 어떻게 작동하는지 이해하려면 source code를 살펴보는 것이 좋습니다. 아래에서 두 가지 중요한 부분만 살펴보겠습니다.

program은 첫 번째 argument에 주어진 이름의 파일을 엽니다. 이 파일의 file descriptor는 variable @fd에 저장됩니다.

그러면 program은 다음과 같이 lseek() 에 대한 함수 호출을 수행합니다.

if (lseek(fd, address, SEEK_SET) < 0) {
    perror("Failed to seek");
    exit(1);
  }

variable @address 에는 program의 두 번째 argument가 들어 있습니다. 위의 memwrite를 사용하는 첫 번째 예에서 이는 0였습니다. 두 번째 예에서는 3였습니다. 일반적으로 lseek()은 파일 내의 특정 위치로 이동하는 데 사용됩니다. 이 경우 파일 내의 위치는 액세스하려는 register 의 번호와 같습니다.

다음으로, program은 allwrite()에 대한 함수 호출을 수행합니다.

allwrite(fd, &data, 1);

이것은 파일에 하나의 byte를 씁니다. allwrite()는 memwrite.c에 정의되어 있으며 잘 알려진 function write()와 비슷합니다. 따라서 allwrite()를 사용하는 대신 이것은 거의 동일합니다.

write(fd, &data, 1);

차이점은 write()가 데이터가 쓰여지는 것을 보장하지 않는다는 것입니다. 반면, allwrite()함수는 데이터가 파일에 쓰여지는 것을 보장합니다.

이 경우, allwrite() 에 대한 함수 호출은 program의 세 번째 argument의 값을 씁니다. 다시 말해, 이것은 register의 새로운 값입니다.

host 측의 Xillybus의 API 에 대한 자세한 내용은 이 주제에 대한 문서 , 특히 6.1섹션을 참조하세요.

Verilog code에 대한 설명

먼저 xillydemo.v 의 Verilog code가 FPGA내부의 registers를 구현하는 방법을 보여드리겠습니다. 이어서 PWM pulse를 구현하는 방법을 보여드리겠습니다.

registers 하드웨어를 구현하기 위한Xillybus의 API 에 대해서는 Xillybus FPGA designer's guide 에서 자세히 설명합니다.

registers 와 관련된 wires는 이미 원래 xillydemo.v 파일에 정의되어 있습니다.

// Wires related to /dev/xillybus_mem_8
  wire  user_r_mem_8_rden;
  wire  user_r_mem_8_empty;
  wire [7:0] user_r_mem_8_data;
  wire  user_r_mem_8_eof;
  wire  user_r_mem_8_open;
  wire  user_w_mem_8_wren;
  wire  user_w_mem_8_full;
  wire [7:0] user_w_mem_8_data;
  wire  user_w_mem_8_open;
  wire [4:0] user_mem_8_addr;
  wire  user_mem_8_addr_update;

이러한 wires는 instantiation의 일부로 Xillybus IP core 에 연결됩니다.

xillybus xillybus_ins (

    // Ports related to /dev/xillybus_mem_8
    // FPGA to CPU signals:
    .user_r_mem_8_rden(user_r_mem_8_rden),
    .user_r_mem_8_empty(user_r_mem_8_empty),
    .user_r_mem_8_data(user_r_mem_8_data),
    .user_r_mem_8_eof(user_r_mem_8_eof),
    .user_r_mem_8_open(user_r_mem_8_open),

    // CPU to FPGA signals:
    .user_w_mem_8_wren(user_w_mem_8_wren),
    .user_w_mem_8_full(user_w_mem_8_full),
    .user_w_mem_8_data(user_w_mem_8_data),
    .user_w_mem_8_open(user_w_mem_8_open),

    // Address signals:
    .user_mem_8_addr(user_mem_8_addr),
    .user_mem_8_addr_update(user_mem_8_addr_update),

[ ... ]

    .quiesce(quiesce)
  );

다음으로, 이 프로젝트를 위해 특별히 추가된 Verilog code를 살펴보겠습니다. 이 부분부터 시작해서 host와의 데이터 교환에 flow control이 적용되지 않도록 합니다.

assign  user_r_mem_8_empty = 0;
   assign  user_r_mem_8_eof = 0;
   assign  user_w_mem_8_full = 0;

8개의 registers는 다음과 같이 선언됩니다.

reg [7:0] reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;

다음 부분에서는 registers에 대한 쓰기 작업을 구현합니다. @user_w_mem_8_wren이 높으면 registers중 하나에 새 값이 기록됩니다. @user_mem_8_addr는 영향을 받는 register를 선택합니다. @user_w_mem_8_wren 와 @user_mem_8_addr는 모두 Xillybus IP core의 outputs 입니다.

always @(posedge bus_clk)
     if (user_w_mem_8_wren)
       case (user_mem_8_addr[2:0])
	 0: reg0 <= user_w_mem_8_data;
	 1: reg1 <= user_w_mem_8_data;
	 2: reg2 <= user_w_mem_8_data;
	 3: reg3 <= user_w_mem_8_data;
	 4: reg4 <= user_w_mem_8_data;
	 5: reg5 <= user_w_mem_8_data;
	 6: reg6 <= user_w_mem_8_data;
	 7: reg7 <= user_w_mem_8_data;
       endcase

이후, 이러한 registers 에서 값을 읽는 기능이 구현되었습니다. @user_r_mem_8_rden이 높으면 @user_r_mem_8_data가 업데이트되어 registers중 하나의 값을 포함합니다. @user_mem_8_addr는 어떤 register의 값을 읽을지 선택합니다.

reg [7:0] mem_8_data_reg;
   assign user_r_mem_8_data = mem_8_data_reg;

   always @(posedge bus_clk)
     if (user_r_mem_8_rden)
       case (user_mem_8_addr[2:0])
	 0: mem_8_data_reg <= reg0;
	 1: mem_8_data_reg <= reg1;
	 2: mem_8_data_reg <= reg2;
	 3: mem_8_data_reg <= reg3;
	 4: mem_8_data_reg <= reg4;
	 5: mem_8_data_reg <= reg5;
	 6: mem_8_data_reg <= reg6;
	 7: mem_8_data_reg <= reg7;
       endcase

마지막으로 servo_pwm module 의 instantiation이 등장합니다.

servo_pwm servo_pwm_i [7:0]
     (
      .clk(bus_clk),
      .rst(quiesce),
      .pwm_signal(J6[7:0]),
      .pwm_width( { reg7, reg6, reg5, reg4, reg3, reg2, reg1, reg0 } )
      );

이 instantiation은 servo_pwm의 동일한 사본 8개를 생성합니다. 첫 번째 사본은 reg0 와 J6[0]에 연결되고, 두 번째 사본은 reg1 와 J6[1] 에 연결됩니다.

이제 servo_pwm module을 살펴보겠습니다. module의 ports 와 registers를 선언하는 것으로 시작합니다.

module servo_pwm
  (
   input clk,
   input rst,

   output reg pwm_signal,
   input [7:0] pwm_width
  );

   reg [9:0]  enable_count;
   reg 	      enable;

   reg [10:0] pwm_count;
   reg [8:0]  threshold;

이전에 @pwm_signal이 register의 값을 수신하고, 이 값은 host의 memwrite command 의 도움으로 업데이트된다는 것을 기억하세요. @pwm_signal은 Smart Zynq board의 pin에 연결되므로, 이것은 오렌지색 전선을 통해 모터에 도착하는 신호입니다.

이 module 의 다음 부분은 strobe signal을 구현합니다. @enable은 1000개의 clock cycles중 한 번 높습니다. @clk의 frequency는 100 MHz입니다. 따라서 @enable은 10μs의 모든 기간 중 한 번 높습니다.

always @(posedge clk)
     begin
	if (enable_count == 999)
	  begin
	     enable_count <= 0;
	     enable <= 1;
	  end
	else
	  begin
	     enable_count <= enable_count + 1;
	     enable <= 0;
	  end

앞서 언급했듯이 register의 값 범위인 0 에서 255는 500μs 와 3050μs 사이의 PWM pulse 너비에 해당합니다( pulse의 너비에 대한 expression은 마이크로초 단위의 500 + x * 10였습니다).

따라서 이것은 @threshold를 위한 expression 입니다.

threshold <= pwm_width + 50; // Add 0.5 ms to PWM width

이 register 에는 PWM pulse 동안 @enable이 높은 횟수가 포함됩니다(즉, PWM signal이 높은 경우). 이 expression은 register 의 값이 10μs단위로 PWM pulse 의 길이라는 사실을 반영합니다. 50을 register의 값에 더하면 500μs의 최소 pulse 너비에 해당합니다.

이 부분에서는@enable이 clock enable 로 사용됩니다.

if (enable)
	  begin
	     if (pwm_count == 1999)
	       pwm_count <= 0;
	     else
	       pwm_count <= pwm_count + 1;

	     pwm_signal <= (pwm_count < threshold);
	  end

@pwm_count는 0 에서 1999 까지 세고 다시 시작합니다. 이 counter는 모든 10μs에서 한 번만 바뀌므로 모든 20000μs = 20 ms에서 완전한 라운드를 완료합니다. 즉, PWM pulse의 반복 주기는 필요에 따라 20ms입니다.

@pwm_signal은 @pwm_count가 @threshold보다 작을 때 높습니다. 이것이 pulse의 너비가 register에 의해 제어되는 방식입니다.

이 module 의 마지막 부분은 일부 registers를 재설정하는 것으로 구성됩니다.

if (rst)
	  begin
	     enable_count <= 0;
	     pwm_count <= 0;
	     pwm_signal <= 0;
	  end
     end
endmodule

@rst가 높으면 이 부분은 위에 쓰여진 모든 것을 무효화합니다. 따라서 @rst는 reset signal의 기능을 갖습니다.

Verilog code 와 실제 pins의 관계

위의 Verilog code는 J6라는 이름의 inout port를 사용하지만, 이 port 와의 연결이 어떻게 pin header에 도달할까요? 답은 xillydemo.xdc에서 찾을 수 있습니다. 이 파일은 bitstream ( "vivado-essentials" directory에서)를 만드는 Vivado 프로젝트의 일부입니다.

xillydemo.xdc 에는 FPGA가 전자부품으로 제대로 작동하기 위해 필요한 다양한 정보가 담겨 있습니다. 이 파일에는 다음과 같은 행이 포함되어 있습니다.

[ ... ]

## J6 on board (BANK33 VADJ)
set_property PACKAGE_PIN U22  [get_ports {J6[0]}];   #J6/1  = IO_B33_LN2
set_property PACKAGE_PIN T22  [get_ports {J6[1]}];   #J6/2  = IO_B33_LP2
set_property PACKAGE_PIN W22  [get_ports {J6[2]}];   #J6/3  = IO_B33_LN3
set_property PACKAGE_PIN V22  [get_ports {J6[3]}];   #J6/4  = IO_B33_LP3
set_property PACKAGE_PIN Y21  [get_ports {J6[4]}];   #J6/5  = IO_B33_LN9
set_property PACKAGE_PIN Y20  [get_ports {J6[5]}];   #J6/6  = IO_B33_LP9
set_property PACKAGE_PIN AB22 [get_ports {J6[6]}];   #J6/7  = IO_B33_LN7
set_property PACKAGE_PIN AA22 [get_ports {J6[7]}];   #J6/8  = IO_B33_LP7

[ ... ]

첫 번째 행은 port J6[0]이 U22에 연결되어야 한다고 말합니다. 이것은 FPGA의 물리적 패키지에 있는 위치입니다. Smart Zynq의 schematics에 따르면, 이 FPGA pin은 pin header의 첫 번째 pin 에 연결됩니다. 다른 ports 의 위치는 같은 방식으로 정의됩니다.

요약

이 튜토리얼은 Smart Zynq board 와 Xillybus의 register API를 사용하여 서보 모터를 제어하는 방법을 보여주었습니다. 이 애플리케이션의 host application 와 Verilog code가 제시되었습니다.

이 튜토리얼은 registers의 도움으로 하드웨어 제어가 필요한 다른 애플리케이션의 기초로 사용할 수도 있습니다.

이 페이지는 영어에서 자동으로 번역됩니다. 불분명한 사항이 있으면 원본 페이지를 참조하십시오.
Copyright © 2021-2024. All rights reserved. (38a9d8fd)