目次
前
次
FPGA用プロセッサテスト
これまで、FPGAにはデジタル回路だけを入れ
外部にマイクロコンピュータを用意して対応
してきました。
利用しているXilinx、Lattice Semiconductorの
FPGAでは、小規模なプロセッサが用意されており
これらを利用すると外部マイコンは、20ピンAVR
でも対応できるのではと思いつきました。
XilinxのFPGAでは、PicoBlazeを使えます。
Lattice SemiconductorのFPGAでは、Mico32
を利用できます。
PicoBlazeは8ビット、Mico32は32ビットです。
Mico32は、OpenSourceであるためXilinxのFPGA
でも利用できます。8ビットにはPicoBlaeを
32ビットにはMico32を1個のFPGAに入れること
にします。
外部にArduinoがあるのに、FPGA中にプロセッサ
を入れるのは、技術的な興味と外部マイコンを
減らして、消費電力を抑制するため。
従来はArduinoの動作クロック16MHzを基本に処理
を考えてきましたが、FPGA内部プロセッサでは
50MHzから100MHzのクロックで動作させることが
可能です。
FPGAは、3.3Vで動作するので、Arduinoの5V消費
電力よりも、より少ない電力で動作させること
が可能になります。
上記の理由から、FPGA中に複数のプロセッサを
入れてみます。
PicoBlazeテスト
PicoBlazeに関係する内容は、次のページで紹介
しています。
http://okgnz.web.fc2.com/pld/pld46.htm
ここでは、PicoBlazeを利用したモーター回転を
テストする処理を考えます。
FPGAは、Spartan3を実装した基板を使います。
FPGAに内蔵するブロックは、以下としました。
- clock divider
- PicoBlaze
- PWM generator
- input buffer
- LED buffer
- synchronizer
順を追って、各ブロックの担当する内容を決めます。
clock divider
利用するFPGA基板には、48MHzのシステムクロック
ジェネレータがあります。
PicoBlazeやPWM波形生成器が必要とするクロック
を生成します。
PicoBlaze
外付けするDIPスイッチの値を読み込んで
PWM波形生成器に渡します。
PWM generator
clock dividerからはクロックを、PicoBlazeから
PWM波形のDUTY比を受取り、2つのPWM波形を生成
します。
2つのPWM波形を生成するのは、2個のDCモータを
利用することを想定しているため。
input buffer
外付けするDIPスイッチの値をバッファします。
PWM波形生成器が必要とするDUTY比は、最大で100
になるので、7ビットあれば充分です。8ビット
目を、左右どちらのDUTY比を与えられたのかを
判定するために使います。
LED buffer
外付けするDIPスイッチの値でDUTY比を設定する
ので、2つのLEDブロックを利用して、DUTY比を
表示します。利用するLED基板は、以下。
synchronizer
PicoBlazeとinput bufferの同期をとるために
利用します。
各ブロックの担当内容を決めたので、VHDLコードと
アセンブリ言語コードを定義します。
clock divider
PicoBlazeのクロックを1MHz、PWM波形生成器で利用
するクロックを10kHzとします。
48MHzのシステムクロックを48分周し
1MHzを生成。1MHzの100分周で10kHz
を生成します。
48分周で1MHzのクロックのDUTY比を1:1にします。
CONSTANT CNTMAX : integer := 47 ;
CONSTANT CNTHALF : integer := 24 ;
-- clock divider (generate 1MHz)
signal iCNT : integer range 0 to CNTMAX ;
signal iCLK : std_logic ;
process (nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iCNT <= 0 ;
elsif rising_edge(CLOCK) then
if ( iCNT = CNTMAX ) then
iCNT <= 0 ;
else
iCNT <= iCNT + 1 ;
end if ;
end if ;
end process ;
iCLK <= '1' when ( iCNT < CNTHALF ) else '0' ;
100分周で1MHzのクロックから10kHzを生成します。
CONSTANT SCNTMAX : integer := 99 ;
CONSTANT SCNTHALF : integer := 50 ;
-- clock divider (generate 10kHz)
signal iSCNT : integer range 0 to SCNTMAX ;
signal iSCLK : std_logic ;
process (nRESET,iCLK)
begin
if ( nRESET = '0' ) then
iSCNT <= 0 ;
elsif rising_edge(iCLK) then
if ( iSCNT = SCNTMAX ) then
iSCNT <= 0 ;
else
iSCNT <= iSCNT + 1 ;
end if ;
end if ;
end process ;
iSCLK <= '1' when ( iSCNT < SCNTHALF ) else '0' ;
PicoBlaze
内部に用意した2レジスタの値を読み込んで
PWM波形生成器が参照する2レジスタに出力します。
;++++++++++++++++++++++++
; input
;++++++++++++++++++++++++
CONSTANT RIGHT,00 ; right register
CONSTANT LEFT,01 ; left register
;++++++++++++++++++++++++
; output
;++++++++++++++++++++++++
CONSTANT XRIGHT,00 ; right register
CONSTANT XLEFT,01 ; left register
;++++++++++++++++++++++++
; redefine register name
;++++++++++++++++++++++++
NAMEREG s0,RREG
NAMEREG s1,LREG
;++++++++++++++++++++++++
; entry address
;++++++++++++++++++++++++
ADDRESS 000
;++++++++++++++++++++++++
; initialize
;++++++++++++++++++++++++
INIT:
; clear
XOR RREG,RREG
XOR LREG,LREG
;++++++++++++++++++++++++
; main loop
;++++++++++++++++++++++++
MAIN:
; get both duty ratio
INPUT RREG,RIGHT
INPUT LREG,LEFT
; masking
AND RREG,7F
AND LREG,7F
; compare
COMPARE RREG,63
JUMP C,MAIN1
COMPARE LREG,63
JUMP C,MAIN2
MAIN1:
LOAD RREG,63
JUMP MAINE
MAIN2:
LOAD LREG,63
MAINE:
; put both duty ratio
OUTPUT RREG,XRIGHT
OUTPUT LREG,XLEFT
;
JUMP MAIN
PWM generator
DUTY比を7ビットx2で入力し、2ビットのパルスを
出力します。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity pwmgen is
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ; -- 10kHz
-- duty ratio
XRIGHT : in std_logic_vector(6 downto 0) ;
XLEFT : in std_logic_vector(6 downto 0) ;
-- pulse output
POUT : out std_logic_vector(1 downto 0) --;
) ;
end pwmgen;
architecture Behavioral of pwmgen is
--
CONSTANT PCNTMAX : integer := 99 ;
-- counter
signal iPCNT : integer range 0 to PCNTMAX ;
-- input
signal iLEFTX : integer range 0 to PCNTMAX ;
signal iRIGHTX : integer range 0 to PCNTMAX ;
-- pulse output
signal iLOUT : std_logic ;
signal iROUT : std_logic ;
begin
-- input
iLEFTX <= conv_integer(XLEFT) ;
iRIGHTX <= conv_integer(XRIGHT) ;
-- output
POUT <= iLOUT & iROUT ;
-- decoder
iLOUT <= '1' when ( iPCNT < iLEFTX ) else '0' ;
iROUT <= '1' when ( iPCNT < iRIGHTX ) else '0' ;
-- counter
process (nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iPCNT <= 0 ;
elsif rising_edge(CLOCK) then
if ( iPCNT = PCNTMAX ) then
iPCNT <= 0 ;
else
iPCNT <= iPCNT + 1 ;
end if ;
end if ;
end process ;
end Behavioral;
input buffer
8ビットのうち、7ビットをDUTY比に割当てしますが
8ビット全体を入力しておき、振り分けます。
signal iDin : std_logic_vector(7 downto 0) ;
signal iLEFT : std_logic_vector(6 downto 0) ;
signal iRIGHT : std_logic_vector(6 downto 0) ;
iDin <= Din ;
process (nRESET,iCLK)
begin
if ( nRESET = '0' ) then
iLEFT <= (others => '0') ;
iRIGHT <= (others => '0') ;
elsif rising_edge(iCLK) then
if ( iDin(7) = '1' ) then
iLEFT <= iDin(6 downto 0) ;
else
iRIGHT <= iDin(6 downto 0) ;
end if ;
end if ;
end process ;
LED buffer
7ビットをDUTY比を負論理で出力します。
GLED <= not iLEFT ;
RLED <= not iRIGHT ;
synchronizer
PicoBlazeは、データ入出力にストローブ信号を
利用します。入出力にクロックを利用した同期
回路をはさんでおきます。
-- PicoBlaze input
process (nRESET,iCLK)
begin
if ( nRESET = '0' ) then
XDin <= '0' ;
elsif rising_edge(iCLK) then
if ( iRDSTB = '1' ) then
if ( iPID = X"00" ) then
XDin <= iRIGHT ;
end if ;
if ( iPID = X"01" ) then
XDin <= iLEFT ;
end if ;
end if ;
end if ;
end process ;
-- PicoBlaze output
process (nRESET,iCLK)
begin
if ( nRESET = '0' ) then
XRIGHT <= (others => '0') ;
XLEFT <= (others => '0') ;
elsif rising_edge(iCLK) then
if ( iWRSTB = '1' ) then
if ( iPID = X"00" ) then
XRIGHT <= iXDout ;
end if ;
if ( iPID = X"01" ) then
XLEFT <= iXDout ;
end if ;
end if ;
end if ;
end process ;
(under construction)
Mico32テスト
Mico32は、Lattice Semiconductor社のFPGAに実装できる
32ビットプロセッサですが、XilinxやAlteraのFPGAでも
動くとされています。
2015年7月時点のMico32開発ツールは、3.5となっています。
このVersionの開発環境は、Diamond3.5が必要です。
Diamond3.5のインストーラ一式をダウンロードして
インストールしてみると、以前の開発環境Diamond2.2
と共存できるようになっていました。
(under construction)
目次
前
次