2011年10月2日 星期日

J1 Forth CPU 研究之二:如何以 Xilinx ISE 來 Synthesize J1 CPU


這是我有關 J1 Forth CPU 的系列文章中的第二篇,雖然,這篇其實是寫於第一篇之前,已經在符式協會論壇發表過。

以下是當初發表的內容:
因未來工作需要,決定建立 J1 Forth CPU 和 Ethernet 結合的技術。第一個步驟,就是將 WGE100 Camera 的 Firmware 以 Xilinx 的 SP601 板跑起來。

但是在改為 SP601 前,由於 WGE100 Camera 使用的是 Spartan 3E,我先以 Spartan 3E 進行 FPGA 的 Synthesis。以下說明我的經驗:


之後,以 Xilinx ISE 開了一個新的 project,選擇 Family Spartan3E,Device XC3S500E,Package CP132,這應該就是原來的作者使用的 Device 和 Package。


然後把以下的檔案加進來:

verilog 目錄下的:
   ck_div.v  j1.v  reset_gen.v  topj1.v  trig_watchdog.v  uart.v  watchdog.v
verilog/coregen 目錄下的:
   pixfifo.xco
lib/mac 目錄下的:
   crc_chk.v  gmux.v   mac.v       reconciliation.v  rx_raw.v     tx_engine_raw.v
   crc_gen.v  greg.v   mii_mgmt.v  rx_engine_raw.v   rx_usr_if.v
   rx_pkt_fifo.v  tx_raw.v
lib/mac/xilinx/spartan3e 目錄下的:
   device_ODDR.v
lib/mac/xilinx/spartan3e/coregen 目錄下的:
   rx_pkt_fifo_sync.xco
   rxfifo.xco
   txfifo.xco
synth 目錄下的:   wge100_RevC_Camera.ucf

我並未加入所有的 .v 檔,只是先加入 topj1.v ,然後再依據 Design Hierarchy 顯示缺少的元件來加入需要的 .v 檔。當有 .v 和 .xco 檔時我選擇 .xco 檔。最後必須加入 wge100_RevC_Camera.ucf 以解決一個 Error。

如此,就可以從 Synthesis 一直做到 Design implementation 得到 bitstream。

在這之後,我想我必須依據 SP601 的硬體設計來修改 routing,以便讓 Ethernet 真的能跑起來。這樣,就可以透過 Ethernet 和 J1 CPU 上的 Forth 程式溝通了。

J1 Forth CPU 研究之一:Camera Firmware 的程式結構

這是一系列文章中的第一篇,這系列的文章是要解讀 J1 CPU 的設計以及在其上的 Forth 語言的使用法。

在這一篇文章中提及的 J1 被應用於 Camera,其 Forth 程式可以在以下目錄中找到:

https://github.com/chengchangwu/wge100_driver/blob/hydro-devel/wge100_camera_firmware/src/firmware

這個 Forth 以 Gforth 為 Host,J1 Forth CPU 為 Target。

首先,看看這個目錄裡最重要的幾個檔案:
  1. main.fs:這是主程式
  2. crossj1.fs:這是 J1 的 Cross compiler
  3. basewords.fs:在這兒,以 j1 的 assembler 來定義了基本的 Forth 指令。
對許多初學 Forth 的人來說,Cross compiler 無疑是最神秘玄奇之物了。因此讓我們先看看它。只有 512 行,真的很短,在裡面最重要的三個命令是:
  1. meta:執行 meta 後就可以開始定義 J1 的 Cross compiler (或稱為 metacompiler) 了。
  2. target:執行 target 後,之後定義的指令或是資料結構最後都會被放到 target 裡,也就是 j1 16k 的 RAM 裡。
  3. j1asm:執行 j1asm 後可以開始定義 j1 的 assembler。
