清霜一梦

bresenham算法的FPGA的实现2

0
阅读(1334)

在上一篇里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 或者修改意见