EDA设计:最大公约数


前言

  本次主要介绍一下关于EDA的实验:最大公约数,包括两个四位二进制整数以及两个八位二进制整数的最大公约数。


一、设计内容及原理

  FPGA 不仅能够实现数字电路设计,而且能够完成算法设计。
  (1)基础任务:输入两个四位二进制整数,找出他们的最大公约数,输入由拨码开关给入,输出由发光二极管显示。
  (2)提高任务:由拨码开关输入两个八位二进制整数,找出两个输入数值的最大公约数,用数码管显示输入输出数值。

二、设计过程(及设计步骤)

2.1 基础任务

(1)源程序:

module decode(x,y,gcd);
        input wire [3:0] x;         
        input wire [3:0] y;    
        output reg [3:0] gcd;     
        reg [3:0] xs,ys;
        integer n;
        always@(x or y)    
        begin
          xs=x;
          ys=y; 
          for(n=0;n<15;n=n+1)
          begin
            if(xs==ys)   
               xs=xs;
           else if(xs<ys)  
               ys=ys-xs;          
           else 
               xs=xs-ys;        
           gcd=xs;                 
          end
       end             
endmodule



(2)约束程序:

set_property -dict {PACKAGE_PIN K2 IOSTANDARD LVCMOS33} [get_ports {gcd[0]}]
set_property -dict {PACKAGE_PIN J2 IOSTANDARD LVCMOS33} [get_ports {gcd[1]}]
set_property -dict {PACKAGE_PIN J3 IOSTANDARD LVCMOS33} [get_ports {gcd[2]}]
set_property -dict {PACKAGE_PIN H4 IOSTANDARD LVCMOS33} [get_ports {gcd[3]}]
set_property -dict {PACKAGE_PIN R1 IOSTANDARD LVCMOS33} [get_ports {y[0]}]
set_property -dict {PACKAGE_PIN N4 IOSTANDARD LVCMOS33} [get_ports {y[1]}]
set_property -dict {PACKAGE_PIN M4 IOSTANDARD LVCMOS33} [get_ports {y[2]}]
set_property -dict {PACKAGE_PIN R2  IOSTANDARD LVCMOS33} [get_ports {y[3]}]
set_property -dict {PACKAGE_PIN P2  IOSTANDARD LVCMOS33} [get_ports {x[0]}]
set_property -dict {PACKAGE_PIN P3  IOSTANDARD LVCMOS33} [get_ports {x[1]}]
set_property -dict {PACKAGE_PIN P4  IOSTANDARD LVCMOS33} [get_ports {x[2]}]
set_property -dict {PACKAGE_PIN P5  IOSTANDARD LVCMOS33} [get_ports {x[3]}]

2.2 提高任务

(1)源程序:

