2014.7.18

前へ

ホームページトップへ戻る

CPLD+SIMMを使ってUSBプロトコルの解析を!
VHDLを速習! XC95144XL+16MB・SIMMを使ってUSBプロトコルアナライザを作ってしまいました!
主目的は差し迫った事情からUSBプロトコルの解析をすることだったのですが、その手段として選んだのがコレ!


[第84回]


●Xilinx ISE Design Suite を使う(3)

中途半端なままでまことに心苦しいのですけれど、今回をもちまして当テーマについてはとりあえずの締めとしたいと思います。
ましかし、CPLDやFPGA、VHDLはなかなかに興味深いテーマではあると思いますので、いずれ時間ができましたならば、このテーマでまた発展させてみたいと思っております。

当テーマを進めるために、あれこれ試行錯誤を重ねながら短期間に滅多矢鱈たくさんのVHDLファイルを作成してきました。
締めくくりとしましてその中の一本を参考までにご披露したいと思います。
前回ISE Design Suiteにかけましたtest7ta.vhdです。
--- test7 13/12/22 12/23 12/24 12/25 12/26 12/27 12/28 12/30 12/31
--- 14/1/3 1/4 1/5 1/6 1/7 1/11 1/12 1/13 1/14 1/15 1/18 1/19
--- 2/5 2/7
---
---
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity test7ta is

        PORT (CLK :in std_logic;
                        USB_IN :in std_logic;
                        --USB_IN2:std_logic;
                        D_IN2 :in std_logic_vector(7 downto 0);
                        AN :out std_logic_vector(10 downto 0);
                        D_OUT0 :out std_logic_vector(7 downto 0);
                        --D_OUT1 :out std_logic_vector(7 downto 0);
                        D_OUT2 :out std_logic_vector(7 downto 0);
                        --D_OUT3 :out std_logic_vector(7 downto 0);
                        RAS :out std_logic:='1';
                        CAS :out std_logic:='1';
                        WE :out std_logic:='1';
                        RES :in std_logic;
                        WEND :out std_logic:='1');
                        --CHECK0OUT :out std_logic_vector(4 downto 0);
                        --CLKQLOUT :out std_logic_vector(4 downto 0);
                        --NUSB_DOUT :out std_logic);
                        
attribute PIN_ASSIGN :string;
--attribute PIN_ASSIGN of USB_IN2:signal is "107";
attribute PIN_ASSIGN of CLK:signal is "110";
attribute PIN_ASSIGN of USB_IN:signal is "61";
attribute PIN_ASSIGN of RAS:signal is "112";
attribute PIN_ASSIGN of CAS:signal is "113";
attribute PIN_ASSIGN of WE:signal is "115";
attribute PIN_ASSIGN of RES:signal is "23";
attribute PIN_ASSIGN of WEND:signal is "24";
attribute PIN_ASSIGN of AN:signal is "129,128,126,125,124,121,120,119,118,117,116";
attribute PIN_ASSIGN of D_OUT0:signal is "137,136,135,134,133,132,131,130";
--attribute PIN_ASSIGN of D_OUT1:signal is "4,3,2,143,142,140,139,138";
attribute PIN_ASSIGN of D_OUT2:signal is "13,12,11,10,9,7,6,5";
--attribute PIN_ASSIGN of D_OUT3:signal is "22,21,20,19,17,16,15,14";
--attribute PIN_ASSIGN of CLKQLOUT:signal is "86,83,81,79,77";
--attribute PIN_ASSIGN of NUSB_DOUT:signal is "88";
attribute PIN_ASSIGN of D_IN2:signal is "105,104,103,102,101,100,98,97";

end test7ta;

architecture Behavioral of test7ta is

