微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > Verilog语言的编写

Verilog语言的编写

时间:10-02 整理:3721RD 点击:
C语言中的多重for循环该怎么去写啊。

    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循环,如果循环范围是常量,可综合。数组可综合。
但浮点类型不可综合。乘除法,特别是除法一般也不推荐使用,即使可综合,逻辑级数也是非常大的。
如果把上面的代码放在一拍之内完成,恐怕得到频率会非常低。

  1. module loop(clk);
  2.         input clk;
  3.        
  4.         integer i, j, k, l;
  5.         integer avg, temp;
  6.         reg loop1_en, loop2_en, loop3_en;
  7.        
  8.         initial
  9.                 begin
  10.                         i = 1;
  11.                         j = 1;
  12.                         k = -1;
  13.                         l = -1;
  14.                         avg = 0;
  15.                         temp = 0;
  16.                         loop1_en = 0;
  17.                         loop2_en = 0;
  18.                         loop3_en = 1;
  19.                 end

  20. task task1;
  21.         if (k <= 1)
  22.                 begin
  23.                         if (l <= 1)
  24.                                 begin
  25.                                         avg = avg + 1;
  26.                                         l = l + 1;
  27.                                 end
  28.                         else
  29.                                 begin
  30.                                         k = k + 1;
  31.                                         l = -1;
  32.                                 end
  33.                 end
  34.         else
  35.                 begin
  36.                         loop1_en = 0;
  37.                         loop2_en = 1;
  38.                         k = -1;
  39.                         l = -1;
  40.                         avg = avg >> 2;
  41.                         $display("%d", avg);
  42.                 end
  43. endtask

  44. task task2;
  45.         if (k <= 1)
  46.                 begin
  47.                         if (l <= 1)
  48.                                 begin
  49.                                         temp =  temp + avg;
  50.                                         l = l + 1;
  51.                                 end
  52.                         else
  53.                                 begin
  54.                                         k = k + 1;
  55.                                         l = -1;
  56.                                 end
  57.                 end
  58.         else
  59.                 begin
  60.                         k = -1;
  61.                         l = -1;
  62.                         loop2_en = 0;
  63.                         loop3_en = 1;
  64.                         $display("%d", temp);
  65.                         avg = 0;
  66.                         temp = 0;
  67.                 end
  68. endtask

  69. task task3;
  70.         if (i < 3)
  71.                 begin
  72.                         if (j < 3)
  73.                                 begin
  74.                                         j = j + 1;
  75.                                         loop3_en = 0;
  76.                                         loop1_en = 1;
  77.                                 end
  78.                         else
  79.                                 begin
  80.                                         $display("biggest loop");
  81.                                         i = i + 1;
  82.                                         j = 1;
  83.                                 end
  84.                 end
  85.         else
  86.                 begin
  87.                         loop1_en = 0;
  88.                         //$display ("finished");
  89.                 end
  90. endtask               

  91.         always @ (posedge clk)
  92.                         begin
  93.                                 if (loop1_en)
  94.                                         begin
  95.                                                 task1;
  96.                                         end
  97.                                 else if (loop2_en)
  98.                                         begin
  99.                                                 task2;
  100.                                         end
  101.                                 else if (loop3_en)
  102.                                         begin
  103.                                                 task3;
  104.                                         end               
  105.                                 else       
  106.                                         begin
  107.                                                 $display("invalid case");
  108.                                         end
  109.                         end
  110.                        
  111. endmodule

复制代码

if else 代码来了,跑过tb,循环跑起来是对的。

軟體與硬體的思考邏輯不同..
所以建議先把演算法用硬體的方式思考一遍
再用RTL寫出...
這樣會比較好

这是仿真用的代码啊


怎么看输出的数据temp啊

学习了软件语言里的for循环转成硬件语言

用计数器写


能具体说一下怎么写吗?谢谢

RE: [verilog] Verilog语言的编写

  1. for(i=0;i<14;i++){
  2.         for(j=0;j<14;j++){

  3.             avg                = 0        ;
  4.             temp        = 0        ;

  5.             for(k=0;k<=2;k++){
  6.                   for(l=0;l<=2;l++){
  7.                           avg = avg + (double)pd[i+k][j+l];

  8.         // ###############
  9.         // 4 counter
  10.         // ###############
  11.         //
  12.         //
  13.         // 1st counter  cnt_dff_l = (cnt_dff_l==l_max) ? 0                 : cnt_dff_l + 1          ;
  14.         //
  15.         // 2nd counter cnt_dff_k = (cnt_dff_l==l_max) && (cnt_dff_k==k_max) ? 0                             :
  16.         //                                       (cnt_dff_l==l_max)                                       ? cnt_dff_k + 1           :
  17.         //                                                                                                               cnt_dff_k                 ;
  18.         //
  19.         // 3rd counter cnt_dff_j = (cnt_dff_l==l_max) && (cnt_dff_k==k_max) && (cnt_dff_j==j_max) ? 0                        :
  20.         //                            (cnt_dff_l==l_max) && (cnt_dff_k==k_max)                                                ? cnt_dff_j + 1        :
  21.         //                                                                                                                                                   cnt_dff_j ;        
  22.         //
  23.         // 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                     :
  24.         //                           (cnt_dff_l==l_max) && (cnt_dff_k==k_max) && (cnt_dff_j==j_max)                                                ? cnt_dff_i + 1   :
  25.         //                                                                                                                                                                                       cnt_dff_i          ;
  26.         // ###############
  27.         // avg_latch
  28.         // ###############
  29.         //  
  30.         // addr1          = cnt_dff_i + cnt_dff_k ;
  31.         // addr2          = cnt_dff_j + cnt_dff_l ;
  32.         // avg_tmp     = avg_dff + pd[addr1][addr2] ;
  33.         //
  34.         // 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 ;
  35.                   }
  36.             }
  37.             
  38.             avg = avg / ((double)sn*sn);
  39.         
  40.         // ###############
  41.         // avg_div
  42.         // ###############
  43.         //
  44.         // avg_div = avg_latch / (sn*sn)

  45.             for(k=-1;k<=1;k++){
  46.                   for(l=-1;l<=1;l++){
  47.                          temp = temp + ((double)pd[i+k][j+l] -avg) * ((double)pd[i+k][j+l] -avg);
  48.                   }
  49.             }  
  50.             
  51.         // ###############
  52.         // temp_latch  
  53.         // ###############
  54.         //  temp_tmp = temp_dff + (pd[addr1][addr2] - avg_div) * (pd[addr1][addr2] - avg_div) ;
  55.         //
  56.         //  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 ;

  57.         }
  58. }

复制代码


寫個概念,需自行改寫成正統 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 電路" 只有平行架構 (電路獨立,迴圈運算無相依性) 才能使用

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top