“集成”人生

集成电路学习心得与个人生活流水

统计

留言簿(1)

链接

阅读排行榜

评论排行榜

三分频VHDL与verilog 实现讨论

  转摘自 www.edacn.net(一个学习IC设计不错的论坛)


LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY feq_sel IS
PORT(clk             : INSTD_LOGIC;
     ena             : INSTD_LOGIC;
reset           : INSTD_LOGIC;

clkout          : out std_logic  
);
END feq_sel;
ARCHITECTURE a OF feq_sel IS

SIGNAL c2 : STD_LOGIc;


begin
process(reset,ena)
begin
   
    if   reset='1' then
       clkout<='0';
        elsif  ena='1' then
   clkout<=c2;
   end if

end process;
process(clk)
 
variable  count : std_logic_vector(7 downto 0);
variable  cnt : std_logic_vector(7 downto 0);
  begin
     IF rising_edge(clk)  THEN
       count:=count+1;
     if count="00000001"  then
      c2<=NOT c2;
           
 elsif count="00000010" then    
      cnt:=cnt+1;    
                 elsif count="00000011"  then
        count:="00000000";
       
   end if;    
   
end if;
IF falling_edge(clk) then
  if cnt="00000001" then--
下降沿的且cnt等于1时候才使c2变化
 c2<=not c2;
 cnt:="00000000";
 end if;
 

end if;

END PROCESS;
end a;
以上是本人抽取的程序,可能还有一些没有改的地方
大体的思路是:(1)、让count记到1 的时候改边一次c2
2)、让count记到2的时候,cnt1,之后当时钟的下降沿来的时候再把c2改变一次
从而实现三分;
实际中遇到问题:编译通过,仿真的时候上述(2)的c2count2时的时钟的上升沿改变了 值而非在时钟的下降沿改变
不知道是为什么?
请高手赐教,本人通宵一夜也没有想出,菜鸟水平,不好意思麻烦大家了!

 

下面这个程序是以前从这儿看到的:

-- 占空比11的通用分频模块
-- by superdsp, 709th Research Institute.
-- Dec-7-2004
-- superdsp@21cn.com

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

entity ClockDiv is
generic (div_size: integer := 24);
port(
 clk : in std_logic;
 rst : in std_logic;
 clkout : out std_logic);
end ClockDiv;

architecture behavioral of ClockDiv is
 signal c1 : integer range 0 to div_size - 1;
 signal c2 : integer range 0 to div_size - 1;
 signal div_even : std_logic;
 signal div_odd : std_logic;
begin

 process(rst, clk)
 begin
   if (rst = '0') then
     c1 <= 0;
   elsif rising_edge(clk) then
     if (c1 = div_size - 1) then
       c1 <= 0;
     else
       c1 <= c1 + 1;
     end if;
   end if;
 end process;

 process(rst, clk)
 begin
   if (rst = '0') then
     c2 <= 0;
   elsif falling_edge(clk) then
     if (c2 = div_size - 1) then
       c2 <= 0;
     else
       c2 <= c2 + 1;
     end if;
   end if;
 end process;

 div_even <= '1' when (c2 >= (div_size + 1) / 2) else '0';
 div_odd <= '1' when ((c2 >= (div_size + 1) / 2) or (c1 >= (div_size + 1) / 2)) else '0';

 clkout <= clk when (div_size = 1) else
           div_even when (div_size / 2 * 2 = div_size) else
           div_odd;

end behavioral;

 

 

 

 

仅在modelsim功能仿真,欢迎仁者见仁,智者见智啊:)
module dclk(a,b,c,clk,reset,i,j);
   input  clk,reset;
   output[1:0] i,j;
   output   a,b,c;
   reg [1:0] i,j;
   reg   a,b,c;
 //2:1  posedge clk  
always @(posedge clk or negedge reset)
   begin
       if (!reset)
          begin
            i<=0;
            a<=0;
          end
       else
     
         begin
           i=i+1;
          case(i)
             1 :   a=1;
             2 :   a=1;
             3 :   a=0;
             default: begin
                         a=1;
                         i=1;
                      end
          endcase
         end  
    end

