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

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

:::
### <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
```
||
|:---:|
|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 面積會比較小
||
|:---:|
| Counter with MUX |