再來,看看 main.fs 吧,在這個檔案中我們可以看出 cross compiler 是怎麼被使用的。首先,include crossj1.fs 載入了 metacompiler,再來執行 meta,定義了一些常數以及 basewords,最後執行 target,include hwwge.fs 及 boot.fs,然後開始定義 Camera 的應用程式。其中,hwwge.fs 以及位於 boot.fs 之後的程式都只是針對 camera 這個應用,在此就不詳提了,只說明 boot.fs 和在檔案尾端的 0jump。
  1. boot.fs:boot loader,它使用 spi 從 flash 載入整個 Forth 系統。它佔據了記憶體 3e00H 以後的空間,從檔案尾端的 h# 3e00 org 得知它從 3e00H 處開始執行。目前我還不清楚 boot loader 又是怎麼被誰放到 RAM 的 3e00H 後的空間中。這等待以後更瞭解時再向大家報告。
  2. 0jump:在 main.fs 尾端的 0jump 是主程式冷起動的位置。從之前的 0 org 可以知道它的 RAM 位址 是 0。由於有一行 h# 3e00 ubranch 被放在註解中,而 3e00H 是 boot loader 的開始位置,因此我們知道 boot loader 並沒有真的被使用。緊接在那行的是 main ubranch,所以,程式一開始會跳到 main,也就是這個 camera 的應用程式。

2011年9月14日 星期三

學習 Verilog HDL

因為工作需要使用 Xilinx FPGA,我開始學習 FPGA 以及 Verilog。
以下是我的學習過程。

我買了兩本原文書,但幫助不大。目前只讓我知道有 WebPACK 這玩意。

[2011/10/08修正:在開始閱讀我要研究的 j1 Forth CPU 後,其中的一本,Digital Dsign and Verilog HDL Fundamentals 開始有幫助,我覺得這一本寫得很清楚。不過,它缺少了 Verilog 2001 的內容,如 generate/genvar 等。對 generate/genvar 等的說明可以參考 "The IEEE Verilog 1364-2001 Standard, What's New, and Why You Need It" 一文。
]

下載 WebPACK。

閱讀 Xilinx ISE In-Depth Tutorial:
http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_1/ise_tutorial_ug695.pdf

至於 Verilog,弟弟傳了 OVIVerilog HDL LRM Version 1.0 做為參考手冊。

此外,以下連結提供了許多資訊:http://www.asic-world.com/verilog/verilinks.html

以下連結中的 on-line reference guides 也很值得參考: http://www.sutherland-hdl.com/reference-guides.php 。







2011年9月3日 星期六

Why EtherCAT?

以下摘錄自 EtherCAT - the Ethernet fieldbus 這篇文章。

EtherCAT 的特點:
  1. real time 能力。
  2. 多種 Topology。商用 Ethernet 採用星狀的 Topology。EtherCAT 可以使用星狀或環狀或所謂的 E-Bus,以減少配線降低成本。
  3. Only full duplex,分離的 Tx, Rx 線。
  4. Without collision detection and retransmission.
  5. Master/slave 架構。
  6. Master 不需特別的晶片。因此任何有商用 Ethercat 的電腦都可以當 master。
  7. 可和其他 Ethernet 裝置並存於同一 Bus,可以使用商用的 switch。
  8. 就算是將 2bit 的 I/O 獨立做成一 slave 也不會增加太多成本。
  9. 最大效能。Ethernet 頻寬儘量用於傳送 user 的 data。
  10. Short cycle time, < 100 microsecond。
每個裝置都有 64k bytes 的 memory。
EtherCAT 的 telegrams 有兩種可能結構,使用 EtherCAT Header 或是 UDP Header。如果使用 EtherCAT Header ,則第一個裝置必須是一個能處理 MAC 定址的裝置。

EtherCAT 的 telegrams 內有多個 EtherCAT commands,一般來說,一個 command 針對一個 device,但是為了要處理極小的,比如只有 2bit 的 I/O devices,EtherCAT 使用 FMMU 使得一個 EtherCAT command 可以下給多個 devices。FMMU 的 logical address space 是 4GB,因此,對 master 來說,裝置可被視為 distributed memory。

遠距離傳輸時可以使用一般的 Ethernet Cable 或是光纖。較近距離的裝置可以使用以 LVDS 為基礎的 E-Bus。唯一要注意的是必須滿足 EtherCAT full duplex 的要求。

