在上一篇里http://www.cnblogs.com/sepeng/p/4045593.html 《bresenham算法的FPGA的实现1》已经做了一个整体框架的布局,但是那个程序只是支持|k|<1.要想全屏支持,就还需要对这个程序做修改,觉得自己的修改方式很繁琐,期望大家的指点,有高质量的code出现。算法的原理部分在上一篇中已经给出
1 /* 2 date:2014/10/23 3 version : QuartusII + de1-soc cyclone V 4 designer : pengxiaoen 5 funtion : 实现bresenham 算法在象限对直线的计算 6 说明:(1) in_en 至少是2个clock才能保证前面模块数据装载的成功 7 8 9 10 11 12 */ 13 14 module bresenham ( 15 clock , 16 reset , 17 xs_in , //输入的X 点的起始坐标 18 ys_in , // 输入的Y 点的起始坐标 19 xe_in , //输入X点的终止坐标 20 ye_in , //输入Y 点的终止坐标 21 in_en , //当前输入信号有效标志 1:有效 0:无效 22 23 x_ou, //输出的X 点的坐标 24 y_ou, // 输出的Y 点的坐标 25 fini_flag //计算完成标志位 26 ); 27 input clock ,reset ; 28 input in_en ; 29 input [9:0] xs_in ,xe_in ; 30 input [8:0] ys_in ,ye_in ; 31 32 output reg [9:0] x_ou ; 33 output reg [8:0] y_ou ; 34 output reg fini_flag ; 35 36 wire [15:0] dx ; // X方向上的变化量 37 wire [15:0] dy ; //Y方向上的变化量 38 reg signed [15:0] pi ; //算法pi 39 40 wire [9:0] Xmin ; 41 wire [9:0] Xmax ; 42 wire [8:0] Ymin ; 43 wire [8:0] Ymax ; 44 wire x_dir ; //X走向标志 45 wire y_dir ; //Y走向标志 46 wire cha_flag ; //coordinate change flag 47 // 48 assign x_dir= (xs_in<xe_in)? 1'd0 : 1'd1 ; //0: 递增方向 49 assign y_dir= (ys_in<ye_in)? 1'd0 : 1'd1 ; //1: 递减方向 50 assign Xmin = (xs_in<xe_in)? xs_in : xe_in ; 51 assign Xmax = (xs_in<xe_in)? xe_in : xs_in ; 52 assign Ymin = (ys_in<ye_in)? ys_in : ye_in ; 53 assign Ymax = (ys_in<ye_in)? ye_in : ys_in ; 54 55 assign dx = Xmax-Xmin; //得出X方向上的差值 56 assign dy = Ymax-Ymin; //得出Y方向上的差值 57 assign cha_flag = (dx>dy) ? 1'd0:1'd1 ; //0:右手坐标系 1:左手坐标系 58 59 60 reg signed [9:0] x_cnt ; // 坐标计数 有符号运算 61 //********************************************************** 62 always @ (posedge clock ) 63 if(!reset) 64 begin 65 x_cnt <= 10'd0 ; 66 fini_flag <= 1'd0 ; 67 end 68 else if(cha_flag) //旋转,将X与Y 颠倒过来 69 begin 70 if(in_en) 71 begin 72 x_cnt <= {1'b0,ys_in} ; 73 fini_flag <= 1'd0 ; 74 end 75 else if (x_cnt==ye_in) // 运算完毕 76 fini_flag <= 1'd1 ; 77 else x_cnt <= x_cnt + {{9{y_dir}},1'd1}; 78 end 79 else 80 begin 81 if(in_en) 82 begin 83 x_cnt <= xs_in ; 84 fini_flag <= 1'd0 ; 85 end 86 else if (x_cnt==xe_in) // 运算完毕 87 fini_flag <= 1'd1 ; 88 else x_cnt <= x_cnt + {{9{x_dir}},1'd1}; 89 end 90 91 92 //算法的具体实现部分 93 always @(posedge clock ) 94 if(!reset) 95 begin 96 y_ou <= 9'd0 ; 97 x_ou <= 10'd0 ; 98 end 99 else if ((!fini_flag) && (!in_en)) //运算标志正在运算,并且装载数据完成 100 begin 101 if(pi[15]) 102 begin 103 if(cha_flag) //坐标旋转,X,Y 颠倒 104 begin 105 pi <= pi+(dx<<1) ; 106 y_ou <= x_cnt[8:0] ; 107 end 108 else 109 begin 110 pi <= pi+(dy<<1) ; 111 x_ou <= x_cnt ; 112 end 113 114 end 115 else 116 begin 117 if(cha_flag) //坐标旋转,X,Y 颠倒 118 begin 119 pi <= pi + (dx<<1) - (dy<<1) ; 120 x_ou <= x_ou + {{8{x_dir}},1'd1}; 121 y_ou <= x_cnt[8:0] ; 122 end 123 else 124 begin 125 pi <= pi + (dy<<1) - (dx<<1) ; 126 y_ou <= y_ou + {{8{y_dir}},1'd1}; 127 x_ou <= x_cnt ; 128 end 129 130 end 131 end 132 else 133 begin 134 if(cha_flag) pi<= (dx<<1)-dy ; //坐标旋转,X,Y 颠倒 135 else pi<= (dy<<1)-dx ; 136 y_ou <= ys_in ; 137 x_ou <= xs_in ; 138 end 139 140 endmodule
附上测试代码
1 `timescale 1ns/1ps 2 3 4 module bresenham_tb ; 5 6 reg clock ,reset ; 7 reg in_en ; 8 reg [9:0] xs_in ,xe_in ; 9 reg [8:0] ys_in ,ye_in ; 10 11 wire [9:0] x_ou ; 12 wire [8:0] y_ou ; 13 wire fini_flag ; 14 15 16 bresenham U1_bresenham( 17 .clock (clock), 18 .reset (reset), 19 .xs_in (xs_in), 20 .ys_in (ys_in), 21 .xe_in (xe_in), 22 .ye_in (ye_in), 23 .in_en (in_en), 24 25 .x_ou (x_ou), 26 .y_ou (y_ou), 27 .fini_flag (fini_flag) 28 ); 29 30 31 always #10 clock = ~clock ; 32 33 initial 34 begin 35 clock = 1'd0 ; reset =1'd0 ; in_en = 1'd0 ; 36 xs_in = 10'd0 ; xe_in = 10'd0 ; 37 ys_in = 9'd0 ; ye_in = 9'd0 ; 38 39 #40 reset = 1 ; 40 in_en = 1 ; 41 xs_in = 100 ; xe_in = 200 ; 42 ys_in = 100 ; ye_in = 150 ; 43 #80 in_en = 0 ; 44 #3000 ; // k = 1/2 验证 正方向 45 46 in_en = 1 ; 47 xs_in = 200 ; xe_in = 100; 48 ys_in = 150 ; ye_in = 100; 49 #80 in_en = 0 ; 50 #3000 ; // k = 1/2 验证 反方向 51 52 in_en = 1 ; 53 xs_in = 100 ; xe_in= 200 ; 54 ys_in = 100 ; ye_in= 50 ; 55 #80 in_en = 0 ; // k = -1/2 验证 正方向 56 #3000 57 58 in_en = 1 ; 59 xs_in = 200 ; xe_in= 100; 60 ys_in = 50 ; ye_in= 100 ; 61 #80 in_en = 0 ; // k = -1/2 验证 反方向 62 #3000 63 64 in_en = 1 ; 65 xs_in = 100 ; xe_in= 150 ; 66 ys_in = 100 ; ye_in= 200 ; 67 #80 in_en = 0 ; // k = 2 验证 68 #3000 69 70 in_en = 1 ; 71 xs_in = 100 ; xe_in= 150 ; 72 ys_in = 200 ; ye_in= 100 ; 73 #80 in_en = 0 ; // k = -2 验证 74 #3000 75 $stop ; 76 77 end 78 79 endmodule
欢迎大家提出bug 或者修改意见