FPGA设计:介绍三种不同的分频方法

我们这次来讲解使用VHDL语言编写三种不同的分频方法
代码如下:
第一种:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity devide5m is
	port(clkin:in std_logic;
		  clkout:buffer std_logic);
	end;
	
architecture rtl of devide5m is
	begin 
		process(clkin)
			variable num:integer range 0 to 4;  --定义一个变量
				begin
					if clkin'event and clkin='1' then        --检测信号的上升沿
						if num<4 then num:=num+1;       
							else num:=0;clkout<=not clkout;    --取反
						end if;
					end if;
		end process;
end;

程序是设置一个0-4范围的变量,然后通过检测信号上升沿后使num+1,然后加到num为4后使num为0,然后将clkout信号取反。这样我们就可以得到一个0-4的高电平和0-4的低电平,这样周期就是10,我们就可以得到一个10分频的模块,如果输入信号频率为10Hz,则输出的信号频率为1Hz

第二种:采用m1和m2可以更加灵活设置分频值和占空比
代码如下:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY devide1 IS 
  PORT(clk_in:IN STD_LOGIC;
        clk_out:OUT STD_LOGIC);
   END devide1;
ARCHITECTURE RTL OF devide1 IS
constant m1:integer:=9;       --定义了几分频
constant m2:integer:=4;       --定义了占空比
signal cc:integer range 0 to m1;     --定义一个信号量
  BEGIN     
PROCESS(clk_in)
     BEGIN      
      IF (clk_in'EVENT AND clk_in='1' ) THEN 
          if cc<m1 then cc<=cc+1;          
              else  cc<=0;
             end if;
          end if;
             end process;
     process(clk_in)
       begin
          if clk_in'event and clk_in='1' then
              if cc<=m2 then  clk_out<='1';    --小于等于m2,clk_out输出高电平
                   else clk_out<='0';          --大于m2,clk_out输出低电平
              end if;
           end if;
        end process;
    END RTL;

这个分频模块采用两个常量m1和m2来设置分频数和占空比,我们可以从程序中看到第一个进程中是当cc<m1就可以使cc+1,反之则cc=0,重新开始。这样当m1=9时候,cc的范围就为0-9,一共得到十个数。这样我们就可以实现十分频。然后第二个进程是根据m2的值来设置clk_out的输出高低电平,程序中m2=4和cc<=m2,所以当cc为0-4的时候clk_out=1;当cc为5-9时候clk_out=0。我们可以得到高电平和低电平持续时间都为五个周期。所以根据占空比公式=高电平周期/整个信号周期,我们可以得到输出信号的占空比为5/10=1/2。

第三种:采用两个信号根据上升沿和下降沿之差来得到频率为奇数其占空比为1/2的分频方法
代码如下:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
entity div1to2 is 
  port(clk_in:in std_logic;
       clk_out:out std_logic);
end div1to2;
architecture rtl of div1to2 is
  constant fpb:integer:=18;    --设置分频值
  constant temp:integer:=9;    --设置占空比
signal a1,a2:integer range 0 to fpb;
signal ctr1,ctr2: std_logic;
 begin
    process(clk_in)
       begin
		 if rising_edge(clk_in) then   --检测信号上升沿
              if a1<fpb then a1<=a1+1;
                  else a1<=0;
               end if;
          end if;    end process; 
    process(clk_in)
       begin
         if falling_edge(clk_in)  then  --检测信号下降沿
              if a2<fpb then a2<=a2+1;
                 else a2<=0;
               end if;
         end if;   end process;
	process(clk_in)
     begin
      if rising_edge(clk_in) then
		if a1<temp  then ctr1<='1';   --从第一个周期的上升沿开始
               else ctr1<='0';
        end if;
      end if;
    end process;
 
  process(clk_in)
   begin
     if falling_edge(clk_in) then
           if a2<temp then ctr2<='1' ; --从第一个周期的下降沿开始
              else ctr2<='0';
            end if;
         end if;
     end process;
   clk_out<=ctr1 or ctr2;   --将两个信号的高电平时间进行或运算
 end ;

仿真图如下,从图中可以看到clk_out的高电平周期为9.5。
在这里插入图片描述

原理讲解:
第三种方法我设置两个常数fpb和temp,fpb是用来设置分频值,temp是用来设置占空比。结构体里面采用四个进程,第一个进程是用来看当信号clk_in上升沿时候使a1+1,当a1>fpb时候就是a1=0,重新开始。第二个进程一样,只不过是当信号clk_in下降沿时候才使a2+1,这样我们就可以得到两个分频值都为11的两个信号a1和a2。
第三个进程是当信号上升沿并且a1小于temp时候使其ctr1=1(高电平);当信号上升沿并且a1大于temp时候,ctr1=0。因为temp=9,所以当a1为0,1,2,3,4,5,6,7,8时候,ctr1=1;当a1为9,10,11,12,13,14,15,16,17,18时候,ctr1=0。这样我们可以得到其占空比为9/19。
然后我们看第四个进程是当信号下降沿并且a2小于temp时候使其ctr2=1(高电平);当信号下降沿并且a2大于temp时候,ctr2=0。因为temp=9,所以当a2为0,1,2,3,4,5,6,7,8时候,ctr2=1;当a2为9,10,11,12,13,14,15,16,17,18时候,ctr2=0。这样我们可以得到其占空比为9/19。
到现在我们得到了两个占空比都为9/19的信号,但是输出信号量ctr1是根据信号上升沿使其为高电平,而输出信号量ctr2是根据信号下降沿使其为低电平。我们知道一个周期的上升沿和下降沿是相隔半个周期的,所以最后我们将两个信号量进行或运算赋值给clk_out输出,代码为clk_out<=ctr1 or ctr2。这样就可以那半个周期,clk_out信号的输出高电平周期就为9.5,而此时占空比为9.5/19=0.5这样我们就可以得到信号频率为奇数时候,要求其占空比为1/2的分频方法。

好了,三种方法介绍到此!如果有帮助到大家,希望点赞加关注哦。

本人水平有限,上述信息仅供参考,如有错误和不妥之处,请多多指教。
另外创作不易,请勿抄袭,如果有帮助到大家的话希望大家可以点个赞,谢谢~

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

OMGMac

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

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

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

打赏作者

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

抵扣说明:

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

余额充值