# **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)