搜索
bottom↓
回复: 58

原创: 用fpga 实现图形算法的硬件加速设计 有源码,能直接用

  [复制链接]

出0入25汤圆

发表于 2012-3-30 14:46:59 | 显示全部楼层 |阅读模式
本例子我早先已发到别的论坛上,可知音甚少,今在贴之,望对大家有所帮助. 我不想本贴是一个很严肃的技术贴,而作为一种思想,理论联系实践

武术最高境界--万源归宗,其实单片机,dsp ,cpu,都是有限状态机的特例,就数字电路来讲,只是其中的一部分,由此而来,统称的 类mcu,cpu等

都有其特定的长处与短处,软件的东西可以硬件做,硬件的东西可以软件模拟,南拳北腿,内外兼修,方能登堂入室, 心中有招,刀剑棍棒皆可用,

无论单片机,FPGA或是ARM DSP.

下面是Bresenham画线算法 分别用C语言和verilog 分别实现,这是我做的LCD控制器里硬件加速的一个模块,其它如画圆,字符,填充等可以以此类推

Bresenham画线算法 C程序如下:
int BresenhamLine ( int x1 , int y1 , int x2 , int y2 , int c)
{
int dx , dy ;
int tx , ty ;
int inc1 , inc2 ;
int d , iTag ;
int x , y ;
putpixel ( x1 , y1 , c ) ;
if ( x1 == x2 && y1 == y2 )
  return 1 ;
iTag = 0 ;
dx = abs ( x2 - x1 );
dy = abs ( y2 - y1 );
if ( dx < dy )
{
  iTag = 1 ;
  Swap ( & x1 , & y1 );
  Swap ( & x2 , & y2 );
  Swap ( & dx , & dy );
}
tx = ( x2 - x1 ) > 0 ? 1 : -1 ;  
ty = ( y2 - y1 ) > 0 ? 1 : -1 ;
x = x1 ;
y = y1 ;
inc1 = 2 * dy ;
inc2 = 2 * ( dy - dx );
d = inc1 - dx ;
while ( x != x2 )
{
  if ( d < 0 )
   d += inc1 ;
  else
  {
   y += ty ;
   d += inc2 ;
  }
  if ( iTag )
   putpixel ( y , x , c ) ;
  else
   putpixel ( x , y , c ) ;
  x += tx ;
}
return 0;
}
Swap ( int * a , int * b )
{
int tmp ;
tmp = * a ;
* a = * b ;
* b = tmp ;
  
}



FPGA实现如下verilog HDL :
module line
(
    input[31 :0] page_address,
input    clk_i,
input    rstn_i,
input    load_i,
    input    ack_i,
input signed  [15:0] sx,
input signed  [15:0] sy,
input signed  [15:0] ex,
input signed  [15:0] ey,
input[23:0]   f_color_i,
    input[23:0]   b_color_i,
input[7 :0]   data_i,
   
    output[23 :0] data_o,
    output[23 :0] addr_o,
    output        pset_start_o,
    output reg    line_over_o
);
reg[23: 0]  addr;
reg[7 :0]   rdata_i;
reg signed [15:0] x;
reg signed [15:0] y;
reg signed [15  :0] xsign;
reg signed [15  :0] ysign;