EtherCAT Slave 會從 ethernet telegram 讀取資料,並能插入資料交給下一個 slave。由最後一個 slave 將所有 slaves 的資料回傳給第一個 slave,再由第一個 slave 回傳給 master。(在文章中另一部份說最後一個 slave 將資料回傳給 master。這可能和 EtherCAT telelgrams 的兩種結構有關。當採用 EtherCAT Header 時,第一個 Device 會是有 MAC 定址能力的 device。)


EtherCAT Slave 能偵測斷線而將要送給下一站的資料回傳給上一站。作法請見文件。

EtherCAT Slave 也能偵測斷線回復。作法請見文件。

EtherCAT 使用distributed clocks 來保証所有 slaves 的時間一致。Master 每隔一段時間就會送出特別的 telegram 以較正時間。

除了以上所列,EtherCAT 還提供了不同的定址方法,internode 通訊,同時也允許傳送 Ethernet 訊息。詳情請見文件。

2011年9月2日 星期五

自動化機械展中的工業網路大戰

昨日參觀台北南港展覽館的自動化機械展,想瞭解 EtherCAT 中 E-Bus 的長相。因為,從 Beckhoff 公司的圖片中只見到每個 I/O module 有六個名為 E-Bus 的突出物,完全無法想像當插入新模組時,這新模組怎麼和其他模組相連。

在展場中找尋 Beckhoff 的 EtherCAT 模組時,我先遇到了三菱、Panasonic、Proface、凌華等公司的 PLC。Panasonic 的擴充模組靠一個小接口和主機相連,那接口的形狀限制了擴充模組插拔的方式:只能從左側或是右側插拔,無法從正面插拔。因此,當有多個延伸模組時,必須移動其他的模組才能拔出想要檢修的模組。

為此,當我看到 Beckhoff 的 E-Bus 時,不得不為其設計驚嘆。E-Bus 由六片大銅片構成,模組和模組靠銅片的彈性相接,彷彿放大版的 Ethernet 接口。它可以正面插拔。

對於 E-Bus 我還有一個疑問:它為什麼要用這麼寬的銅片?因為要提供絕佳的接觸嗎?

在現場中,Mechatrolink III 、 SSCNET 及 CC-Link 各有其支持者。PLC 的大廠 OMROM 從 Mechatrolink II 倒向 EtherCAT,Mechatrolink III 支持者安川(Yaskawa)悄悄提供了 EtherCAT 界面的 Drives,讓我感覺到 EtherCAT 在未來的戰事上,至少在必須整合運動控制的市場,獲勝。

會場中展示 Beckhoff 產品的公司員工告訴我台達電計劃明年推出 EtherCAT 的產品,而台達電一直抱怨授權費太高。支持 Mechatrolink III 的安川員工告訴我 FPGA IP 的授權費用高達數十萬。這些,讓我有些許震驚。如果 FPGA IP 的授權費高達數十萬,那顯然不是我目前能採用的。同時,如果台達明年會推出 EtherCAT 產品,那麼我們引進台達 DMCNET 的計劃是否該延後呢?

此外,我發覺自已的一項疏失:EtherCAT似乎不能和 Ethernet/IP 並用?

在展場中另一項吸引我目光的是凌華的 MotionNet,透過在馬達 Drive 端小小的轉接器,MotionNet 可以控制不同公司的馬達。可惜,使用的是 Pulse command,不是我想走的方向。

Note: 以下是我之前詢問過的 EtherCAT IP Core 的價格,那每年都要繳的維護費,真讓人無語啊...


2011年8月11日 星期四

Java NIO 的教材

工作需要我必須學習 Java NIO。在網路上找到了以下兩個連結:

2011年8月8日 星期一

以 batik 讀取 svg 中的 points

如何透過 rhino 及 batik 讀取 SVG 中的 points?

以下是我的程式:


importClass(org.apache.batik.parser.PointsHandler);
importClass(org.apache.batik.parser.PointsParser);

var pp = new PointsParser();
var ph = new PointsHandler({point: function(x, y) {print('('+ x + ',' + y + ')');}});
pp.setPointsHandler(ph);

測試一下:
pp.parse('50,375,150,375 150,325 250,325 250,375,350,375 350,250 450,250 450,375,550,375 550,175 650,175 650,375,750,375 750,100, 850,100 850,375, 50,375 950,25 1050,25 1050,375,1150,375');