constant zero11 : std_logic_vector(10 downto 0) :="00000000000";
constant ff11 :std_logic_vector(10 downto 0):="11111111111";
constant zero3 : std_logic_vector(2 downto 0) :="000";
signal clkqL:std_logic_vector(2 downto 0):=zero3;
signal clkqm:std_logic_vector(10 downto 0):=zero11;
signal clkqh:std_logic_vector(11 downto 0):=zero11&'0';
signal eclk:std_logic;
signal nusb_d:std_logic;
--signal nusb_2:std_logic;
signal we1:std_logic;
signal usb_d:std_logic;
signal usb_q1:std_logic;
signal usb_q2:std_logic;
signal databf0:std_logic_vector(7 downto 0);
--signal databf1:std_logic_vector(7 downto 0);
--signal databf2:std_logic_vector(7 downto 0);
--signal databf3:std_logic_vector(7 downto 0);
signal nclkqh11:std_logic;
signal d_out0_1:std_logic_vector(7 downto 0);
--signal d_out1_1:std_logic_vector(7 downto 0);
signal d_out2_1:std_logic_vector(7 downto 0);
--signal d_out3_1:std_logic_vector(7 downto 0);
signal an1:std_logic_vector(10 downto 0);
signal ras1:std_logic;
signal cas1:std_logic;
signal gate:std_logic:='0';
--signal check0:std_logic_vector(4 downto 0);
--signal checkf:std_logic_vector(7 downto 0);
--signal checkdt:std_logic_vector(7 downto 0);

begin

usb_d <= usb_q1 xor usb_q2;
nusb_d<=not usb_d;
--nusb_d<=not USB_IN;
--nusb_2<=not USB_IN2;
nclkqh11<=not clkqh(11);
WEND<=clkqh(11);
--eclk<=nclkqh11 and CLK and gate;
eclk<=nclkqh11 and not CLK and gate;
--CHECK0OUT<=check0;
--CLKQLOUT<=clkqL;
--NUSB_DOUT<=nusb_d;

process (USB_IN,RES)
begin
if (RES='0') then
        gate<='0';
        
elsif (rising_edge(USB_IN)) then
        gate<='1';
end if;
end process;


process (we1,clkqm,clkqh,d_out0_1,d_out2_1,an1,ras1,cas1)
begin
        if clkqh(11)='0' then
                D_OUT0<=d_out0_1;
                --D_OUT1<=d_out1_1;
                D_OUT2<=d_out2_1;
                --D_OUT3<=d_out3_1;
                --D_OUT1<=clkqm(7 downto 0);
                --D_OUT2<=clkqh(4 downto 0)&clkqm(10 downto 8);
                --D_OUT3<=clkqh(12 downto 5);
                AN<=an1;
                RAS<=ras1;
                CAS<=cas1;
                WE<=we1;--'0';--we1;
        else
                D_OUT0<="ZZZZZZZZ";
                --D_OUT1<="ZZZZZZZZ";
                D_OUT2<="ZZZZZZZZ";
                --D_OUT3<="ZZZZZZZZ";
                AN<="ZZZZZZZZZZZ";
                RAS<='Z';
                CAS<='Z';
                WE<='1';
        end if;
        end process;

process (eclk,RES,clkqL,clkqm,nusb_d)
begin
        if(RES='0') then
        clkqL<=zero3;
        clkqm<=zero11;
        clkqh<=zero11&'0';
        
        --elsif (clkqL=zero5) then
                        --check0<=zero5;
        elsif (rising_edge(eclk)) then
                        if (clkqL="111") then -- and check0/=zero5) then
                                clkqL<=zero3;-- need this!!!
                                --check0<=zero5;
                                --if (check0/=zero5) then
                                        clkqm<=clkqm+'1';
                                --end if;
                                --check0<=zero5;
                        --else 
                                --clkqL <= clkqL+'1';
                        end if;
                        if (clkqm=ff11) then
                                clkqh<=clkqh+'1';
                                clkqm<=zero11;-- need this!!!
                        end if;
                        usb_q1 <= USB_IN;
                        usb_q2 <= usb_q1;
                        --check0<=check0+nusb_d;
                        databf0(7 downto 0)<=nusb_d&databf0(7 downto 1);
                        --databf1(7 downto 0)<=nusb_d&databf1(7 downto 1);
                        --databf2(7 downto 0)<=USB_IN&databf2(7 downto 1);
                        --databf3(7 downto 0)<=nusb_d&databf3(7 downto 1);
                        clkqL <= clkqL+'1';
        end if;
end process;

-- data write to sdram

