zoukankan      html  css  js  c++  java
  • line

      小君童靴说头儿给了他一个project,实现给出屏幕上任意两个点,求出这两个点之间直线上的所有的点。觉得这个很好玩,就自己也写了一点code

      1 /*
      2 date : 2014/10/21
      3 version : QuartusII 14.0 + DE1-SOC(cycloneV)
      4 function: 输入两个点 Xmax = 1023  Ymax = 511 ,计算出中间点的坐标 
      5 
      6 说明 : (1)1023=0x3ff  (10bit)    511 = 0x1ff (9bit)
      7        (2)直线方程: y=kx+m ;
      8        (3)第116行 装载Ymin值的时候-1, 要求输入Ymin不可以小于1:如
      9 果这个地方不剪掉1,会导致输出有(Ymax-Ymin)个脉冲的延时
     10        (4)现象三的原因是 144 行的判定方法导致。判定当前点为合适点的
     11 方式是第二次离直线最近,第一次prev2_dm 较大,第三次curr_dm也较大,116
     12 行不减1就无法满足“远,近,远”的判定,从而一直扫到最后都找不到合适点。
     13        (5)本程序的计算方式是最直接的运算,计算量大,浪费硬件资源,更
     14 好的算法等待大家的指点
     15        (6)由于计算输出延时了三个周期,如150行,所以最后三个点无法覆盖到。
     16 */
     17 
     18 
     19 module line (
     20             clock ,
     21             reset ,
     22             xs_in ,        //输入的X 点的起始坐标
     23             ys_in ,        // 输入的Y 点的起始坐标 
     24             xe_in ,        //输入X点的终止坐标
     25             ye_in ,        //输入Y 点的终止坐标
     26             in_en ,        //当前输入信号有效标志    1:有效    0:无效
     27             
     28             x_ou,         //输出的X 点的坐标 
     29             y_ou,         // 输出的Y 点的坐标  
     30             fini_flag     //计算完成标志位
     31             );
     32   input         clock ,reset  ; 
     33   input         in_en ; 
     34   input [9:0]     xs_in  ,xe_in ;
     35   input [8:0]     ys_in  ,ye_in ; 
     36   
     37   output reg [9:0]    x_ou ; 
     38   output reg [8:0]    y_ou ; 
     39   output reg        fini_flag ; 
     40   
     41   wire signed [15:0] dx  ;     // X方向上的变化量
     42   wire signed [15:0] dy  ;     //Y方向上的变化量  
     43   reg signed  [15:0] line_k ;  // 用来存储线条的斜率        
     44   reg signed  [15:0]  line_m ;  // 直线的常数项 
     45   reg signed  [15:0]  curr_m ;     //当前m值
     46   reg         [15:0]  curr_dm ; //当前的m偏差量
     47   reg         [15:0]  prev1_dm ; //上一次的m偏差量
     48   reg         [15:0]  prev2_dm ; //上上一次m的偏差量
     49   reg                    point_flag ; //找到当前最近点的标志位    
     50   
     51   wire signed  [9:0] Xmin ; 
     52   wire signed  [9:0] Xmax ; 
     53   wire signed  [8:0] Ymin ; 
     54   wire signed  [8:0] Ymax ; 
     55 
     56   assign dx = xe_in-xs_in;  //得出X方向上的差值
     57   assign dy = ye_in-ys_in;  //得出Y方向上的差值
     58   
     59   
     60   //求得所需的直线就在这么一个矩形框内,针对这个矩形框进行运算
     61   assign Xmin = (xs_in<xe_in)? xs_in : xe_in ;
     62   assign Xmax = (xs_in<xe_in)? xe_in : xs_in ;
     63   assign Ymin = (ys_in<ye_in)? ys_in : ye_in ;
     64   assign Ymax = (ys_in<ye_in)? ye_in : ys_in ;
     65   
     66   //绝对值函数
     67   function [15:0] abs (input signed[15:0] data1,  input signed [15:0] data2 );
     68         abs = (data1>data2) ? (data1-data2):(data2-data1);
     69   endfunction 
     70         
     71 //*********斜率的计算,并且扩大了2^6次方倍,并得出M值的2^6倍的大小******************  
     72   always @ (posedge clock)
     73         if(!in_en)
     74             begin 
     75                     //line_k <= 16'd0 ;
     76                     //line_m <= 16'd0 ;
     77             end 
     78         else 
     79             begin 
     80                     line_k <= (dy<<6)/(dx) ; 
     81                     line_m <= (ye_in<<6) - line_k*xe_in ; 
     82             end 
     83             
     84 reg  [9:0] x_cnt ;        // X 坐标计数
     85 reg  [8:0] y_cnt ;        // Y 坐标计数
     86 //*********************矩形框X方向上计数*********************************    
     87 always @ (posedge clock )
     88     if(!reset)             
     89             begin 
     90                     x_cnt     <= 10'd0 ; 
     91                     fini_flag <= 1'd0  ; 
     92             end 
     93     else if (in_en) //装载Xmin值
     94             begin 
     95                     x_cnt     <= Xmin + 10'd1 ;
     96                     fini_flag <= 1'd0  ; 
     97             end 
     98     else if (x_cnt == Xmax) //矩形框扫描完毕   
     99             begin 
    100                     fini_flag <= 1'd1  ;
    101             end 
    102     else if ((y_cnt==Ymax)||(point_flag))  //列扫描完毕,x+1 
    103             begin 
    104                     x_cnt     <= x_cnt + 10'd1 ; 
    105                     fini_flag <= 1'd0 ; 
    106             end 
    107 
    108 //********************矩形框Y方向上计数 **************            
    109 always @ (posedge clock )
    110     if(!reset)             
    111             begin 
    112                     y_cnt   <= 9'd0 ; 
    113             end 
    114     else if (in_en)  //装载Ymin值
    115             begin 
    116                     y_cnt   <= Ymin - 9'd1 ;
    117             end 
    118     else if ((y_cnt == Ymax)||(point_flag)) //列扫描完毕重新装载运算     
    119             begin 
    120                     y_cnt     <= Ymin ;
    121             end 
    122     else     begin 
    123                     y_cnt   <= y_cnt + 9'd1 ; 
    124             end 
    125 
    126   always @ (posedge clock )
    127     if ((!reset) || (in_en))  
    128             begin 
    129                     x_ou       <= 10'd0 ; 
    130                     y_ou       <= 9'd0  ; 
    131                     point_flag <= 1'd0  ;
    132                     prev1_dm   <= 16'd0 ;
    133                     prev2_dm   <= 16'd0 ;
    134                     curr_dm    <= 16'd0 ;  
    135             end 
    136     else if (!fini_flag)
    137             begin 
    138                     //point_flag <= 1'd0 ;
    139                     curr_m  <= (y_cnt<<6)-(x_cnt*line_k) ;
    140                     prev1_dm <= curr_dm ;
    141                     prev2_dm <= prev1_dm;
    142                     curr_dm <= abs(curr_m , line_m) ;
    143                     if((prev1_dm<curr_dm) &&(prev1_dm < prev2_dm)) //当前点在远离直线,以上一次的点有效
    144                             begin
    145                                     point_flag <= 1'd1 ; //找到最近点,x,y跳转,结束x列的查找
    146                                     prev1_dm   <= 16'h00 ;
    147                                     curr_dm    <= 16'h00 ;
    148                                     prev2_dm   <= 16'h00 ;
    149                                     x_ou <= x_cnt; 
    150                                     y_ou <= y_cnt - 9'd3 ;
    151                             end
    152                     else     point_flag <= 1'd0 ;
    153             end 
    154     else    begin
    155                     point_flag <= 1'd0 ;
    156                     prev1_dm   <= 16'h00 ;
    157                     curr_dm    <= 16'h00 ;
    158                     prev2_dm   <= 16'h00 ;
    159                     x_ou       <= 10'd0 ; 
    160                     y_ou       <= 9'd0  ; 
    161             end 
    162 
    163 endmodule 

    附上测试tb

     1 `timescale 1ns/1ps
     2 
     3 
     4 module line_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 line U1_line(
    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 ; in_en = 1 ; 
    40                 xs_in = 100 ; xe_in = 200 ; 
    41                 ys_in = 100 ; ye_in = 200 ; 
    42             #80 in_en = 0 ; 
    43             #80000 ;
    44             #50000 ;
    45             in_en = 1 ; 
    46             xs_in = 50 ; xe_in= 90 ; 
    47             ys_in = 120; ye_in= 20 ; 
    48             #80 in_en = 0 ; 
    49             #90000  $stop ; 
    50                 
    51     end 
    52 
    53 endmodule 

    其实我听到这个project第一反应是软件中的两个for循环查找差值最小的点,再对应到HDL中想到的是generate,generate写到一半才发现输出怎么办,难道先让结果放到memory里面再慢慢取出来?觉得这么做是不是太繁琐了,于是叉掉重现写。

    第二次想到的是用if  else 实现软件中的for,写了n久都觉得这个逻辑关系很纠结,if else 都嵌套了。再加一层嵌套就不利于维护了,证明这个架构是不行的。

    最后一想不是可以用计数器实现for吗,哎,是不是最近一直在看C,怎么把HDL设计思想和C 想混合了。对于大师来说我的这个思维历程很搞笑,对于菜鸟的我来说是第一次亲身感受到了软硬件代码设计思想的差异—— 以前只是书上说自己没有感触到

  • 相关阅读:
    Docker部署LAMP项目
    Linux学习4-部署LAMP项目
    Docker环境安装
    Python数据库读写
    Python读取和写入Excel文件数据
    Python读取和写入txt,csv文件数据
    Linux学习1-软件测试从业者的高频Linux命令
    Docker的基础命令
    TurtleBot3 MODEL的相应说明
    ROS2 SLAM(同时定位和地图绘制)
  • 原文地址:https://www.cnblogs.com/sepeng/p/4042464.html
Copyright © 2011-2022 走看看