2011年11月24日木曜日

PicoBlaze を使ってみる


by yosikawa » 2011年2月13日(日) 12:10
さて、スイッチとLEDを確認できたので液晶表示に進みたいところだが、
ハードウェアだけで液晶を使うのは大変だ。その前に PicoBlaze を使いこなしたい。

例によってすごく簡単なことから始める。
簡単といっても、最小限、マシン語のプログラムを書かないといけない。

コード: 全て選択
      ADDRESS 000      ; Programs always start at reset vector 0
BEGIN:
      LOAD s0, a1
      OUTPUT s0, 00
      JUMP BEGIN      ; Embedded applications never end


ADDRESS は開始アドレスを指定している。PicoBlaze のアドレス空間は10ビット。
000~3ffの範囲。

BEGINはラベル。ジャンプ先を指定している。

LOADはどんなCPUにも必ずある命令で、ここではレジスタs0に16進数の a1h を代入している。
レジスタはs0~sF までの16個。sの次の文字が16進数になっている。
各レジスタの大きさは8bit。すべてのレジスタは同じように機能し、特別な役割を持ったレジスタはない。

OUTPUT はI/Oポート出力。PicoBlaze と外部とのやり取りはすべてI/Oポートから行う。
ここではレジスタs0の内容をポートアドレス00h (必ず16進数2桁で書かないといけない)に出力している。

JUMP は無条件ジャンプ命令。条件によらずかならずBEGINで示した場所に飛ぶ。

よってこのプログラムは、出力ポート00h に16進数の a1h を出力し続ける。
a1h という値に特に意味はない。ffhとかだと、何か他の理由でも起こりうるが、a1h のパターンでLEDが光れば、
これはもう疑いなくPicoBlaze から届いた値と分かるから。

さて、これをアセンブラにかけて、verilogソースに変換する。
xilinxのサイトでPicoBlaze で検索してSpartan-3E用のPicoBlaze をダウンロードする。
ダウンロードするにはユーザ登録が必要。
KCPSM3.zip をダウンロードしたらこれを展開して、Assemblerフォルダの中のファイルをすべて
作業ディレクトリにコピーする。同じ場所に上記アセンブラプログラムを置く。名前はここではt4_rom.psm とした。
コード: 
KCPSM3.EXE t4_rom.psm > out.txt

上記コマンドでアセンブルする。出力されたout.txtの最後がsuccessfulなら成功。
以下は出力例。
コード: 
KCPSM3  v1.30.      Ken Chapman (Xilinx-UK) 2005

The assembler for KCPSM3 Programmable State Machine

PASS 1 - Reading input PSM file
.......
.......
.......
PASS 11 - Writing memory definition files
           t4_rom.hex
           t4_rom.dec
           t4_rom.mem


KCPSM3 successful.

KCPSM3 complete.


成功すると、T4_ROM.V というファイルができる。
これは先ほどのマシン語プログラムから作成されたROMのverilogソースだ。
ROMのハードウェア定義と、マシン語のプログラムの定義も一緒に含まれているので、
PicoBlaze とつなぐだけだ。

プロジェクトを作成する。プロジェクトは以下のファイルからなる。
  • top.v
  • kcpsm3.v
  • t4_rom.v
  • top.ucf

top.v と top.ucf は以下に掲載する。kcpsm3.vがPicoBlaze のverilogソースだ。

