# FPGA 共筆 南大
[TOC]
# 環境設定
> 使用 Windows 的同學請直接去安裝 Quartus II,因為 mac 和 linux 沒有與其相同版本的 Quartus II,所以可以採用以下方法
## Verilog
Linux
```bash
sudo apt update
sudo apt install iverilog gtkwave
```
macOS: (請事先安裝好 [brew](https://brew.sh) )
```bash
brew install icarus-verilog gtkwave
```
## VHDL
Linux
```bash
sudo apt update
sudo apt install ghdl gtkwave
```
macOS: (請事先安裝好 [brew](https://brew.sh) )
```bash
brew install ghdl
brew install --cask gtkwave
```
# 語法
## Cheatsheets
* Verilog: https://marceluda.github.io/rp_dummy/EEOF2018/Verilog_Cheat_Sheet.pdf
* VHDL: https://owd.tcnj.edu/~hernande/r/VHDL_QRC__01.pdf
## Comments
Verilog
``` verilog
// One line comment
/*
Two line comment
just like C
*/
```
VHDL
```vhdl
-- This is the only way
-- to comment in VHDL
-- yeck! 🤮
```
## Modules
```verilog
module name(
// Input and output
);
// your code here
endmodule
module name(); // no input, etc testbench
endmodule
```
```vhdl
-- What on earth is this??
entity entity_name is port (
-- your input and output
);
end entity_name;
architecture arch_name is
-- constants, variable, singals, components
-- can be declared here
begin
-- your code here
end arch_name;
-- no input, etc testbench
entity entity_name is port ();
end entity_name;
-- remain the same...
```
## Input and Output
Verilog
```verilog
module main(
// inputs
input a, // one bit input
input[0:3] b, // little endian input
input[3:0] c, // big endian input
// outputs
output d, // one bit output
output[0:3] e, // little endian output
output[0:3] f, // big endian output
// register (memorize your state)
output reg g // register also as an output
// no "," at the end
);
reg h; // a register
reg[0:7] i; // one byte register
// your code here
endmodule
// also can written in
module main(a,b,c,d,e,f,g);
// inputs
input a, // one bit input
input[0:3] b, // little endian input
input[3:0] c, // big endian input
// outputs
output d, // one bit output
output[0:3] e, // little endian output
output[0:3] f, // big endian output
// register (memorize your state)
output reg g // register also as an output
reg h;
reg[0:7] i;
endmodule
```
VHDL
```vhdl
entity example_entity is port(
a: in std_logic;
b: in std_logic_vector(0 to 3);
c: in std_logic_vector(3 downto 0);
d: out std_logic;
e: out std_logic_vector(0 to 3);
f: out std_logic_vector(3 downto 0);
);
end example_entity;
```
# Testbench 撰寫
> 這裡假設你對 Verilog 的撰寫擁有一定的基礎
## Verilog
Testbench 的結構大致會呈現如下:
你一定會有一個 main module,這裡假設是 `main.v` 和 main:
```verilog
module main(
...
);
... your code here ...
endmodule
```
testbench 基本上就是一個程式測資,和任何程式的 unit test 一樣,他是一個可以運作的程式(在這裏是電路)
你一定會這幾個段落:
1. 測試的輸入和輸出 變數/wire/暫存器,偶爾可能還會有一些測試資料
2. 你需要在 tester 裡調用你自己的 main module(top level entry )
3. 你需要 clock 和留有一些 delay 給你的程式,如下定義
main_test.v
```verilog
`timescale 1ns/ 1ns
`include "main.v"
module tester();
// inputs for your main module
reg clk;
reg reset;
reg start;
reg din;
// outputs for your main module
// > outputs should always be "wire"
wire count_out;
wire[0:3] count_one;
wire dout_valid;
wire dout;
// your constants data
reg[0:7] data = 8'b01010010;
// This part will
// connect your main module into tester module
main m(
.reset(reset),
.clk(clk),
.start(start),
.din(din),
.count_out(count_out),
.count_one(count_one),
.dout_valid(dout_valid),
.dout(dout)
);
// maybe some integer to count on
integer i;
// the part of only run once
initial begin
// this part is very important!
// this define the vvp (runtime) to output
// the wave file result main_test.vcd
// for later with the signals inside tester module
$dumpfile("main_test.vcd");
$dumpvars(0, tester);
clk = 0;
reset = 0;
start = 0;
din = 0;
// send a reset signal
// this means waiting 2 unit of time
// as well as defined in $timescale
#2;
reset = 1;
#2;
reset = 0;
// ...
for (i = 0; i < 8; i = i + 1) begin
din = data[i];
#2;
end
// ...
// This is also very important!
// To stop the vvp simulation,
// you'll need this line
$finish;
end
// generate clock signal for every 1 unit of time
//
// why not #2? because one cycle of clock
// required two changes, high and low,
// so the program above will wait every 2 unit of time
always #1 clk = ~clk;
endmodule
```
最後再執行這個 tester 就可以了。
vvp 是 iverilog 的模擬環境,用來模擬你編譯好的 verilog。
```
iverilog -o main_test.vvp main_test.v
vvp main_test.vvp
```
模擬完後理論上會出現一個 main_test.vcd
1. 在你的資料夾內,用 GTKWave File > Open Tab 開啟這個檔案
2. 再SST裡選擇你的 module
3. 在下方選擇要觀測的訊號,按下最下面的 Insert
4. 然後就可以看到你的執行結果了。
如果你再次模擬了程式,只需要 File > Reload Waveform 或按下快捷鍵 Ctrl+Shift+R 即可載入最新結果
# 延深閱讀
## 影片教學
用 GHDL + gtkwave 模擬 VHDL
{%youtube j9hya97kRJA %}
用 iverilog + gtkwave 模擬 verilog
{%youtube 3Xm6fgKAO94 %}
## Links
* 如何寫 Testbench:https://ithelp.ithome.com.tw/articles/10192465