# Unet
:::info
## SPEC
[UnetWrapper_Code](https://github.com/yuchengwang1121/Unet)

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

:::
## 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

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

* 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

* 第一個藍 : par給0101,並於下個clk_serial延遲後(第二藍處),將值透過ser_data由低至高輸出
## Patch Size Compare
* 使用$128*128$才可pipeline實作各layer,否則$256*256$只能一次做一個patch

## Implement on Vivado - BRAM for Base_Addr
* Interface: 要在in/out put 的地方新增以下指令即可透過vivado之內建interface做包線
 
```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之結果
* 接法

* Address Editor(PS以及Unet_Wrapper)


* 成功放置位置0x4580_0000

* [Bram Controller diagram](https://docs.xilinx.com/v/u/en-US/pg078-axi-bram-ctrl)

### Synthesize 模擬結果
* 報錯

* [解決辦法](https://blog.csdn.net/qq_44692266/article/details/114538905)
### Implement 模擬結果
* 報錯1 [解決辦法](https://blog.csdn.net/qq_42025108/article/details/124693736)

* 報錯2 [解決辦法](https://blog.csdn.net/qq_38376586/article/details/121994755)

### 成功畫面

## 問題
### Framwork端無法寫入Bram
* Single-port : 只能一時刻寫,一時刻讀
* Simple Dual-port : 一端寫,一端讀
 
:::info
### 嘗試將Bram改SDport看看 [參考](https://zhuanlan.zhihu.com/p/208375629)

:::
### 驗證是否能從BRAM正確取值 - PYNQ
* 合成完以後點選【Set Up Debug】,並添加addrb、doutb和enb。分別讀出BRAM PORTB 地址、讀出數據以及始能
* 可以在net schematic時對感興趣線按右鍵選【Mark Debug】,之後再set up debug就不用慢慢拉

* 接著設置採樣深度,越深採集到的數據越多

* 模擬結果

## Implement on Vivado - FLASH for Input_data
## bb

