# Looping Statement: ###### tags: `Digital IC Design` [回到主頁面](https://hackmd.io/@derek8955/BkK2Nb5Jo/https%3A%2F%2Fhackmd.io%2FdpcBlBL8TlShpQ-wSi9Quw) 在 verilog 中,有四種 looping statement: forever 、 repeat 、 while 、 for - 前三種語法只使用於 testbench - 以下只介紹 for loop ### <font color = "blue"> Array in verilog </font> 在介紹 for loop 之前先說明一下 verilog 的 array 怎麼定義 ::: success Vector ```verilog= reg [7:0] a; // 8 bit 的 data initial begin a = 8'b0000_0010; // 下底線沒有意義,只是方便檢視 $display("%b, %b", a[1], a[0]); // result: 1, 0 end // 可以透過這樣的方式去 index 一維的 value // 這邊你可能會有個疑問,為什麼資料寬度的定義是由大到小 // 如果現在定義 [7:0] 代表最左邊的bit是 MSB,最右邊是 LSB; // 反之若定義成 [0:7] 代表最右邊的bit是 MSB,最左邊是 LSB。見下圖 reg [0:7] a; // assume a = 8'b0000_0010; initial $display("%b, %b", a[1], a[0]); // result: 0, 0 ``` ![](https://i.imgur.com/SAFTJ0i.png) ::: :::info array ```verilog= reg [3:0] memory[0:4]; // 前面的 [3:0] 意旨 4 bit的資料寬度,後面的 [0:4] 意旨資料的深度,如下圖 initial begin memory[0] = 12; memory[1] = 16;// 因為資料寬度是 4bit,最大只能存放15,超過則 overflow memory[2] = 7; memory[3] = 3; memory[4] = 9; $display("%d",memory[0]); // 12 $displayb(memory[0]); // 1100 $displayb(memory[0][3]); // result : 1,第0個 block 中第3個 bit 的 value end ``` ![](https://i.imgur.com/LnP1ZZE.png) ::: ### <font color = "blue"> For loop </font> ```verilog= // 簡單的 shift register,電路在下方 module LOOP( clk, rst_n, data_in ); input clk, rst_n; input [3:0] data_in; integer i; // 使用 for loop 則必須宣告 integer 這個 data type // integer 後面不須設定資料寬度,default則是 32 bit reg [3:0] memory[0:4]; always@( posedge clk or negedge rst_n ) begin if( !rst_n ) begin for( i=0 ; i<5 ; i=i+1 ) memory[i] <= 0; end else begin memory[0] <= data_in; for( i=0 ; i<4 ; i=i+1 ) memory[i+1] <= memory[i]; // 在 verilog 中, for loop 只是 copy 相同功能的電路,所以第16行的功能相當於第18行到第21行 memory[1] <= memory[0]; memory[2] <= memory[1]; memory[3] <= memory[2]; memory[4] <= memory[3]; end end endmodule ``` |![](https://i.imgur.com/w99e20y.png)| |:---:| |Shift register| |Ref: https://zh.wikipedia.org/zh-tw/%E7%A7%BB%E4%BD%8D%E5%AF%84%E5%AD%98%E5%99%A8| ### <font color = "blue"> Apendix : Shift Regsiter vs. Counter</font> Shift Regsiter 跟 Counter 都可拿來存放 input data ```verilog= // Shift Regsiter always @( posedge clk or negedge rst_n ) begin if( !rst_n ) begin for( i=0; i<4 ; i=i+1 ) mem[i] <= 0; end else if( in_valid ) begin // input valid mem[0] <= data_in; for( i=0; i<3 ; i=i+1 ) mem[i+1] <=mem[i]; end end // counter always @( posedge clk or negedge rst_n ) begin if( !rst_n ) cnt <= 0; else if( in_valid ) cnt <= cnt + 1; end always @( posedge clk or negedge rst_n ) begin if( !rst_n ) begin for( i=0; i<4 ; i=i+1 ) mem[i] <= 0; end else if( in_valid ) mem[cnt] <= data_in; end ``` 但 counter 合成出的電路會多了 MUX,因此利用 shift register 面積會比較小 |![](https://i.imgur.com/O6u1a2G.png)| |:---:| | Counter with MUX |