bresenham算法的FPGA的实现2
0赞
发表于 10/23/2014 2:20:27 PM
阅读(2651)
在上一篇里http://www.cnblogs.com/sepeng/p/4045593.html 《bresenham算法的FPGA的实现1》已经做了一个整体框架的布局,但是那个程序只是支持|k|<1.要想全屏支持,就还需要对这个程序做修改,觉得自己的修改方式很繁琐,期望大家的指点,有高质量的code出现。算法的原理部分在上一篇中已经给出
/*
date:2014/10/23
version : QuartusII + de1-soc cyclone V
designer : pengxiaoen
funtion : 实现bresenham 算法在象限对直线的计算
说明:(1) in_en 至少是2个clock才能保证前面模块数据装载的成功
*/
module bresenham (
clock ,
reset ,
xs_in , //输入的X 点的起始坐标
ys_in , // 输入的Y 点的起始坐标
xe_in , //输入X点的终止坐标
ye_in , //输入Y 点的终止坐标
in_en , //当前输入信号有效标志 1:有效 0:无效
x_ou, //输出的X 点的坐标
y_ou, // 输出的Y 点的坐标
fini_flag //计算完成标志位
);
input clock ,reset ;
input in_en ;
input [9:0] xs_in ,xe_in ;
input [8:0] ys_in ,ye_in ;
output reg [9:0] x_ou ;
output reg [8:0] y_ou ;
output reg fini_flag ;
wire [15:0] dx ; // X方向上的变化量
wire [15:0] dy ; //Y方向上的变化量
reg signed [15:0] pi ; //算法pi
wire [9:0] Xmin ;
wire [9:0] Xmax ;
wire [8:0] Ymin ;
wire [8:0] Ymax ;
wire x_dir ; //X走向标志
wire y_dir ; //Y走向标志
wire cha_flag ; //coordinate change flag
//
assign x_dir= (xs_in<xe_in)? 1'd0 : 1'd1 ; //0: 递增方向
assign y_dir= (ys_in<ye_in)? 1'd0 : 1'd1 ; //1: 递减方向
assign Xmin = (xs_in<xe_in)? xs_in : xe_in ;
assign Xmax = (xs_in<xe_in)? xe_in : xs_in ;
assign Ymin = (ys_in<ye_in)? ys_in : ye_in ;
assign Ymax = (ys_in<ye_in)? ye_in : ys_in ;
assign dx = Xmax-Xmin; //得出X方向上的差值
assign dy = Ymax-Ymin; //得出Y方向上的差值
assign cha_flag = (dx>dy) ? 1'd0:1'd1 ; //0:右手坐标系 1:左手坐标系
reg signed [9:0] x_cnt ; // 坐标计数 有符号运算
//**********************************************************
always @ (posedge clock )
if(!reset)
begin
x_cnt <= 10'd0 ;
fini_flag <= 1'd0 ;
end
else if(cha_flag) //旋转,将X与Y 颠倒过来
begin
if(in_en)
begin
x_cnt <= {1'b0,ys_in} ;
fini_flag <= 1'd0 ;
end
else if (x_cnt==ye_in) // 运算完毕
fini_flag <= 1'd1 ;
else x_cnt <= x_cnt + {{9{y_dir}},1'd1};
end
else
begin
if(in_en)
begin
x_cnt <= xs_in ;
fini_flag <= 1'd0 ;
end
else if (x_cnt==xe_in) // 运算完毕
fini_flag <= 1'd1 ;
else x_cnt <= x_cnt + {{9{x_dir}},1'd1};
end
//算法的具体实现部分
always @(posedge clock )
if(!reset)
begin
y_ou <= 9'd0 ;
x_ou <= 10'd0 ;
end
else if ((!fini_flag) && (!in_en)) //运算标志正在运算,并且装载数据完成
begin
if(pi[15])
begin
if(cha_flag) //坐标旋转,X,Y 颠倒
begin
pi <= pi+(dx<<1) ;
y_ou <= x_cnt[8:0] ;
end
else
begin
pi <= pi+(dy<<1) ;
x_ou <= x_cnt ;
end
end
else
begin
if(cha_flag) //坐标旋转,X,Y 颠倒
begin
pi <= pi + (dx<<1) - (dy<<1) ;
x_ou <= x_ou + {{8{x_dir}},1'd1};
y_ou <= x_cnt[8:0] ;
end
else
begin
pi <= pi + (dy<<1) - (dx<<1) ;
y_ou <= y_ou + {{8{y_dir}},1'd1};
x_ou <= x_cnt ;
end
end
end
else
begin
if(cha_flag) pi<= (dx<<1)-dy ; //坐标旋转,X,Y 颠倒
else pi<= (dy<<1)-dx ;
y_ou <= ys_in ;
x_ou <= xs_in ;
end
endmodule附上测试代码
`timescale 1ns/1ps module bresenham_tb ; reg clock ,reset ; reg in_en ; reg [9:0] xs_in ,xe_in ; reg [8:0] ys_in ,ye_in ; wire [9:0] x_ou ; wire [8:0] y_ou ; wire fini_flag ; bresenham U1_bresenham( .clock (clock), .reset (reset), .xs_in (xs_in), .ys_in (ys_in), .xe_in (xe_in), .ye_in (ye_in), .in_en (in_en), .x_ou (x_ou), .y_ou (y_ou), .fini_flag (fini_flag) ); always #10 clock = ~clock ; initial begin clock = 1'd0 ; reset =1'd0 ; in_en = 1'd0 ; xs_in = 10'd0 ; xe_in = 10'd0 ; ys_in = 9'd0 ; ye_in = 9'd0 ; #40 reset = 1 ; in_en = 1 ; xs_in = 100 ; xe_in = 200 ; ys_in = 100 ; ye_in = 150 ; #80 in_en = 0 ; #3000 ; // k = 1/2 验证 正方向 in_en = 1 ; xs_in = 200 ; xe_in = 100; ys_in = 150 ; ye_in = 100; #80 in_en = 0 ; #3000 ; // k = 1/2 验证 反方向 in_en = 1 ; xs_in = 100 ; xe_in= 200 ; ys_in = 100 ; ye_in= 50 ; #80 in_en = 0 ; // k = -1/2 验证 正方向 #3000 in_en = 1 ; xs_in = 200 ; xe_in= 100; ys_in = 50 ; ye_in= 100 ; #80 in_en = 0 ; // k = -1/2 验证 反方向 #3000 in_en = 1 ; xs_in = 100 ; xe_in= 150 ; ys_in = 100 ; ye_in= 200 ; #80 in_en = 0 ; // k = 2 验证 #3000 in_en = 1 ; xs_in = 100 ; xe_in= 150 ; ys_in = 200 ; ye_in= 100 ; #80 in_en = 0 ; // k = -2 验证 #3000 $stop ; end endmodule
欢迎大家提出bug 或者修改意见
