我们这次来讲解使用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的分频方法。
好了,三种方法介绍到此!如果有帮助到大家,希望点赞加关注哦。
本人水平有限,上述信息仅供参考,如有错误和不妥之处,请多多指教。
另外创作不易,请勿抄袭,如果有帮助到大家的话希望大家可以点个赞,谢谢~