module decode(x,y,led_pin,clk,rst_n,b,an);  //声明模块名,端口信号
        input clk;     //时钟  
        input rst_n;  //清零端
        input wire [7:0] x;   //输入的8位二进制数x   
        input wire [7:0] y;   //输入的8位二进制数 y  
        output reg [15:0] led_pin;  //输出的最大公约数
        output reg [7:0] b;     //段信号
        output reg [3:0] an;   //位选信号    
        reg    [3:0] one,ten;
        reg    [1:0] hun;
        reg    [3:0] count;
        reg    [17:0]shift_reg=18'b000000000000000000;       
        reg [7:0] xs,ys;
        reg [7:0] bin;
        integer n;
        always@(x or y)    
        begin
          xs=x;
          ys=y; 
          for(n=0;n<128;n=n+1)
          begin
            if(xs==ys)   
               xs=xs;
           else if(xs<ys)  
               ys=ys-xs;          
           else 
               xs=xs-ys;        
           bin=xs;                 
          end
       end 
        always @ ( posedge clk or negedge rst_n )  // 计数部分
        begin
        if( !rst_n )
             count<=0;
        else if (count==9)
             count<=0;
        else
             count<=count+1;
        end      
       always @ (posedge clk or negedge rst_n ) // 二进制转换为十进制 
       begin
       if (!rst_n)
            shift_reg=0;
       else if (count==0)
             shift_reg={10'b0000000000,bin};
       else if ( count<=8)                //实现8次移位操作
       begin
       if(shift_reg[11:8]>=5)         //判断个位是否>5,如果是则+3  
          begin
             if(shift_reg[15:12]>=5) //判断十位是否>5,如果是则+3  
                 begin
                   shift_reg[15:12]=shift_reg[15:12]+2'b11;   
                   shift_reg[11:8]=shift_reg[11:8]+2'b11;
                   shift_reg=shift_reg<<1;  //对个位和十位操作结束后,整体左移
                 end
            else
            begin
                 shift_reg[15:12]=shift_reg[15:12];
                 shift_reg[11:8]=shift_reg[11:8]+2'b11;
                 shift_reg=shift_reg<<1;
            end
          end              
          else
          begin
             if(shift_reg[15:12]>=5)
                 begin
                 shift_reg[15:12]=shift_reg[15:12]+2'b11;
                 shift_reg[11:8]=shift_reg[11:8];
                shift_reg=shift_reg<<1;
              end
             else
             begin
                  shift_reg[15:12]=shift_reg[15:12];
                  shift_reg[11:8]=shift_reg[11:8];
                  shift_reg=shift_reg<<1;
             end
          end        
        end
       end
       always @ ( posedge clk or negedge rst_n )
       begin
       if ( !rst_n )
       begin
         one<=0;
         ten<=0;
         hun<=0; 
       end
       else if (count==9)  //此时8次移位全部完成,将对应的值分别赋给个,十,百位
       begin
          led_pin[15:10]<=6'b000000; 
          led_pin[9:0]<=shift_reg[17:8]; 
        end      
      end           
      reg [20:0] clkdiv;  //时钟分频 计数器
      always @(posedge clk or negedge rst_n)
      begin
           if(!rst_n)
	clkdiv<=21'd0;
           else
	clkdiv<=clkdiv+1;
      end
      wire  [1:0]bitcnt;
      assign bitcnt=clkdiv[20:19];
      always @(posedge clk or negedge rst_n) //an:位选信号产生,高有效
      begin 
      if(!rst_n)
           an=4'd0;
      else
      case(bitcnt)
           2'd0:an=4'b0001;
           2'd1:an=4'b0010;
           2'd2:an=4'b0100;
           2'd3:an=4'b1000;
       endcase
      end
       reg [3:0]digit;  //it 当前带显示的数字
      always @(posedge clk or negedge rst_n)
           begin
          if (!rst_n)
	digit=4'd0;
          else
	case(bitcnt)
	  2'd0:digit=led_pin[3:0];
	  2'd1:digit=led_pin[7:4];
	  2'd2:digit=led_pin[11:8];
	  2'd3:digit=led_pin[15:12];
	  default:digit=4'd0;
	endcase
           end
//b: 段码信号,共阴极数码管,段码高有效。 7段译码表
           always @(posedge clk or negedge rst_n)
           begin
           if(!rst_n)
               b=8'b11111100;
           else
            case(digit)
               0:b=8'b11111100;
               1:b=8'b01100000;
               2:b=8'b11011010;
               3:b=8'b11110010;
               4:b=8'b01100110;
               5:b=8'b10110110;
               6:b=8'b10111110;
               7:b=8'b11100000;
               8:b=8'b11111110;
               9:b=8'b11110110;
               default:b=8'b11111100;
            endcase
          end
endmodule



(2)约束程序:

##按键
set_property -dict {PACKAGE_PIN B4 IOSTANDARD LVCMOS33} [get_ports {b[7]}]  
set_property -dict {PACKAGE_PIN A4 IOSTANDARD LVCMOS33} [get_ports {b[6]}]  
set_property -dict {PACKAGE_PIN A3 IOSTANDARD LVCMOS33} [get_ports {b[5]}]
set_property -dict {PACKAGE_PIN B1 IOSTANDARD LVCMOS33} [get_ports {b[4]}]
set_property -dict {PACKAGE_PIN A1 IOSTANDARD LVCMOS33} [get_ports {b[3]}]
set_property -dict {PACKAGE_PIN B3 IOSTANDARD LVCMOS33} [get_ports {b[2]}]
set_property -dict {PACKAGE_PIN B2 IOSTANDARD LVCMOS33} [get_ports {b[1]}]
set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS33} [get_ports {b[0]}]
set_property -dict {PACKAGE_PIN G2 IOSTANDARD LVCMOS33} [get_ports {an[3]}]   
set_property -dict {PACKAGE_PIN C2 IOSTANDARD LVCMOS33} [get_ports {an[2]}]
set_property -dict {PACKAGE_PIN C1 IOSTANDARD LVCMOS33} [get_ports {an[1]}]
set_property -dict {PACKAGE_PIN H1 IOSTANDARD LVCMOS33} [get_ports {an[0]}]
set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports clk ]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports rst_n ]
set_property -dict {PACKAGE_PIN R1 IOSTANDARD LVCMOS33} [get_ports {y[0]}]
set_property -dict {PACKAGE_PIN N4 IOSTANDARD LVCMOS33} [get_ports {y[1]}]
set_property -dict {PACKAGE_PIN M4 IOSTANDARD LVCMOS33} [get_ports {y[2]}]
set_property -dict {PACKAGE_PIN R2  IOSTANDARD LVCMOS33} [get_ports {y[3]}]
set_property -dict {PACKAGE_PIN P2  IOSTANDARD LVCMOS33} [get_ports {y[4]}]
set_property -dict {PACKAGE_PIN P3  IOSTANDARD LVCMOS33} [get_ports {y[5]}]
set_property -dict {PACKAGE_PIN P4  IOSTANDARD LVCMOS33} [get_ports {y[6]}]
set_property -dict {PACKAGE_PIN P5  IOSTANDARD LVCMOS33} [get_ports {y[7]}]
set_property -dict {PACKAGE_PIN T5 IOSTANDARD LVCMOS33} [get_ports {x[0]}]
set_property -dict {PACKAGE_PIN T3 IOSTANDARD LVCMOS33} [get_ports {x[1]}]
set_property -dict {PACKAGE_PIN R3 IOSTANDARD LVCMOS33} [get_ports {x[2]}]
set_property -dict {PACKAGE_PIN V4 IOSTANDARD LVCMOS33} [get_ports {x[3]}]
set_property -dict {PACKAGE_PIN V5 IOSTANDARD LVCMOS33} [get_ports {x[4]}]
set_property -dict {PACKAGE_PIN V2 IOSTANDARD LVCMOS33} [get_ports {x[5]}]
set_property -dict {PACKAGE_PIN U2 IOSTANDARD LVCMOS33} [get_ports {x[6]}]
set_property -dict {PACKAGE_PIN U3 IOSTANDARD LVCMOS33} [get_ports {x[7]}]

