ComProcWorkshop/第2章:表示する数値をパソコンから送る
パソコンからシリアル通信で数値を送り、ドットマトリクスLEDに表示する 整数を1つだけ認識する初めての「コンパイラ」を作る
CPUボード無しでワークショップに参加する人はここからスタート
シリアル通信
RS-232やUARTとも呼ばれる
送信、受信にそれぞれ1本ずつの信号線
1ビットずつデータをやり取り
シフトレジスタを用いてエンコード、デコード
シフトレジスタ
https://gyazo.com/d83493ba33061e4f84023ac12ce6d1d0/thumb/400.png
複数ビットの数値を記憶し、端から1ビットずつ取り出す部品
逆に、1ビットずつ書き込んで一気に読むこともできる
PCとUSBで繋ぐにはUSBシリアル変換モジュールをかませる
シリアル通信してみる
UART Master IPを使うためのコードを追加
ターミナルソフト
パソコンでシリアル通信するソフト
試しに8ビット値をいくつか送ってみる
通信速度を9600bpsに設定する
https://gyazo.com/6f6ffffe1dd62a5b12f56fbc491cd476
https://gyazo.com/e8da19332f94e9f31ff328acd1f86e3b
レジスタアドレスの指定
I_RADDRに読みたいレジスタアドレスを指定
0 (RBR):受信データが格納されるレジスタ
5 (LSR):各種ステータスを表すレジスタ
I_RX_EN=1にしてクロックを立ち上げるとI_RADDRが取り込まれる
図ではクロック19、21、23、25のタイミング
読み込みのタイミング
レジスタ値は、次のクロックでO_RDATAに出力される
クロック19でI_RADDR=5が取り込まれ、クロック20でO_RDATAにレジスタ値が出力される
クロック21でI_RADDR=0が取り込まれ、クロック22でO_RDATAにレジスタ値が出力される
rx_vの役割
信号rx_vは、そのときにO_RDATAに出力されているデータが受信データであることを表す
上図の場合、クロック22から24にかけて出力されている「0xA5」が受信データ
データ有無の確認
LSR.RxRDY(ビット0)がデータ有無を表す
0なら、RBRが空
1なら、RBRからデータを読める
rx_rdyはLSR.RxRDY=1のときに1になる信号
assign rx_rdy = ~rx_v & rdata[0];
受信データのビット0がたまたま1であるときにrx_rdy=1になるのを防ぐために~rx_v &
実機での動作写真
https://gyazo.com/02fa8e3de3d8786496598371c1d6470d/thumb/150.png
https://gyazo.com/eeed33b4de762e5e1867616b8e2b6e20/thumb/150.jpg
エコーバック
受信した1バイトをそのまま送り返すこと
現状、PC上では送信が成功したことが分からない
処理系として致命的なので、結果を受け取りたい
エコーバックの動作タイミング
https://gyazo.com/ab2056dfb8b8fbed2ab7cb52bcf37baf
受信した0x41をそのまま送り返している
エコーバックの動作の様子
https://gyazo.com/4306da80d7748ae29c7a9b7f3ad3ab06/thumb/250.jpg
エコーバックされた1バイトが赤字で表示されている
ドットマトリクスLEDの2行目にデータが表示されている
初めてのコンパイラ
整数を1つ認識して16進数に変換し、シリアル通信でFPGAに送る
シリアル通信で戻ってきた値を「出力値」と考える
https://gyazo.com/b6446a55f0efd1bd0a48b3a16b7269b1/thumb/500.png
整数の認識と16進数変換
scanf("%d", &x);で読める
printf("%02x\n", x);で16進数表示できる
表示された16進数をターミナルソフトで送信すると、同じ値が返ってくる
スクリプト内でシリアル通信
コンパイラ出力を自作CPUに送るのに、毎回ターミナルソフトに手動入力したくない
uart.pyで「4f」を送る例
code:Shell
$ ./attach_vcom.sh
Multiple serial devices: please attach by hand.
./attach_vcom.sh BUS_ID
5-1 USB Serial Converter A, USB Serial Converter B Not attached
13-2 USB Serial Converter Not attached
$ ./attach_vcom.sh 13-2
Attaching a specified device: BUS_ID = 13-2
$ sudo ./uart.py 4f
4f
$
uart.pyの説明
引数に16進数を1つ以上指定すると、順に1バイトずつ送信する
上記例では「4f」
送信先はデフォルトで/dev/ttyUSB0
--dev デバイスへのパスというオプションで変更可能
attach_vcom.shの説明
WSL2を使う際に、Linux側からUSBシリアル変換モジュールを見えるようにするスクリプト 事前にusbipdがセットアップされている必要がある
PCに接続されたUSBシリアル変換が1つなら、それをWSLに接続する
複数ある場合、どれをWSLに接続するかを選択する(BUS_ID)
シミュレーションで実験する場合
Icarus Verilog(iverilog)でシミュレーション実行
シリアル通信の代わりに標準入出力を経由してデータをやり取り
コンパイラの出力をシミュレーションから読み、CPUに入力
CPUの出力値をターミナルへ表示
エコーバックのシミュレーション
標準入力から1バイトを読み、標準出力にそのまま表示するだけ
第3章以降で、sim.svと作成したCPUを接続する
test_value 1f 1f
入力した値がそのまま出力されることのテスト
https://gyazo.com/01e3f596eb3275430a3026f4e08ea09f