process (clkqL,clkqm,clkqh,databf0,D_IN2)--,databf1,databf2,databf3)
begin
        if (clkqL="000") then 
                ras1<='1';
                cas1<='1';
                d_out0_1<=databf0;
                we1<='1';
                --d_out1_1<=clkqm(7 downto 0);
                --d_out2_1<=databf2;
                --d_out3_1<=clkqh(12 downto 5);
                d_out2_1<=D_IN2;
                an1<=clkqm;
        end if;
        if (clkqL="001") then 
                ras1<='0';-- RAS active
                cas1<='1';
                d_out0_1<=databf0;
                d_out2_1<=D_IN2;
                --d_out2_1<=databf2;
                an1<=clkqm;
                we1<='1';
        end if;
        if (clkqL="010") then
                ras1<='0';
                cas1<='1';
                d_out0_1<=databf0;
                d_out2_1<=D_IN2;
                --d_out2_1<=databf2;
                an1<=clkqh(10 downto 0);
                we1<='0';
        end if;
        if (clkqL="011") then
                ras1<='0';
                cas1<='0';-- CAS active
                d_out0_1<=databf0;
                d_out2_1<=D_IN2;
                --d_out2_1<=databf2;
                an1<=clkqh(10 downto 0);
                we1<='0';
        end if;
        if (clkqL="00100") then
                ras1<='0';
                cas1<='0';--    write data
                d_out0_1<=databf0;
                d_out2_1<=D_IN2;
                --d_out2_1<=databf2;
                an1<=clkqh(10 downto 0);
                we1<='0';
        end if;
        if (clkqL="101") then
                ras1<='1';
                cas1<='1';
                d_out0_1<=databf0;
                d_out2_1<=D_IN2;
                --d_out2_1<=databf2;
                an1<=clkqh(10 downto 0);
                we1<='1';
        end if;
end process;

end Behavioral;

なかなかのボリュームでありましょう。
ソースリストの先頭のコメント行でいっぱい日付が並んでいますが、このリストを作るためにこれだけの日数がかかったということではありません。
試行錯誤しながら目的に合ったものをあれこれ作り上げるのに、毎回最初からソースを書くのも芸が無い話ですので、先に作ったソースリストをコピーして、それに必要な部分を書き加え、また不要なところを削除して、ということを繰り返した結果、日付だけが矢鱈付け加えられることになったものです。

しかしこの日付は、VHDLについて全く知識ゼロからスタートして、ここまでのソースを書くことができるようになったという記録でもあります。
およそ2ヶ月ほどの短期速習であります。

このようにして、VHDLを通じてCPLDを実際にさわってみますと、かってどこかに書きましたが、これはもうバーチャルの最たるものだという気がいたします。
中身は完全なブラックボックスでありますね。
ま、ハードの特徴を追求した効率よい書き方なんてものもあるのかも知れませんが、まあちまちま工夫を凝らして四苦八苦するくらいなら、容量とかクロックとかで1クラス上のハードを使うほうが楽でありましょう。

さてこうやってはじめてVHDLを使ってCPLDを動かしてみるという体験をしてみまして、一体これはハードウェアなのだろうか、それともソフトウェアなのだろうか、という疑問が浮かんできました。
私はこの30年以上もの長い間、ハードウェアの技術者であると同時にソフトウェアの技術者でもあるという、いわば両刀使いの経験を積んできました。
今回のVHDLの速習もその過去の経験が大いに助けになっていると思っておりますが、それではそれはハードとソフトのいずれの経験が役に立ったのでありましょうか。

まあ、おそらくその両方なのでありましょうが、ソースを書く過程を思い浮かべてみますと、どうもこれはソフトウェアだなあという気がいたします。
おそらく論理演算の苦手な方にとりましては、VHDLを使いこなすのは至難の技ではありませんでしょうか。
おお、そうそう、まさにロジック回路でありますね。
あれ?
ということはハードウェアか?
ま、とにかくCPLD、VHDLのはじめの一歩はロジック回路の学習、論理演算の理解というところでありましょうか。
うむむ。
CPLD、VHDLの入門キットなんてものを作ってみるのもよいかも知れませんですねえ。
いずれそのうち考えてみましょうか。

次回からは新テーマでの連載開始となります。
乞う、ご期待。

CPLD+SIMMを使ってUSBプロトコルの解析を![第84回]
2014.7.18upload
前へ

ホームページトップへ戻る