作者: hxl_led 时间: 2012-3-30 14:46
标题: 原创: 用fpga 实现图形算法的硬件加速设计 有源码,能直接用
本例子我早先已发到别的论坛上,可知音甚少,今在贴之,望对大家有所帮助. 我不想本贴是一个很严肃的技术贴,而作为一种思想,理论联系实践
武术最高境界--万源归宗,其实单片机,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
|