top.v
コード: 
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    03:19:51 02/13/2011 
// Design Name: 
// Module Name:    top 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
`default_nettype none
module top(clk, led);

   input wire clk;               // グローバルクロック
   output reg [7:0] led;         // LED
   
   // PicoBlaze の信号定義
   wire [9:0] address;
   wire [17:0] instruction;
   wire [7:0] port_id;
   wire write_strobe;
   wire [7:0] out_port;
   wire read_strobe;
   reg [7:0] in_port = 0;
   reg interrupt = 0;
   wire interrupt_ack;
   wire reset = 1;

   // PicoBlaze インスタンス定義 (resetはアクティブ・ハイ)
   kcpsm3 kcpsm3(
      address,
      instruction,
      port_id,
      write_strobe,
      out_port,
      read_strobe,
      in_port,
      interrupt,
      interrupt_ack,
      ‾reset,
      clk);

   //ROM 定義
   t4_rom t4_rom(address, instruction, clk);
   
   // 出力ポートから信号を取り出す
   always @(posedge clk) begin
      if(write_strobe) begin
         led <= out_port;
      end
   end
   
endmodule


top.ucfは、今回はclkとLEDしか使わないので、他の定義は全部消した。
コード: 
#
# Period constraint for 50MHz operation
#
NET "clk" PERIOD = 20.0ns HIGH 50%;
#
# soldered 50MHz Clock.

NET "clk" LOC = "C9" | IOSTANDARD = LVTTL;
#
#
# Simple LEDs 
# Require only 3.5mA. 
#
NET "led<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<6>" LOC = "E9"  | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<7>" LOC = "F9"  | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
#
#
# End of File
#


以上をコンパイルしてtop.bitを作成する。後はいつものようにボードに書き込む。
見事、期待通りの 10100001 のパターンでLEDが光った。

以下は、PicoBlazeのブロック図。

この図で、左上のPROMの部分だけ、PicoBlazeの外側にある。
PCからPROMにつなぐ線がaddress。(top.vの中のPicoBlazeのパラメータ参照)
PROMからの出力がinstruction。

普通、多くのCPUは外部のメモリを使うが、PicoBlazeのメモリは全部で64バイトしかなく、
すべてPicoBlaze本体に含まれている。
よって外部のメモリは必要ないし、使えない。
だからCPUとROMを繋ぐだけで小型マイコンが動作する。

top.vでは、出力ポートからledに出力している。
コード: 
   // 出力ポートから信号を取り出す
   always @(posedge clk) begin
      if(write_strobe) begin
         led <= out_port;
      end
   end

ポートは1つしかないのでport_idに出力されるポートアドレスは無視した。
write_strobeがハイのときだけ、出力される。

ではここで、PicoBlazeの信号について簡単に説明する。
コード: 
// PicoBlaze の信号定義
module kcpsm3(
   address,
   instruction,
   port_id,
   write_strobe,
   out_port,
   read_strobe,
   in_port,
   interrupt,
   interrupt_ack,
   reset,
   clk) ;

// ROMとの接続用
output    [9:0]   address ;  // ROMのアドレス
input    [17:0] instruction ;  // ROMのデータ。マシン語命令になる。マシン語は18ビット。

// 出力ポート
output    [7:0]   port_id ;  // ポートアドレス。入出力で共通。
output    write_strobe ;  // これがハイのときだけ、出力ポートの内容が有効。
output    [7:0]   out_port ; // 出力ポートの値

// 入力ポート
// port_id は出力と共通
output    read_strobe ;  // PicoBlazeが入力ポートから読み込むタイミングより1パルス前にハイになる。でも通常この信号は不要。
input    [7:0]   in_port ;  // 入力ポートの値

// 割り込み
input      interrupt ;  // これをハイにすると割り込みを要求する。
output    interrupt_ack ;  // これがハイになると、割り込みを受け付けたことを表す。

// その他
input      reset ;  // リセット。ハイになるとリセットする。
input      clk ;  // クロック。50MHzをそのまま接続してもいいし、もっと遅いクロックでもいい。どんなに遅くても動作する。


入出力ポートをいかに使いこなすかがキモになる。
例えば入出力ポートにRAMを繋げは、最大256バイトまでメモリ空間を拡張できる。
次回は入力にスイッチをつないでみる。

2/13 追記
ユーザガイドの日本語版があった。英語版を読み終わった後で気づいた。。。
PicoBlaze 8 ビット エンベデッド マイクロコントローラ ユーザー ガイド (Spartan-3 Generation、Virtex-II、および Virtex-II Pro FPGA 用) v1.1.1 (日本語版)(PDF, ver 1.1.2, 1.55 MB )

Spartan-3E スタータキットのユーザガイドも、実は日本語版があった。
Spartan-3E スタータキット. ボード ユーザーガイド. UG230 (v1.0) 2006 年 3 月 9 日

0 件のコメント:

コメントを投稿