今天要來跟大家分享的是for loop這個語法,大家一定都知道這語法,但在verilog的使用上會跟一般在C的使用方式會有大大的不同,所以使用前一定要瞭解他的規則並小心使用.
舉例來說:
Verilog:
reg[31:0]matrix[8:0];
always@(posedge clk)begin
if(reset)
for(idx=0; idx <9; idx = idx +1)begin
matrix[idx] <= 0;
end
end
C code:
int matrix[9];
for(idx=0;idx<9;idx++){
matrix[idx] = 0;
}
兩者看起來好像都是對matrix做歸零的動作,但是以行為上來說是不相同的,以C code來說,它是一個一個對matrix裡的元素做歸零,時間上來說,以上面這例子要花9個單位時間做完這個歸零的動作,而verilog是說,每當你的時脈(clock)正緣觸發時,會更新完always block裡面所要求的動作,以上面例子來說呢,就是當時脈正緣觸發時,就會把matrix裡面的所有元素做歸零的動作
等同於:
always@(posedge clk)begin
matrix[0] <= 0;
matrix[1] <= 0;
matrix[2] <= 0;
matrix[3] <= 0;
matrix[4] <= 0;
matrix[5] <= 0;
matrix[6] <= 0;
matrix[7] <= 0;
matrix[8] <= 0;
matrix[9] <= 0;
end
用一個波形圖給大家看看,當reset訊號等於1且clock正緣觸發時,matrix裡面的每一個元素都會做歸零。
這樣看起來的話,當你在verilog使用for loop時,他會把你的for做展開的動作,並每次時脈正緣觸發時去做always block所要求的動作,所以如果要做像是迭代的運算的話在verilog就不能用for loop實現,舉例來說:假設你要累加一個值十次好了,如果你寫成:
reg [7:0]temp;
always@(posedge clk)begin
for(idx=0;idx<10;idx=idx+1)begin
temp <= temp+idx;
end
end
把這種想法寫成電路的話,照剛剛的說法把for展開並在時脈正緣觸發時做動作,意思就會像下面這樣.
always@(posedge clk)begin
temp <= temp+0;
temp <= temp+1;
temp <= temp+2;
temp <= temp+3;
.
.
.
temp <= temp+9;
end
這樣應該跟我們當初想要的行為不一樣,所以在verilog來說,如果你要做像是累加這種運算,或者是重複的動作要做數次,可以利用counter來計數,像是剛剛累加10次的例子,我們利用counter來重寫一次看看:
reg[3:0]counter;
always@(posedge clk)begin
if(reset)
counter <= 0;
else
counter <= (counter == 10) ? counter : counter + 1;
end
always@(posedge clk)begin
if(reset)
temp <= 0;
else if(counter<10)
temp <= temp + counter;
end
下面用一個波形示意圖給大家看,
上圖顯示reset完開始做累加,達到原先我們要的要求。
所以如果需要在verilog 使用for loop的話,請先思考一下是否你寫出來的for是符合你的要求,試著把for展開看看,看一下展開後的行為是不是你要的,如果只是想要用for去迭代做運算或者是其他迭代的行為,那在verilog這邊推薦大家使用counter的方式去代替,最後面的應用電路主題當中如果有用到的話,會再提醒大家,那今天就先到這裡囉.