三、 硬件验证

3.1 基础任务

在这里插入图片描述 在这里插入图片描述在这里插入图片描述 在这里插入图片描述

  当按键F6、G4、G3、J4时(前四位拨码开关),表示第一个四位二进制数;当按键H4、J3、J2、K2时(后四位拨码开关),表示第二个四位二进制数;4个LED表示二进制最大公约数。
  例如:第一幅图中输入的两个二进制数均为1111,即15和15的最大公约数,为15,对应的led显示为1111。
  第二幅图中输入的两个二进制数分别为0010和0100,即2和4的最大公约数,为2,对应的led显示为0010。

3.2 提高任务

在这里插入图片描述 在这里插入图片描述在这里插入图片描述 在这里插入图片描述

  当按键F6、G4、G3、J4、H4、J3、J2、K2时(前八位拨码开关),表示第一个八位二进制数;当按键时U3、U2、V2、V5、V4、R3、T3、T5(后八位拨码开关),表示第二个八位二进制数;前4个数码管显示十进制最大公约数。
  例如:第一幅图中输入的两个二进制数分别为00000100和10000000,即128和8的最大公约数,为8,对应的数码管显示为8。
  第二幅图中输入的两个二进制数分别为11111111和11111111,即255和255的最大公约数,为255,对应的数码管显示为255。

