Verilog语言的编写
for(i=1;i<15;i++)
{
for(j=1;j<15;j++)
{
avg=0;
temp=0;
for(k=-1;k<=1;k++)
{
for(l=-1;l<=1;l++)
{
avg+=(double)pd[i+k][j+l];
}
}
avg=avg/((double)sn*sn);
for(k=-1;k<=1;k++)
{
for(l=-1;l<=1;l++)
{
temp+=((double)pd[i+k][j+l]-avg)*((double)pd[i+k][j+l]-avg);
}
}
各位高手提点意见或者帮忙写一下。谢谢。
在可综合的verilog中,RTL设计一般不推荐用for语句,一般用在testbench中。
可以用if...else...语句去替换
理解代码的功能才是最重要的,你应看到的是累加或者求均值或者求方差,而不是多重循环。然后再把同样的逻辑转换到verilog。
只是简单的for语句由于其在部分情况下是不可综合的,所以没人会推荐在综合代码中使用for的。
具体的软件循环的硬件化,应该分析代码的真正意图,了解其要完成的功能,然后使用“在某根控制信号有效时,连续工作,否则停止”类型的电路来实现。
代码的意思我懂,就是不知道该如何去转换,无从下手啊。
for循环,如果循环范围是常量,可综合。数组可综合。
但浮点类型不可综合。乘除法,特别是除法一般也不推荐使用,即使可综合,逻辑级数也是非常大的。
如果把上面的代码放在一拍之内完成,恐怕得到频率会非常低。
- module loop(clk);
- input clk;
-
- integer i, j, k, l;
- integer avg, temp;
- reg loop1_en, loop2_en, loop3_en;
-
- initial
- begin
- i = 1;
- j = 1;
- k = -1;
- l = -1;
- avg = 0;
- temp = 0;
- loop1_en = 0;
- loop2_en = 0;
- loop3_en = 1;
- end
- task task1;
- if (k <= 1)
- begin
- if (l <= 1)
- begin
- avg = avg + 1;
- l = l + 1;
- end
- else
- begin
- k = k + 1;
- l = -1;
- end
- end
- else
- begin
- loop1_en = 0;
- loop2_en = 1;
- k = -1;
- l = -1;
- avg = avg >> 2;
- $display("%d", avg);
- end
- endtask
- task task2;
- if (k <= 1)
- begin
- if (l <= 1)
- begin
- temp = temp + avg;
- l = l + 1;
- end
- else
- begin
- k = k + 1;
- l = -1;
- end
- end
- else
- begin
- k = -1;
- l = -1;
- loop2_en = 0;
- loop3_en = 1;
- $display("%d", temp);
- avg = 0;
- temp = 0;
- end
- endtask
- task task3;
- if (i < 3)
- begin
- if (j < 3)
- begin
- j = j + 1;
- loop3_en = 0;
- loop1_en = 1;
- end
- else
- begin
- $display("biggest loop");
- i = i + 1;
- j = 1;
- end
- end
- else
- begin
- loop1_en = 0;
- //$display ("finished");
- end
- endtask
- always @ (posedge clk)
- begin
- if (loop1_en)
- begin
- task1;
- end
- else if (loop2_en)
- begin
- task2;
- end
- else if (loop3_en)
- begin
- task3;
- end
- else
- begin
- $display("invalid case");
- end
- end
-
- endmodule
if else 代码来了,跑过tb,循环跑起来是对的。
軟體與硬體的思考邏輯不同..
所以建議先把演算法用硬體的方式思考一遍
再用RTL寫出...
這樣會比較好
这是仿真用的代码啊
怎么看输出的数据temp啊
学习了软件语言里的for循环转成硬件语言
用计数器写
能具体说一下怎么写吗?谢谢
RE: [verilog] Verilog语言的编写
- for(i=0;i<14;i++){
- for(j=0;j<14;j++){
- avg = 0 ;
- temp = 0 ;
- for(k=0;k<=2;k++){
- for(l=0;l<=2;l++){
- avg = avg + (double)pd[i+k][j+l];
- // ###############
- // 4 counter
- // ###############
- //
- //
- // 1st counter cnt_dff_l = (cnt_dff_l==l_max) ? 0 : cnt_dff_l + 1 ;
- //
- // 2nd counter cnt_dff_k = (cnt_dff_l==l_max) && (cnt_dff_k==k_max) ? 0 :
- // (cnt_dff_l==l_max) ? cnt_dff_k + 1 :
- // cnt_dff_k ;
- //
- // 3rd counter cnt_dff_j = (cnt_dff_l==l_max) && (cnt_dff_k==k_max) && (cnt_dff_j==j_max) ? 0 :
- // (cnt_dff_l==l_max) && (cnt_dff_k==k_max) ? cnt_dff_j + 1 :
- // cnt_dff_j ;
- //
- // 4th counter cnt_dff_i = (cnt_dff_l==l_max) && (cnt_dff_k==k_max) && (cnt_dff_j==j_max) && (cnt_dff_i==i_max) ? 0 :
- // (cnt_dff_l==l_max) && (cnt_dff_k==k_max) && (cnt_dff_j==j_max) ? cnt_dff_i + 1 :
- // cnt_dff_i ;
- // ###############
- // avg_latch
- // ###############
- //
- // addr1 = cnt_dff_i + cnt_dff_k ;
- // addr2 = cnt_dff_j + cnt_dff_l ;
- // avg_tmp = avg_dff + pd[addr1][addr2] ;
- //
- // avg_latch = (cnt_dff_l==l_max) && (cnt_dff_k==k_max) && (cnt_dff_j==j_max) && (cnt_dff_i==i_max) ? avg_tmp : avg_latch ;
- }
- }
-
- avg = avg / ((double)sn*sn);
-
- // ###############
- // avg_div
- // ###############
- //
- // avg_div = avg_latch / (sn*sn)
- for(k=-1;k<=1;k++){
- for(l=-1;l<=1;l++){
- temp = temp + ((double)pd[i+k][j+l] -avg) * ((double)pd[i+k][j+l] -avg);
- }
- }
-
- // ###############
- // temp_latch
- // ###############
- // temp_tmp = temp_dff + (pd[addr1][addr2] - avg_div) * (pd[addr1][addr2] - avg_div) ;
- //
- // temp_latch = (cnt_dff_l==l_max) && (cnt_dff_k==k_max) && (cnt_dff_j==j_max) && (cnt_dff_i==i_max) ? temp_tmp : temp_latch ;
- }
- }
寫個概念,需自行改寫成正統 Verilog 語法。
1. 需要用 clock DFF 存取資料,造計數器,取pd資料位置,待所有 Sum完成,才能做除法運算
2. temp 運算結果會慢 avg_div 整整一個 counter 循環
3. 以上概念可進行電路合成
看不懂 路过
首先谢谢你,我还有一个问题就是 avg+=(double)pd[i+k][j+l];这个语句你是怎么给写的。
其实我只是告诉你怎么将for循环转换成verilog,为方便起见, 里面用的整数运算。
你说的那个表达式,具体是什么不会写呢? 双精度的转换和运算需要你的平台支持FPU。 其它应该都不是什么问题吧?
就是那各pd[][]这个存储器该怎么去写。谢谢。
pd[][]是二维数组, 假定每个数组元素的数据宽度为8位, 你可以这么定义reg [7:0]pd[15:0][15:0];
然后在initial块里面逐个给赋初始值,如pd[0][0]=8'bxxx; pd[0][1]=8'bxxx ... ....
也可以先将初始值放到数据文件中,然后调用系统函数$readmemb/reamdmemh(...)一下全部赋给pd数组。
谢谢
对于这样的表达式avg=avg+pd[i+k][j+l]就这样直接在程序中写出来,还是需要变换啊。
应该可以的,具体你试试就知道了啊
有点看不明白,你这个逻辑是不是跟我的C语言有点不一样啊。
对于这样的表达式avg=avg+pd[i+k][j+l]就这样直接在程序中写出来,还是需要变换啊。
應該先請教您一個問題1. 這段 C 語言是要轉換成 "Testbench 使用 " 的 Verilog (不可 synthesis) ?
2. 或是 C 語言是要轉換成 "實際硬體電路 " 的 Verilog (可作 synthesis) ?
若是寫測試用的 Testbench (不可 synthesis),參考 8樓樓主。
若是要轉換成 "實際硬體電路" 的 Verilog,思考方式會與軟體 C 語言不同。
我的寫法是以硬體可作 synthesis 來思考的。
我寫的方式是 "可作 synthesis " 的思考邏輯來寫的。
若只是要寫 Testbench ,寫法就隨意了。
但提出這問題解答需先了解,您這個C語言演算法轉換成 Verilog 的目的是甚麼 ?
若要轉成 "可作 synthesis" 的電路,
用 C 語言的思考邏輯來寫會出問題。
谢谢!我要写的是可综合的Verilog语言,可是你给我的那个看的不是太懂,能详细一点吗?非常感谢!
剛剛看了版大您問的另一個 Verilog 問題,
發現您對於硬體電路的思考有需要調整的觀念:
Verilog 是硬體語言,簡單區分以下兩種電路
1. 組合邏輯 Combination Logic (無記憶性電路,輸入是甚麼資料輸出是甚麼資料)
2. 循序邏輯 Sequential Logic (有記憶性電路 ex : 有限狀態機 FSM,計數器,累加器 ...)
你必須先有以上觀念,才能思考可作 Synthesis 的電路要如何撰寫。
先最小化今天的問題,拆解運算動作。
假設 i = 1 ; j = 1;
for(k=-1;k<=1;k++){
for(l=-1;l<=1;l++){
avg+=(double)pd[i+k][j+l];
}
}
上述的兩個迴圈運算做了哪些事情,誰先誰後。迴圈拆解如下
為什麼要拆解,因為硬體語言是在寫電路。
寫電路是需要思考你的電路運算到底需要多少面積和硬體來實現。
硬體電路必須在寫之前就先決定好,你到底要運算的資料有多少,
它不是 C 語言,你隨時要改架構,丟個參數進去就能作不同數量的計算。
avg_sum1 = (double) { pd[0][0] + pd[0][1] + pd[0][2] }
avg_sum2 = (double) { pd[1][0] + pd[1][1] + pd[1][2] }
avg_sum3 = (double) { pd[2][0] + pd[2][1] + pd[2][2] }
avg_sum = avg_sum1 + avg_sum2 + avg_sum3 ;
上有8個加法計算,要用多少硬體來實現加法運算要看設計者來決定
假設我硬體面積足夠,我就直接用8個運算,若面積不夠我只要用少些加法器運算,
就要考慮到資料存取的問題。
解法 a. avg_sum = pd[0][0] + pd[0][1] + ... + pd[2][2] ; 組合邏輯 Combination Logic
解法 b. 1個運算加法器,1個 DFF 存資料 ;
循序邏輯 Sequential Logic
avg_sum 是資料存取的 DFF
pd_k = pd[m][n] | m=0~2 n=0~2
avg_sum_next = avg_sum + pd_n;
假設我只用1個加法器要實現它,我必須要確認幾件事情:
(0) 我利用8個 Clock 來運算它
(1) 每個 clock 需存取計算後的資料 avg_sum = avg_sum_next
(2) 在初始,或計算完全部的資料後, avg_sum 歸零
(3) 每次運算的 pd_k 在不同時間要選取不同的運算資料來源,在avg_sum 歸零後,pd_k 從頭選取運算資料,週而復始。
拆解完以上動作再思考,怎麼實現電路,才能在只用1個運算家法器的硬體面積限制下,完成目標。
上述的運算在只用1個加法器的條件下,就要運用到 counter 計數器,才能實現。
計數器用來作 pd_k 資料的選取條件,以及 avg_sum 歸零的動作
以上是單純對於兩個迴圈拆解的內容,
也提供兩種方法去解這個問題,當然也有很多方法,
看你的硬體面積限制決定你要怎麼做,
確認這些都搞懂了,再去想如何拆解你的演算法
否則我現在寫一堆,你仍會無法理解硬體的思考方式。
提醒:
如果今天是要撰寫 "可作 synthesis 電路"
1. 請務必先了解你自己的演算法在做的運算到底該怎麼拆解。
2. 完整拆解完之後,到底要用多少電路來完成
3. For 迴圈是不能自動轉換成累加電路,請不要再誤用 For 迴圈來實現累加運算的電路了,是非常錯誤的觀念。
For 用在"可作 synthesis 電路" 只有平行架構 (電路獨立,迴圈運算無相依性) 才能使用
