---
# System prepended metadata

title: Unet_Wrapper
tags: [CAIDLAB]

---

# Unet
:::info
## SPEC
[UnetWrapper_Code](https://github.com/yuchengwang1121/Unet)
![](https://hackmd.io/_uploads/HkXzPuKy6.png)
### Input Spec : 8-bit, 3 channel, 85,000 X 200,000 pixels
### Patch Spec : 128*128 patch (50% overlap)
### Output Spec : 8-bit, 128*128 patch p1, m0, mc
  * p1 : Output of UNET, Probability of droplet boundary
  * m0 : p0 >= 0.5, mask of droplet region
  * mc : (p0-p1) >= 0.5, mask of separated droplet region

![](https://hackmd.io/_uploads/Syez9dtka.png)

:::

## Q&A
### Questions
* How to use the Flash read and write control signal line (Please give us a read and write example and wave file for observation)
* If we want to connect the external circuit, What kind of connection is recommended?
* MEMORY_INITIALIZATION_RADIX表示數據進制類型
* MEMORY_INITIALIZATION_VECTOR表示要儲存的數據
* Toggle DDR接口控制器將內部信號轉換為外部物理NAND引腳。
* What is the sub-module in Flash Channel Controller doing?(Data path ,Control Path, Command Dispatcher and Toggle DDR interface Controller) Is there a more detailed document that we can read and use it?
* When Flash Channel Controller reads data, how to input addr to get data? Will the output be a burst or a page?
* Why the size of DataPath and Control Path from Flash Channel Controller is 32*4 ?

### Answer
* 寫操作 - iladata_program.ila
* 讀操作 - iladata_page_read.ila/iladata_random_data_out.ila，讀取指令的輸出是一個頁面。讀操作包含兩個階段，頁讀取 / 隨機數據輸出。由於從NAND頁面將數據移動到頁緩衝區需要一些時間，因此在等待數據移動完成期間，軟體可以執行其他操作。
* 如果要連接外部電路，請將新的指令添加到ROM代碼(uProgROM_v2.0.coe)並修改指令調度程序。
* 指令在ROM代碼中定義 - cosm-plus-sys\cosm-plus-sys.sdk\run-gftl3\src\t4nsc_ucode.h。
* 據我所知，目前沒有關於NAND控制器的詳細設計文檔。
* 數據路徑和控制路徑的大小為32*4，因為通道控制器有4個通道。每個通道都有單獨的數據路徑和控制路徑。
* 數據路徑是64位匯流排，通過DMA接口傳輸頁數據。控制路徑是32位匯流排，用於傳輸指令。
* 當控制器讀取數據時，地址信息通過DQ[7:0]傳輸5個時鐘週期。當ALE為高電平且WE為下降沿時，地址被讀取。請查看ila文件iladata_page_read.ila。
* 請查收附上的讀寫控制信號線波形圖。Vivado通過「文件」->「導入」->「導入ILA數據」菜單顯示波形圖從ila文件中導入。
* 軟體通知指令調度程序特定NAND操作的ROM代碼的起始索引。指令調度程序解釋ROM代碼並執行NAND操作。

## Waveform
### ILA waveform
```ila=
close_hw
//Report ERROr for initialize
read_hw_ila_data C:/Users/WangYuCheng/Desktop/UNET/iladata_program.ila 
open_hw
//read_hw_ila_data .ila position
read_hw_ila_data C:/Users/WangYuCheng/Desktop/UNET/iladata_program.ila
display_hw_ila_data
```
### Write Data
* **sys_top.v**
  * **sys_top_v2nfc_x_x t4nfc_(0~7)**
    * **NFC_Toggle_Top_DDR100**
      * **Nphy_Toggle_Top_DDR100**
        * **NPhy_Toggle_Physical_Output_DDR100**
          * **OSERDESE2 (Output Parallel-to-Serial Logic Resources)**
            * *[2:0]  iPOReadEnable*
            * *[2:0]  iPOWriteEnable*
            * *[31:0] iPODQ*
            * *[3:0]  iPODQStrobe*
    * wire (connect **NPM_Toggle_Top_DDR100** & **NPhy_Toggle_Top_DDR100**)
      * *[7:0]  wPOChipEnablePMPHY*
      * *wPOAddressLatchEnablePMPHY*
      * *wPOCommandLatchEnablePMPHY*

## Related Module
### OSERDESE2
![](https://hackmd.io/_uploads/Hysm5_2_2.png =x500)
#### Ports
* CLK, CLKDIV : Serial & parallel CLK
* RST         : reset
* D1 ~ D8     : Parallel data input port
* OCE         : HIGH active CLK Enable signal
* OFB         : Output feedback port
* OQ          : Serial data output
* TBYTEIN     : Byte group 3-state input
* TBYTEOUT    : Byte group 3-state output
* TCE         : HIGH active 3-state CLK Enable signal
* TFB         : Output feedback port
* TQ          : 3-state Ctrl module Output
* T1 ~ T4     : 3-state Ctrl module Input
* SHIFTIN1/SHIFTIN2   : Carry output for data width expansion.
* SHIFTOUT1/SHIFTOUT2 : Carry input for data width expansion
#### Parameter
![](https://hackmd.io/_uploads/Sy3ZbjpOn.png =x350)
* DATA_RATE_OQ : 控制數據是以DDR或是以SDR作為輸出
* DATA_RATE_TQ : 3-state控制是以DDR或是以SDR作為輸出
* DATA_WIDTH   : data的bit寬
* INIT_OQ      : 輸出數據的初始化值
* INIT_TQ      : 3-state控制輸出數據的初始化值
* SERDES_MODE  : 主從模式
* SRVAL_OQ     : 當SR使用時，OQ的輸出值
* SRVAL_TQ     : 當SR使用時，TQ的輸出值
* TBYTE_CTL    : 用於DDR3，3-state的字符操作使能
* TBYTE_SRC    : 用於DDR3，3-state的字符源使能
* TRISTATE_WIDTH : 3-state的bit寬
  ```verilog=
    OSERDESE2#
    (
        .DATA_RATE_OQ   ("DDR"      ),    //DDR, SDR
        .DATA_RATE_TQ   ("BUF"      ),    //DDR, BUF, SDR
        .DATA_WIDTH     (4          ),    //Parallel data width(2-8, 10,14)
        .INIT_OQ        (1'b0       ),    //1'b0, 1'b1
        .INIT_TQ        (1'b0       ),    //1'b0, 1'b1
        .SERDES_MODE    ("MASTER"   ),    //MASTER, SLAVE
        .SRVAL_OQ       (1'b0       ),	  //1'b0, 1'b1
        .SRVAL_TQ       (1'b0       ),	  //1'b0, 1'b1
        .TRISTATE_WIDTH (1          )     //3-state converter width(1, 4)
    )
  ```
* **[More detail at p.161](https://docs.xilinx.com/v/u/en-US/ug471_7Series_SelectIO)**

#### Run simulation
* Use vivado -> Language Template -> Search"OSERDESE2"
* Code for OSERDESE2
:::spoiler
```verilog=
//////////////////////////////////////////////////////////////////////////////////
// Engineer:    YuChengWang
// Create Date: 2023/07/01 23:11:10
// Design Name: Test_of_OSERDESE2_write_function
// Module Name: OSERDESE2_write
// Revision 0.01 - File Created
//////////////////////////////////////////////////////////////////////////////////


module OSERDESE2_write(
    input clk_serial,
    input clk_parallel,
    input rst_n,
    input [3:0] par_data,
    output ser_data
    );
    
    OSERDESE2 #(
          .DATA_RATE_OQ("DDR"),   // DDR, SDR
          .DATA_RATE_TQ("BUF"),   // DDR, BUF, SDR
          .DATA_WIDTH(4),         // Parallel data width (2-8,10,14)
          .INIT_OQ(1'b0),         // Initial value of OQ output (1'b0,1'b1)
          .INIT_TQ(1'b0),         // Initial value of TQ output (1'b0,1'b1)
          .SERDES_MODE("MASTER"), // MASTER, SLAVE
          .SRVAL_OQ(1'b0),        // OQ output value when SR is used (1'b0,1'b1)
          .SRVAL_TQ(1'b0),        // TQ output value when SR is used (1'b0,1'b1)
//          .TBYTE_CTL("FALSE"),    // Enable tristate byte operation (FALSE, TRUE)
//          .TBYTE_SRC("FALSE"),    // Tristate byte source (FALSE, TRUE)
          .TRISTATE_WIDTH(1)      // 3-state converter width (1,4)
       )
       OSERDESE2_inst (
          .OFB(),             // 1-bit output: Feedback path for data
          .OQ(ser_data),               // 1-bit output: Data path output
          // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
          .SHIFTOUT1(),
          .SHIFTOUT2(),
          .TBYTEOUT(),   // 1-bit output: Byte group tristate
          .TFB(),             // 1-bit output: 3-state control
          .TQ(),               // 1-bit output: 3-state control
          .CLK(clk_serial),             // 1-bit input: High speed clock
          .CLKDIV(clk_parallel),       // 1-bit input: Divided clock
          // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
          .D1(par_data[0]),
          .D2(par_data[1]),
          .D3(par_data[2]),
          .D4(par_data[3]),
          .D5(),
          .D6(),
          .D7(),
          .D8(),
          .OCE(1'b1),             // 1-bit input: Output data clock enable
          .RST(~rst_n),             // 1-bit input: Reset
          // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
          .SHIFTIN1(),
          .SHIFTIN2(),
          // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
          .T1(1'b0),
          .T2(1'b0),
          .T3(1'b0),
          .T4(1'b0),
          .TBYTEIN(1'b0),     // 1-bit input: Byte group tristate
          .TCE(1'b0)              // 1-bit input: 3-state clock enable
       );
endmodule
```
:::

* Code for OSERDESE2_tb
:::spoiler
```verilog=
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer:    YuChengWang
// Create Date: 2023/07/01 23:11:10
// Design Name: Test_of_OSERDESE2_write_function
// Module Name: OSERDESE2_write
// Revision 0.01 - File Created
//////////////////////////////////////////////////////////////////////////////////
module OSERDESE2_write_tb( );
reg  clk_serial;
reg  clk_parallel;
reg  rst_n;
reg [3:0] par_data;
wire ser_data;

initial begin
    clk_serial <= 1'b1;
    clk_parallel <= 1'b0;
    rst_n <= 1'b0;
    par_data <= 4'b0;
    #180
    rst_n <= 1'b1;
end

// set clk DATA_WIDTH=4, 2 Cycle
always #5 clk_parallel = ~clk_parallel;
always #2.5 clk_serial = ~clk_serial;

//input data
always #10 par_data <= $random%16;

OSERDESE2_write OSERDESE2_write_inst(
    .clk_parallel (clk_parallel),
    .clk_serial   (clk_serial),
    .rst_n        (rst_n),
    .par_data     (par_data),
    
    .ser_data     (ser_data)
);
endmodule
```
:::


### Waveform
![](https://hackmd.io/_uploads/BytRlGxtn.png)
* 第一個藍 : par給0101，並於下個clk_serial延遲後(第二藍處)，將值透過ser_data由低至高輸出

## Patch Size Compare
* 使用$128*128$才可pipeline實作各layer，否則$256*256$只能一次做一個patch
![](https://hackmd.io/_uploads/SymSUOKyT.png)

## Implement on Vivado - BRAM for Base_Addr
* Interface: 要在in/out put 的地方新增以下指令即可透過vivado之內建interface做包線
  ![](https://hackmd.io/_uploads/HJVHZzOea.png =x300) ![](https://hackmd.io/_uploads/Bke9qf2yp.png =x150)

  ```verilog=
  //(* X_INTERFACE_INFO = "<interface vinv> <interface_name> <logical_port_name>" *)
  //Example
  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 M_AXI ARADDR" *)
  output [31:0]Unet_M00_AXI_araddr,
  ```
  

### Rtl 模擬結果
* Unet_Wrapper+Bram之結果
  * 接法 
    ![](https://hackmd.io/_uploads/HyrkiNT-a.png)
  * Address Editor(PS以及Unet_Wrapper)
    ![](https://hackmd.io/_uploads/HkmWjN6-p.png)
    ![](https://hackmd.io/_uploads/BJOfjN6ba.png)
  * 成功放置位置0x4580_0000
    ![](https://hackmd.io/_uploads/BkjqklBGa.png)
  * [Bram Controller diagram](https://docs.xilinx.com/v/u/en-US/pg078-axi-bram-ctrl)
    ![](https://hackmd.io/_uploads/H1OzVxSGp.png)

### Synthesize 模擬結果
* 報錯
  ![](https://hackmd.io/_uploads/SyGK__Tk6.png)
* [解決辦法](https://blog.csdn.net/qq_44692266/article/details/114538905)

### Implement 模擬結果
* 報錯1 [解決辦法](https://blog.csdn.net/qq_42025108/article/details/124693736)
    ![](https://hackmd.io/_uploads/SyWv7jTkT.png)
* 報錯2 [解決辦法](https://blog.csdn.net/qq_38376586/article/details/121994755)
  ![](https://hackmd.io/_uploads/HkYLow_e6.png)

### 成功畫面
![](https://hackmd.io/_uploads/SyGOIq8Gp.png)

## 問題
### Framwork端無法寫入Bram
* Single-port : 只能一時刻寫，一時刻讀
* Simple Dual-port : 一端寫，一端讀
  ![image](https://hackmd.io/_uploads/HJfLlahmp.png =x200) ![image](https://hackmd.io/_uploads/Sy5UlpnQp.png =x200)
:::info
### 嘗試將Bram改SDport看看 [參考](https://zhuanlan.zhihu.com/p/208375629)
![image](https://hackmd.io/_uploads/SJW2NahX6.png)

:::

### 驗證是否能從BRAM正確取值 - PYNQ
* 合成完以後點選【Set Up Debug】，並添加addrb、doutb和enb。分別讀出BRAM PORTB 地址、讀出數據以及始能
  * 可以在net schematic時對感興趣線按右鍵選【Mark Debug】，之後再set up debug就不用慢慢拉
  ![image](https://hackmd.io/_uploads/SJFEfWIET.png =x300)
* 接著設置採樣深度，越深採集到的數據越多
  ![image](https://hackmd.io/_uploads/rJ70MZLN6.png =x300)
* 模擬結果
  ![image](https://hackmd.io/_uploads/Bkn2IOiB6.png)

## Implement on Vivado - FLASH for Input_data


## bb
 ![image](https://hackmd.io/_uploads/SkRU3LO86.png)
![image](https://hackmd.io/_uploads/BkVwx17Pa.png)