四、 问题解决

  1.问题:基础部分知道用LED显示结果,但是数码管不知道该怎么去控制。
  解决办法:在网上查阅后,发现首先需要将求出的结果转化为十进制,然后用数码管循环显示。
  2.问题:Vivado 上的数码管编程和自己之前学的51单片机不同,一开始不知如何写源程序去调用。
  解决办法:在进行编码转换器显示到数码管程序前,学习显示译码器部分内 容,通过参考7段数码管显示十进制数 12345678,来实现bcd码转换器在数码管上的显示
  3.问题:源文件提示错误[Synth 8-3352] multi-driven net count[9] with 2nd driver pin’count_reg[9]/Q’。
  解决办法:在网上查阅后,发现这个错误的原因是在多个always块中对同一个reg型寄存器赋值,后来我把两个always语句合并成了一个,就解决了问题。
  4.问题:编写的约束文件总是显示到某一行有错误。
  解决办法:编写的约束文件时我犯过几个错误,主要有三个地方需要注意:(1)约束文件的注释符和源文件不一样,应该用##,而不是//。(2)引脚间要注意有空格。(3)端口信号是一位时,不需要用{}。例如[get_ports {wei}]是错误的,应该写成[get_ports wei]。
  5.问题:做基础任务时,编写源代码时,首先看到的书上的程序,书上用的是一个while语句来进行循环,但是仿真时会有错误。
  解决办法:自己通过查阅资料,发现while的循环次数是无限的,仿真时无法构架电路。但是我们小组没有按照书上的程序进行顶层模块的调动,来实现求最大公约数。而是用了一个for循环,确定2个四位二进制求最大公约数最多循环15次。因此只需要for循环多于相应的次数即可出结果,for(n=0;n<15;n=n+1)。
后面我们小组又做了提高任务,将2个四位二进制变成了2个八位二进制,循环次数变为了128,可以用led很容易来表示对应的结果。

五、 心得体会

  在进行本次实验时,我首先从最大公约数的原理入手,只做了基础部分和提高部分,这里我程序原理设计用的是更相减损法。
  做基础任务,编写源代码时,我首先看到的书上的程序,书上用的是一个while语句来进行循环,但是仿真时会有错误,因为while的循环次数是无限的,仿真时无法构架电路。但是我没有按照书上的程序进行顶层模块的调动,来实现求最大公约数。而是用了一个for循环,确定2个四位二进制求最大公约数最多循环15次。因此只需要for循环多于相应的次数即可出结果,for(n=0;n<15;n=n+1)。
  后面我又做了提高任务,将2个四位二进制变成了2个八位二进制,循环次数变为了128,可以用led很容易来表示对应的结果。但是题中要求用数码管显示结果,因此首先需要将求出的结果转化为十进制,然后用数码管循环显示。由于我在做组合逻辑电路时,没有做二进制转十进制的实验,因此,需要重新编程,导致我另外设计了二进制转十进制的程序,验证正确后,才加入了原程序中。这里我并没有用层次化设计,而是将其放在了一个程序中。转化时8次移位全部完成,将对应的值分别赋给个,十,百位,然后led_pin[15:10]=6’b000000; led_pin[9:0]=shift_reg[17:8];将重新赋值后的led_pin用数码管显示。

  • 17
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道无方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值