---
# System prepended metadata

title: SOC StudyJournal

---

# **Lab3 FIR Design**
[lab3-Github](https://github.com/weixiang1118/SOCLAB3-FIR)

![89a84d7e-fbe2-4661-a4b4-d85462e35e09](https://hackmd.io/_uploads/HkQ_nDMYp.jpg)

* Data_Width 32
* Tape_Num   11
* Data_Num   600
* Interface
    1. data : axi_stream
    2. coef : axi_lite
    3. len : axi_lite
    4. ap_start : axi_lite
    5. ap_done : axi_lite

## **AXI4-Lite Protocol** 
**hint: valid=1 && ready=1 => data transfer**
###  **READ**
read有主要4個控制訊號


    1. arvalid(input) : 等於1時，address可以拿
    2. arready(output) : 去決定我們的address甚麼時候去做transfer
    3. rvalid(output) : 決定我們的data甚麼時候去做transfer
    4. rready(input) : 等於1時，data可以拿
![1](https://hackmd.io/_uploads/Hk0MovGFT.jpg)

### **WRITE**
write有主要4個控制訊號
    
    1. awvalid(input) : 等於1時，address可以拿 
    2. awready(output) : 去決定我們的address甚麼時候去做transfer
    3. wvalid(input) :  決定我們的data甚麼時候去做transfer
    4. wready(output) : 等於1時，data可以拿

![7b4a1323-1f58-4a13-8bec-424317828e0d](https://hackmd.io/_uploads/B1hNswfFa.jpg)


## **AXI4-Stream Protocol**
主要有3個控制訊號

    1. tvalid(input) : 等於1時，data可以拿
    2. tready(output) : 決定我們的data甚麼時候去做transfer
    3. tlast(input) : 最後一筆data已到達

![88a7f077-8f5d-481f-a533-95b8fc261685](https://hackmd.io/_uploads/rJ3IoDfYa.jpg)


## **Configuration Register Address map** 
  * Address [31:0]
     0x00 [0] **ap_start**: 初始化為1，但第一筆input stream data進來時，要設ap_start=0
     0x00 [1] **ap_done** : 初始化為0，最後一筆input進來(input tlast=1)，以及收到最後一筆output data時(output tlast=1)，ap_done設為1，且在下一個周期時設為0
     0x00 [2] **ap_idle**: 初始化為0，當收到ap_done等於1時，設為1
     所以0x00 [2:0] 的變化為 **001->000->010->100**
     0x10-14 : data-length
     0x20-FF : Tap parameters(ex:0x20-24 tap0, 0x25-29 tap1,以此類推)
    
## **Testbench運作**
*   AXI-lite
    一開始會先使用write通道，把tap的係數寫入
    ![image](https://hackmd.io/_uploads/SyDIh5mK6.png)
    接下來來到read部分，這裡選擇把tap的係數送進sdram
    ![image](https://hackmd.io/_uploads/S1P6hqQY6.png)
*   AXI-stream
    這裡可看出data最後一筆時，ap_done=1
    ![image](https://hackmd.io/_uploads/S1XWac7t6.png)
    
    
    
# **Lab4 Caravel SOC**
![image](https://hackmd.io/_uploads/SklT0q7Fa.png)
## **lab4-0 環境設定**
### **版本**
* Ubuntu 20.04+
* RISC-V GCC Toolchains rv32i-4.0.0
* Icarus Verilog v10.3
* Icarus Verilog v12 + GTKWave Windows (option)
* GTKWave v3.3.103
* vtags-3.11
* GDBWave
### **設定**
只要複製以下指令即可
```
sudo apt update
sudo apt install iverilog gtkwave vim python gcc git -y
sudo wget -O /tmp/riscv32-unknown-elf.gcc-12.1.0.tar.gz https://github.com/stnolting/riscv-gcc-prebuilt/releases/download/rv32i-4.0.0/riscv32-unknown-elf.gcc-12.1.0.tar.gz
sudo mkdir /opt/riscv
sudo tar -xzf /tmp/riscv32-unknown-elf.gcc-12.1.0.tar.gz -C /opt/riscv
sudo wget -O /tmp/vtags-3.11.tar.gz https://www.vim.org/scripts/download_script.php?src_id=28365
sudo tar -xzf /tmp/vtags-3.11.tar.gz -C /opt/python /opt/vtags-3.11/vim_glb_config.py
git clone https://github.com/bol-edu/caravel-soc ~/caravel-soc
cd ~/caravel-soc/python /opt/vtags-3.11/vtags.py
cd ~/ && rm -rf ~/caravel-soc/
echo 'export PATH=$PATH:/opt/riscv/bin' >> ~/.bashrc
echo 'alias vtags="python /opt/vtags-3.11/vtags.py"' >> ~/.bashrc
echo 'source /opt/vtags-3.11/vtags_vim_api.vim' >> ~/.vimrc
source ~/.bashrc
```
**Post simulation debugging**
```
sudo apt install make g++ zlib1g-dev gdb -y
git clone https://github.com/tomverbeure/gdbwave.git ~/gdbwave
pushd ~/gdbwave/src && make && popd
```

## **Lab4-1 exmem-fir**
了解WB跟RAM之間的相關操作，並且寫一個FIR的firmware去驗證WB是否有連接到RAM
*    **Firmware**
lab-exmem_fir/testbench/counter_la_fir.c
```c=63
  reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT;
  reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT;


  reg_mprj_io_15 = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_14 = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_13 = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_12 = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_11 = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_10 = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_9  = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_8  = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_7  = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_5  = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_4  = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_3  = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_2  = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_1  = GPIO_MODE_USER_STD_OUTPUT;
  reg_mprj_io_0  = GPIO_MODE_USER_STD_OUTPUT;

  reg_mprj_io_6  = GPIO_MODE_MGMT_STD_OUTPUT;
```
上述程式碼是在設定mprj io
```c=103
  reg_mprj_xfer = 1;
  while (reg_mprj_xfer == 1);
```
設定完，會讓reg_mprj_xfer = 1，並且firmware會等到io設定完，才會繼續
```c=
 reg_la0_oenb = reg_la0_iena = 0x00000000;    // [31:0]
 reg_la1_oenb = reg_la1_iena = 0xFFFFFFFF;    // [63:32]
 reg_la2_oenb = reg_la2_iena = 0x00000000;    // [95:64]
 reg_la3_oenb = reg_la3_iena = 0x00000000;    // [127:96]
 reg_la1_data = 0x00000000;
 reg_la1_oenb = reg_la1_iena = 0x00000000; 
```
以上是logic analyzer的相關設定，不過此次lab用不到LA，所以都設為初始值
```c=
 reg_mprj_datal = 0xAB400000;
 int* tmp = fir();
 reg_mprj_datal = *tmp << 16;
 reg_mprj_datal = *(tmp+1) << 16;
 reg_mprj_datal = *(tmp+2) << 16;
 reg_mprj_datal = *(tmp+3) << 16;
 reg_mprj_datal = *(tmp+4) << 16;
 reg_mprj_datal = *(tmp+5) << 16;
 reg_mprj_datal = *(tmp+6) << 16;
 reg_mprj_datal = *(tmp+7) << 16;
 reg_mprj_datal = *(tmp+8) << 16;
 reg_mprj_datal = *(tmp+9) << 16;
 reg_mprj_datal = *(tmp+10) << 16;
```
reg_mprj_datal是用來輸入到checkbit 去判斷說我們firmware給的值是否正確
其中AB41-AB51是起始跟終點
*    **Wishbone**
![089d7f76-8fe4-40c0-aebe-5d353be9272c](https://hackmd.io/_uploads/HJh0yRXtT.jpg)

WB有主要8個訊號

    1. wb_clk
    2. wbs_stb
    3. wbs_cyc
    4. wbs_we
    5. wbs_dat_i
    6. wbs_adr_i
    7. wbs_ack_o
    8. wbs_dat_o
  
 
(stb=1 && cyc=1)時，ADDR的值才有效
WE=0 -> READ 且 ACK=1時，wbs_dat_i的值才有效
WE=1 -> WRITE 只要滿足stb跟cyc的條件，wbs_dat_o的值就有效

在lab4-1中，wbs->ram的addr為0x3800

在makefile中
lab-exmem_fir/testbench/run_sim
* compile
```sh=3
riscv32-unknown-elf-gcc -Wl,--no-warn-rwx-segments -g \
	--save-temps \
	-Xlinker -Map=output.map \
	-I../../firmware \
	-march=rv32i -mabi=ilp32 -D__vexriscv__ -DUSER_PROJ_IRQ0_EN \
	-Wl,-Bstatic,-T,../../firmware/sections.lds,--strip-discarded \
	-ffreestanding -nostartfiles -o uart.elf ../../firmware/crt0_vex.S ../../firmware/isr.c uart.c counter_la_uart.c
```
其中可以發現這一行
```sh=7
-march=rv32i -mabi=ilp32 -D__vexriscv__ -DUSER_PROJ_IRQ0_EN \
```
這一行是用來設定UART IRQ的東西，在本LAB不會用到，但不影響
*    把.elf轉檔成.hex
```sh=11
riscv32-unknown-elf-objcopy -O verilog uart.elf uart.hex
```
*    匯出組合語言去做debugging
```sh=12
riscv32-unknown-elf-objdump -D uart.elf > uart.out
```

## **Lab4-2 WB+RAM+FIR**
![534cc408-3044-46ba-97f6-b711631142d6](https://hackmd.io/_uploads/HkTmr0XFp.jpg)
此次LAB根據LAB4-1的情況下，再把FIR給接起來
其中:ADDR=0X3000 -> FIR，ADDR=0X3800 -> BRAM

# **Final Project**
*    **Block Diagram**
![image](https://hackmd.io/_uploads/ry2bB7BK6.png)