reg signed [16  :0] delta_x;
reg signed [16  :0] delta_y;
reg [16  :0] rdelta_x;
reg [16  :0] rdelta_y;
reg signed [16  :0] i;
reg signed [16  :0] e;
reg  change;
reg [3:0]state;
reg   pset_load;
wire  over_o;
// Declare states
parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3,S4 = 4, S5 = 5,S6 =6, S7=7,S40 = 8;
// Determine the next state synchronously, based on the
// current state and the input
always @ (posedge clk_i or negedge rstn_i) begin
  if (! rstn_i)
   begin
     line_over_o <= 1'b0;
     rdata_i <= 8'd0;
     addr    <= 24'd0;
           xsign   <= 16'd0;
           ysign   <= 16'd0;
           delta_x <= 17'd0;
           delta_y <= 17'd0;
            i      <= 17'd0;
            e      <= 17'd0;
            
            pset_load <= 1'b0;
   state <= S0;
   end
  else
   case (state)
    S0:
       if(load_i)
     begin
       line_over_o <= 1'b1;
      
      x       <= sx;
      y       <= sy;
      delta_x <= ex - sx;
      delta_y <= ey - sy;
      state <= S1;
     end
       else
        begin
      line_over_o <= 1'b0;
      state <= S0;
     end
    S1:
       begin
      if(delta_x < 0 ) begin rdelta_x <= (~ delta_x )+ 1'b1; xsign<= -1; end
      else             begin rdelta_x <=  delta_x ;          xsign <= 1;  end
      if(delta_y < 0 ) begin rdelta_y <= (~ delta_y )+ 1'b1; ysign <= -1; end
      else             begin rdelta_y <=  delta_y ;          ysign <= 1;  end
      
      state <= S2;
      
       end  
    S2:
     begin
                 if(rdelta_x < rdelta_y)
                   begin
        delta_x <= rdelta_y;
        delta_y <= rdelta_x;
        change  <= 1'b1;
        end
     else
       begin
        delta_x <= rdelta_x;
        delta_y <= rdelta_y;  
        change  <= 1'b0;
       end                    
     state <= S3;
     end
    S3:
     begin
      e        <= ( delta_y * 2 ) - delta_x;
      i        <= 17'd1;
         rdata_i  <= data_i;
      state    <= S4;
     end
    S4:
     begin
      addr      <=( ( y * 1024 ) + x ) + page_address[23 :0];
      pset_load <= 1'b1;
      state     <= S40;
     end
    S40:
     begin
      if(over_o == 1'b1 )
       begin
         pset_load <= 1'b0;
         state <= S5;   
       end
       else
         state <= S40;   
     end
    S5:
     begin
       if( e >= 0 )
       begin
        if(change == 1'b1) x <= x + xsign;
        else               y <= y + ysign;
        e <= e + ( delta_x * 2);
        state <= S5;
       end   
      else
        state <= S6;
     end
     
    S6:
     begin
      if( change == 1'b1)   y <= y + ysign;
      else                  x <= x + xsign;
       e <= e + ( delta_y * 2);
      state <= S7;
     end
     
    S7:
     begin
      if(i < delta_x )
       begin
         i     <= i + 1'b1;
         state <= S4;
       end
      else
       begin
         line_over_o <= 1'b0;
         state <= S0;
       end
     end
     
   endcase
end

endmodule

阿莫论坛20周年了!感谢大家的支持与爱护!!

阿莫论坛才是最爱国的,关心国家的经济、社会的发展、担心国家被别国牵连卷入战争、知道珍惜来之不易的和平发展,知道师夷之长,关注世界的先进文化与技术,也探讨中国文化的博大精深,也懂得警惕民粹主义的祸国殃民等等等等,无不是爱国忧民的表现。(坛友:tianxian)

出0入0汤圆

发表于 2012-3-30 17:12:53 | 显示全部楼层
顶,一直不懂用FPGA实现算法

出0入0汤圆

发表于 2012-3-30 17:24:17 | 显示全部楼层
楼主你太牛了!

出0入0汤圆

发表于 2012-3-30 17:52:57 | 显示全部楼层
谢谢,MARK。

出0入0汤圆

发表于 2012-3-30 19:20:46 | 显示全部楼层
fpga 实现的, 记号

出0入0汤圆

发表于 2012-3-31 09:08:19 | 显示全部楼层
mark 谢谢

出0入0汤圆

发表于 2012-3-31 12:41:23 | 显示全部楼层
支持楼主,不错

出0入0汤圆

发表于 2012-3-31 12:44:39 | 显示全部楼层
支持楼主,顶!

出0入0汤圆

发表于 2012-3-31 13:19:47 | 显示全部楼层
这个要顶。。。

出0入0汤圆

发表于 2012-3-31 13:41:12 | 显示全部楼层
楼主心中有剑

出0入0汤圆

发表于 2012-4-1 08:05:34 | 显示全部楼层
状态机真是控制时序和跳转的好东西啊

出0入0汤圆

发表于 2012-4-1 08:53:47 | 显示全部楼层
现在刚开始上手FPGA,学习了!

出0入0汤圆

发表于 2012-4-1 09:50:10 | 显示全部楼层


FPGA已经1年多没用了

楼主厉害

出0入0汤圆

发表于 2012-4-1 10:33:42 | 显示全部楼层
其实Verilog 的实现不必拘泥于对于C算法的翻译。比如说求绝对值和dx dy交换那一段在时下流行的FPGA里面完全可以用组合逻辑完成,不会成为timing的瓶颈,不必占用状态,可以减小启动时的延迟。如果实际应用中有大量曲线(由短的直线构成),启动延迟累积起来还是很可观的。
另外我没有仔细看你的代码(个人习惯,状态机的组合逻辑和时序逻辑分开写,所以不太习惯看很长的状态机),不知道你有没有实现每个时钟一个像素的执行效率?
第三就是作为画线功能模块,还是把显存地址的计算分出来比较好,便于灵活配置和移植。还是直接输出XY比较好。
第四就是如果有一个暂停信号,可以暂停画线状态机会很有用。
最后就是想问问LZ有没有计划实现一个反锯齿画线的模块(采用吴小林算法)?

出0入25汤圆

 楼主| 发表于 2012-4-1 15:58:15 | 显示全部楼层
本帖最后由 hxl_led 于 2012-4-1 21:08 编辑
simmconn 发表于 2012-4-1 10:33
其实Verilog 的实现不必拘泥于对于C算法的翻译。比如说求绝对值和dx dy交换那一段在时下流行的FPGA里面完全 ...


呵呵,把高手引出来了,由于没有太多的时间回复每位网友,恕不一一回复了.
一  我开始就讲了这不是一个纯技术的贴子,我说的是做事要有一种思想,然后是理论联系实践
    假如您会一种语言,您懂spi时序,那么您就能操作spi ,又假如您懂SD卡操作时序,那您就能读
    写SD卡扇区,又假如您懂fat32 那您就能用读SD卡中的文件.不论这种语言是C 还是VHDL
     这需用理论基础,这需要软件的,和硬件的,您要清楚您的每句所描述的意义及动作.
     不知我这样说,大家能不能明白我的意思.
二 无论一段式状态机,还是二段式状态机,还是组合和时序分开好等,还是程序风格,这些不是
   本贴希望讨论的,那样会引出更多的争辩,只有更好,没有最好.

三 硬件加速处理图形算法可以用在 雕刻机脱机控制上, 如simmconn大侠能为大家提供好的程序
   那么阿莫老大及广大网友都会热烈欢迎的

出0入0汤圆

发表于 2012-4-1 17:27:35 | 显示全部楼层
就您的程序,真不敢相信您是用fpga的老手。

出0入25汤圆

 楼主| 发表于 2012-4-1 20:41:56 | 显示全部楼层
本帖最后由 hxl_led 于 2012-4-1 20:48 编辑
xcreat 发表于 2012-4-1 17:27
就您的程序,真不敢相信您是用fpga的老手。


请大侠看看,下面的一段.及格吗

parameter IDLE=8'h01, MAC=8'h02, IEEE=8'h04, IP=8'h08,
          ARP=8'h10,  UNK=8'h20, GET=8'h40, CON=8'h80;

            
always@(current or p_empty or p_length or counter or GET_counter
        or len_type or CON_counter)
begin
        next=8'hxx;
        case(current)
        IDLE: begin
                if(!p_empty)
                    next=GET;
                else
                    next=IDLE;
        end
        GET: begin
                if(GET_counter==4)
                    next=MAC;
                else
                    next=GET;
        end
        MAC: begin
                if(counter==12)
                        next=CON;
                else
                        next=MAC;
        end
        CON: begin
                if(CON_counter==3)begin
                        next=ARP;
                        next=UNK;
                end
                else
                        next=CON;
        end
        IEEE: begin
                if(counter==20)
                        next=CON;
                else
                        next=IEEE;
        end
                UNK: begin
                if(counter==p_length)
                        next=IDLE;
                else
                        next=UNK;
        end
        default: next=IDLE;
        endcase
end

always@(posedge clk or negedge rst)
begin
        if(!rst) current<=IDLE;
        else     current<=next;
end

always@(posedge clk or negedge rst)
begin
        if(!rst) begin
                GET_counter <=3'b000;
                p_rd        <=1'b0;
                p_addr      <=13'h0000;
        end
        else begin
                if(next==GET) begin
                        GET_counter<=GET_counter+1'b1;
                        case(GET_counter)
                                0: p_rd   <=1'b1;
                                1: p_rd   <=1'b0;
                                3: p_addr <=p_addr+1'b1;
                        endcase
                end
                else begin
                        GET_counter<=3'b000;
                        p_rd<=1'b0;
                        case(next)
                                IDLE: p_addr <=13'h0000;
                        default:
                                       p_addr <=p_addr+1'b1;
                        endcase
                end
        end
end
always@(posedge clk or negedge rst)
begin
        if(!rst) CON_counter <=2'b00;
        else begin
                if(next==CON)

出0入0汤圆

发表于 2012-4-1 20:48:38 | 显示全部楼层
刚学fpga,状态机这东西真的是很难理解

出0入0汤圆

发表于 2012-4-3 09:48:37 | 显示全部楼层
hxl_led 发表于 2012-4-1 15:58
呵呵,把高手引出来了,由于没有太多的时间回复每位网友,恕不一一回复了.
一  我开始就讲了这不是一个纯技 ...

不至于吧,两段代码就上升到“做事要有一种思想,然后是理论联系实践”的高度。我服了LZ。

不过看帖子的题目好像看不出什么非技术的内容啊
《原创: 用fpga 实现图形算法的硬件加速设计 有源码,能直接用》

LZ既然要规定贴子里可以讨论什么,不可以讨论什么,那我只好道声抱歉,进错地方,打扰了。

本来也没想讨论写代码的风格,只是想解释一下为什么我没有仔细读代码。
想问问LZ画线引擎的效率有没有达到每个时钟一个像素,仅此而已——结果还没有得到答案。

Bresenham画线算法的Verilog代码放狗一搜就能找到好几个。我是用开源的,改改能用就行。

出0入0汤圆

发表于 2012-4-3 10:00:04 | 显示全部楼层
这种实现方式要占用多少资源?

SIMMCON所说达到1pixel / clk应该可以达到,资源耗费相当巨大,但在画曲线时却相当高效

出0入25汤圆

 楼主| 发表于 2012-4-3 12:08:05 | 显示全部楼层
simmconn 发表于 2012-4-3 09:48
不至于吧,两段代码就上升到“做事要有一种思想,然后是理论联系实践”的高度。我服了LZ。

不过看帖子的 ...

请高手simmconn老师将  "Bresenham画线算法的Verilog代码放狗一搜就能找到好几个。我是用开源的,改改能用就行"  上传一,两个来,让大家也

开广眼界,多些学习参考. 也请 网友可不用理会我的胡言乱语,向simmconn 老师学习!



出0入0汤圆

发表于 2012-4-3 13:47:09 | 显示全部楼层
高手称不上,老师也不敢当(要是有LZ这样的学生就更不敢了)。不要向我学习,要向以下代码的原作者们学习:
http://people.ece.cornell.edu/la ... _12_9_09/index.html
(来自康奈尔大学电子系的完整的图形系统,俺用的画线引擎就是从这儿来的)。
http://web.mit.edu/6.111/www/f20 ... ct_Final_Report.pdf
(来自MIT的游戏机项目,其中有硬件源代码)。
其实Bresenham画线引擎在国外电子工程专业本科生和研究生课程中很常见,没有什么大不了的。真不知道触动LZ哪根神经了。

出0入0汤圆

发表于 2012-4-3 14:17:55 | 显示全部楼层
谢啦!楼主真的很厉害

出0入25汤圆

 楼主| 发表于 2012-4-3 14:50:06 来自手机 | 显示全部楼层
simmconn 发表于 2012-4-3 13:47
高手称不上,老师也不敢当(要是有LZ这样的学生就更不敢了)。不要向我学习,要向以下代码的原作者们学习: ...

simmconn老师上传的资料很好,学习中,老师也没触动我的神经,大人不记小人过,您老消消气

出0入0汤圆

发表于 2012-4-3 14:59:01 | 显示全部楼层
我还停留在c绘图上,没到达lz这样的水平啊

出0入0汤圆

发表于 2012-4-3 20:01:29 | 显示全部楼层
值得参考! 顶起!

出0入4汤圆

发表于 2012-4-3 22:12:53 | 显示全部楼层
MARK........

出0入0汤圆

发表于 2012-4-4 18:04:42 | 显示全部楼层
标记一下  改天研究

出0入0汤圆

发表于 2012-4-4 18:11:03 | 显示全部楼层
mark!牛逼

出0入0汤圆

发表于 2012-4-4 19:06:16 | 显示全部楼层
做人要谦虚,我要向以上两位老大学习,这也是我所要学习的知识谢谢了

出0入0汤圆

发表于 2012-5-3 13:57:20 | 显示全部楼层
好 fpga实现算法

出0入0汤圆

发表于 2012-5-3 19:32:00 | 显示全部楼层
大侠们境界很高啊,自叹不如。

出0入0汤圆

发表于 2012-5-3 19:59:21 | 显示全部楼层
支持一下               

出0入0汤圆

发表于 2012-5-4 12:53:19 | 显示全部楼层
simmconn 发表于 2012-4-3 13:47
高手称不上,老师也不敢当(要是有LZ这样的学生就更不敢了)。不要向我学习,要向以下代码的原作者们学习: ...

还有没有这么好的网址介绍了,谢谢

出0入0汤圆

发表于 2012-5-4 13:15:02 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-5-4 14:45:13 | 显示全部楼层
不错不错啊,mark!!!

出0入0汤圆

发表于 2012-5-5 16:38:56 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-5-14 11:58:23 | 显示全部楼层
这个真的是不错!!!

出0入0汤圆

发表于 2012-5-14 15:48:14 | 显示全部楼层
MArk,学习啦

出0入0汤圆

发表于 2012-5-14 16:21:35 | 显示全部楼层
学习一下利用FPGA实现算法。这个实例不错!既有C又有HDL.可以对比着学习下实现算法的思路。

出0入0汤圆

发表于 2012-6-25 16:12:24 | 显示全部楼层
mark~~~~~~~~~~

出0入0汤圆

发表于 2012-6-26 12:07:47 | 显示全部楼层
这个强

出0入0汤圆

发表于 2012-6-27 11:04:00 | 显示全部楼层
值得向hxl_led学习,向hxl_led学习不是指他写的代码,而是能把自己的想法来和大家共享和讨论,这是最难得可贵的;另外,随便鄙视一下simmconn,他的水平可能是很高,但是不和大家共享那什么也不是;

出0入0汤圆

发表于 2012-6-30 13:12:25 | 显示全部楼层
不错,mark

出0入0汤圆

发表于 2012-6-30 23:26:49 | 显示全部楼层
留着 以后肯定用得着!

出0入0汤圆

发表于 2012-6-30 23:31:32 | 显示全部楼层
great,mark

出0入0汤圆

发表于 2012-7-5 18:35:52 | 显示全部楼层
顶一下楼主……

出0入0汤圆

发表于 2012-8-19 16:39:45 | 显示全部楼层
支持楼主无私的分享!!

出0入0汤圆

发表于 2012-8-26 19:23:50 | 显示全部楼层
哎,mark一下吧。。。大神

出0入0汤圆

发表于 2012-11-12 23:49:16 | 显示全部楼层
不错,学习学习

出0入0汤圆

发表于 2012-11-13 01:33:40 | 显示全部楼层
本帖最后由 sky5566 于 2012-11-13 02:04 编辑
simmconn 发表于 2012-4-1 10:33
其实Verilog 的实现不必拘泥于对于C算法的翻译。比如说求绝对值和dx dy交换那一段在时下流行的FPGA里面完全 ...


强~~有没有 3D 的..
听说有一款 3D engine on FPGA 不知道那里下

hxl_led 发表于 2012-4-1 10:33


另外楼主的问题只有程序加速作用,并没有印射到实际的 VGA RAM去,所以你的范例与真正的硬件加速绘图无关.
真正的硬件加速不是这样设计的,19楼说的对.

程序硬化 NIOS II SOPC 有提供设定方式,但是实际效果也没快多少...

出0入0汤圆

发表于 2012-11-13 08:02:21 | 显示全部楼层
marking   

出0入0汤圆

发表于 2012-11-14 16:21:47 | 显示全部楼层
顶起,向你们学习

出0入0汤圆

发表于 2012-11-14 19:59:03 | 显示全部楼层
看到用状态机写的东西感到很清晰,比较好理解。

出0入0汤圆

发表于 2012-11-14 22:47:08 | 显示全部楼层
mark,两位大神学习。。。

出0入0汤圆

发表于 2012-11-14 22:47:35 | 显示全部楼层
资料很不错。。

出0入0汤圆

发表于 2012-11-14 23:17:17 | 显示全部楼层
mark~~~~~~~~~~~~

出0入0汤圆

发表于 2012-12-18 12:07:21 | 显示全部楼层
顶一个,学习了。

出0入0汤圆

发表于 2012-12-18 12:52:53 | 显示全部楼层
http://web.mit.edu/6.111/www/index.html,之前也看到过这个网站MIT的,大概就是FPGA数字系统设计吧,看看里面的项目。再看看学校老师布置的题目,一下发现差距了。PS我们也有类似的一个课设,内容是广告灯、和自动售货机。。。。。。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-16 14:35

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表