//2:1  negedge clk
always @(negedge clk or negedge reset)
   begin
       if (!reset)
          begin
            j<=0;
            b<=0;
          end
       else
         begin
           j=j+1;
          case(j)
             1 :   b=1;
             2 :   b=1;
             3 :   b=0;
             default: begin
                         b=1;
                         j=1;
                      end
          endcase
         end
     end
always @(a or b or c)
        begin
         if(!reset)
             c=0;
         else
             c=a&b;
         end

endmodule

 

 

 

测试文件如下:
module test_dclk;
   wire a,b,c;
   wire [1:0] i,j;
   reg   clk;
   reg   reset;
   dclk dut(.a(a),.b(b),.c(c),.clk(clk),.reset(reset),.i(i),.j(j));
always #10 clk=~clk;
initial
      begin
         clk=0;
         reset=1;
    #5   reset=0;
    #10  reset=1;
      end


endmodule

 

 

 

 

always @(posedge clk)    
begin
if(reset==1'b0)
  out <= 0 ;
  cnt  <= 0 ;
else
  if(cnt==2)    
     cnt <= 0 ;
     out<= ~out  ;
  else cnt <= cnt+1;
end  

 

 

搂主的想法是做一个占空比为113分频器
4
楼的是3分频,搂主的不是,不要忘了i=0的情况

 

module s1
(
// {{ALTERA_ARGS_BEGIN}} DO NOT REMOVE THIS LINE!
clkin, clkout, s1, s2
// {{ALTERA_ARGS_END}} DO NOT REMOVE THIS LINE!
);
// Port Declaration

// {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
input clkin;
output clkout, s1, s2;
// {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
wire s1,s2;
reg [1:0] step1, step2;
always @(posedge clkin)
begin
case (step1)
2'b00: step1<=2'b01;
2'b01: step1<=2'b10;
2'b10: step1<=2'b00;
default :step1<=2'b00;
endcase
end

always @(negedge clkin)
begin
case (step2)
2'b00: step2<=2'b01;
2'b01: step2<=2'b10;
2'b10: step2<=2'b00;
default :step2<=2'b00;
endcase
end

assign clkout=step1[1]|step2[1];
assign s1=step1[1];
assign s2=step2[1];

endmodule

testbench:
`timescale 1ns/1ns
module s1_tb;
  reg clk_in;
  wire clk_out,s1, s2;
 
  always #50 clk_in=~clk_in;
     
  initial
     begin


        clk_in=0;
        #1000 $stop;
       
    end
   
  s1 s10(.clkin(clk_in), .clkout(clk_out), .s1(s1), .s2(s2));
endmodule

 

 

楼上这个才是三分频吧!

 

老师让我们做的占空比为11的三分频
module frus3(clk,qout);
output qout;
input  clk;
reg    qout,q1,q2,d,qout1,qout2;

always @(negedge clk)
begin
q1<=~d;
q2<=~q1;
d<=q1&q2;
qout1=q2;
end

always @(posedge clk)
begin

qout2=qout1;
end

always @(qout1 or qout2)
begin
qout=qout1|qout2;
end
endmodule

 

module ddd;
//-----------------------------------------
//testbench
reg    CLOCK;
reg    RESET;

initial
begin
   RESET = 1'b0;
   CLOCK = 1'b0;
   #100 RESET = 1'b1;
   #230 RESET = 1'b0;
end

always #50 CLOCK = !CLOCK;
//--------------------------------------------
//main module
reg         CLK_even;
reg         CLK_odd_n;
wire        CLK;
reg[4:0]    CNT;
reg[4:0]    RATE = 5'd4;//RATE
是分频系数,要几分频就将RATE设为几

always @(posedge CLOCK)
begin
   if(RESET)
       CNT <= 5'b0;
   else
   begin
      if(CNT==RATE-1'b1)
           CNT <= 5'b0;
      else
           CNT <= CNT + 1'b1;
   end
end
//--------------------------
always @(posedge CLOCK)
begin
   if(RESET)CLK_even <= 1'b0;
   else
   begin:even_freq //
偶分频
       if(CNT==((RATE>>>1)-1'b1))
           CLK_even <= 1'b0;
       else if(CNT==RATE-1'b1)
           CLK_even <= 1'b1;
   end
end
//--------------------------
//generate odd_freq clock
always @(negedge CLOCK)
begin
   if(RESET)
       CLK_odd_n <= 1'b0;
   else
       CLK_odd_n <= CLK_even;
end
//-------------------------
assign    CLK = (RATE[0]==1'b1)?(CLK_even|CLK_odd_n):CLK_even;

endmodule

 

我总结的,不是原创,其中三分频是herewangying的功劳


******************************************************************
分频技术几点
******************************************************************
10.1
分频
9
10分频和111分频
因为
(9
×101×11)/(91)10.1
******************************************************************
实例:用于实现N-0.5分频
******************************************************************
begin
-------
异或门
clk <= inclk xor  divide2;            --------inclk(
输入时钟)
-------
N减法计数器
process(clk)
if (clk'event and clk='1') then
   if (count="0000") then
       count <= present-1;           --------outclk(
输出时钟) ,present 预置分频值,即N
       outclk <= '1';
   else
   count <= count-1;
   outclk <= '0';
   end if;
end if ;
end process;
------2
分频器
process(outclk)
begin
 if (outclk'event and outclk='1') then
 divide2 <= not  divide2;
 end if;
end process;

******************************************************************
3
分频实例:
******************************************************************

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY div3 IS
   PORT ( clk_in  :in std_logic;
          clk_out :out std_logic);
END div3;

ARCHITECTURE behav OF div3 IS
   SIGNAL clk1,clk2:std_logic_vector(1 DOWNTO 0);
BEGIN
   PROCESS1:PROCESS(clk_in)
   
   BEGIN                                
       IF clk_in'event AND clk_in='1' THEN
           CASE clk1 is
             WHEN "00" => clk1 <= "01";
             WHEN "01" => clk1 <= "11";
             WHEN "11" => clk1 <= "00";
             WHEN OTHERS => clk1 <= "00";
           END CASE;
       END IF;
   END PROCESS PROCESS1;

    PROCESS2:PROCESS(clk_in)
   BEGIN                                
       IF clk_in'event AND clk_in='0' THEN
           CASE clk2 IS
             WHEN "00" => clk2 <= "01";
             WHEN "01" => clk2 <= "11";
             WHEN "11" => clk2 <= "00";
             WHEN OTHERS => clk2 <= "00";
           END CASE;
       END IF;
   END PROCESS PROCESS2;
   clk_out <= '1' WHEN(clk1 AND clk2)=0
      ELSE  '0';            
END behav;

 

我在网上看到一个3分频器,它的思路如下
1
写一个根据上升沿触发的12的三分频器(低12
2
写一个根据下降沿触发的12的三分频器(低12
3
两个结果与一下就行了,得到占空比11的三分频器

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.std_logic_unsigned.all;

entity div_three is
port(
clk : in STD_LOGIC;
clr : in STD_LOGIC;
count11:out std_logic;
count00:out std_logic;
div3_clk : out STD_LOGIC
   );
end div_three;

architecture rtl of div_three is
signal count3:std_logic_vector(1 downto 0);
signal count2:std_logic_vector(1 downto 0);
signal count1:std_logic;
signal count0:std_logic;
begin
cnt3:process(clk,clr)
begin
if clr='0' then
count3<="00";
elsif clk'event and clk='1' then
if count3="10"then
count3<="00";
else
count3<=count3+'1';
end if;
end if;
end process cnt3;
count0<='1' when count3<="01"else
'0';
cnt2:process(clk,clr)
begin
if clr='0' then
count2<="00";
elsif clk'event and clk='0' then
if count2="10"then
count2<="00";
else
count2<=count2+'1';
end if;
end if;
end process cnt2;
count1<='1' when count2<="01"else
'0';
div3_clk<=count1 and count0;
count11<=count1;
count00<=count0;
-- enter your statements here --

end rtl;

我不理解这两条语句
count0<='1' when count3<="01"else '0';
count1<='1' when count2<="01"else  '0';

从仿真波形看,count3="10"count0='0';count3="00"count3="01"count0='1'
count2="10"count1='0';count2="00"count2="01"count1='1'
这是为什么呢?

这两条语句
count0<='1' when count3<="01"else '0';
count1<='1' when count2<="01"else  '0';
究竟是什么意思呢?

count0<='1' when count3<="01"else '0';
count3小于等于“01”时count01,否则为0,所以你从仿真波形上看就会有当count3="10"count0='0';count3="00"count3="01"count0='1'

 

count11,count00两个输出是为了看count0 count1的波形

 

 

任意整数的分频器
module divide(clkin,out,clkout1,clkout2);
   input clkin;
   output out,clkout1,clkout2;
   reg    clkout1,clkout2;
   reg   [2:0]  value1,value2;

   always @(posedge clkin)
   begin
     if(value1==3'b001)
        begin
        value1=0;
        clkout1=~clkout1;
        end
     else value1=value1+1;
   end
   
   always @(negedge clkin)
   begin
     if(value2==3'b001)
        begin
        value2=0;
        clkout2=~clkout2;
        end
     else value2=value2+1;
   end
   assign  out=clkout1^clkout2;

endmodule

 

下面这个程序是我看到的一个分频器的程序,可是我看了半天不懂它的原理,请高手帮忙啊!源程序如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity p_cnt is
port(clk:in std_logic;
    rst:in std_logic;
    num_set:in std_logic;--
分频比预置使能端
    div_num:in std_logic_vector(3 downto 0);--
分频比预置端分频比为2-15
    div_out:out std_logic
    );
end p_cnt;
architecture beha of p_cnt is
signal num_reg:std_logic_vector(3 downto 0);
signal counter:std_logic_vector(3 downto 0);
signal rising_cp:std_logic;
signal falling_cp:std_logic;
signal pre_out:std_logic;

begin
    process(clk)
    begin
     if(rising_edge(clk))then
       if(num_set='1')then
         if((div_num(3)or div_num(2)or div_num(1))='0')then
              num_reg<="0001";
         else
              num_reg<=div_num+"1111";
         end if;
        end if;
     end if;
    end process;
   
    process(clk)
    begin
    if(rising_edge(clk))then
         if(rst='1'or counter=num_reg)then
            counter<="0000";
            rising_cp<='0';
         elsif(counter='0'&num_reg(3 downto 1))then
            rising_cp<='1';
            counter<=counter+'1';
         else
            counter<=counter+'1';
         end if;
    end if;
    end process;
   
    process(clk)
    begin
      if(falling_edge(clk))then
         if(rising_cp='1')then
            falling_cp<='1';
         else
            falling_cp<='0';
         end if;
      end if;
    end process;

    pre_out<=(not num_reg(0))and falling_cp;
    div_out<=pre_out or rising_cp;

end beha;

 

 

posted on 2005-08-14 22:56 洪七 阅读(3976) 评论(3)  编辑 收藏 引用 所属分类: 技术

评论

# 如何实现同时输出4M时钟的2.4.8.16.32.64.128分频信号 2005-11-21 11:55 wingk

如何实现同时输出4M时钟的2.4.8.16.32.64.128分频信号
多谢:)  回复  更多评论   

# re: 三分频VHDL与verilog 实现讨论 2005-11-21 20:41 洪七

我已好久不做Coding了,你可以直接到www.edacn.net上去问。
也可以去参考 夏宇闻老师写的《verilog数字系统设计教程》那本书。
后面有个CPU的设计,关于时钟产生器这一块,也要讲述!  回复  更多评论   

# re: 三分频VHDL与verilog 实现讨论 2006-07-16 10:51 rangeprofile

设置一个7位计数器,计数器的各位输出的即各分频信号  回复  更多评论   

只有注册用户登录后才能发表评论。