参考:(详解)BUFG,IBUFG,BUFGP,IBUFGDS等含义以及使用 - 知乎

FPGA资源介绍——时钟资源(二)_fpga时钟资源-CSDN博客

1,BUFGCE

带有时钟使能端的全局缓冲。它有一个输入I、一个使能端CE和一个输出端O。只有当BUFGCE的使能端CE有效(高电平)时,BUFGCE才有输出。

作用:防止竞争冒险现象

使用方法

vlg_design

/
//FPGA系统时钟100MHz
//系统每秒进行一次数据的采集与处理,每次维持10ms,其余时间空闲
//希望系统空闲时,关闭100MHz的工作时钟
//使用BUFGCE原语实现此功能
 
/
`timescale 1ns/1ps
module vlg_design(
    input clk,//100M
    input rest_n,
    output reg clk_10ms_en,
    output reg o_clk_out_1, //自己产生是能
    output  o_clk_out_2 // 使用原语
    );
    
`define Debug 
`ifdef  Debug
localparam CNT_1S_MAX             =  1_000_000 -1 ;  //10ms
localparam CNT_10MS_MAX         =  1_000    -1;   //10us
`else
localparam CNT_1S_MAX             =  100_000_000  -1  ;//1s
localparam CNT_10MS_MAX         =  1_000_000  -1    ; //10ms
`endif

reg [27:0]r_cnt_10ms;   
wire  r_clk_out_1;
wire  r_clk_out_2;
 
 //产生1s的计数
 always @(posedge clk) begin
    if(!rest_n) r_cnt_10ms <='b0;
    else if (r_cnt_10ms < CNT_1S_MAX)  
              r_cnt_10ms <= r_cnt_10ms + 1'b1;
         else r_cnt_10ms <='b0;  
 end 
 
 //10ms以下是能
always @(posedge clk) begin
    if(!rest_n)    clk_10ms_en <='b0;
    else if(r_cnt_10ms <= CNT_10MS_MAX) clk_10ms_en <=1'b1;
        else clk_10ms_en <='b0;
end    
    
 //10ms以下clk_out_1 按clk 输出
 always @(*) begin
    if(!rest_n) o_clk_out_1 <='b0;
    else if(clk_10ms_en) 
         o_clk_out_1 <= clk ;
         else o_clk_out_1 <= 'b0;
end 
 
 
//使用原语例化代码
   BUFGCE BUFGCE_inst (
      .O(r_clk_out_2),   // 1-bit output: Clock output
      .CE(clk_10ms_en), // 1-bit input: Clock enable input for I0
      .I(clk)    // 1-bit input: Primary clock
   );

assign o_clk_out_2 = r_clk_out_2;


endmodule

testbench_top


`timescale 1ns/1ps
module testbench_top();
    

//参数定义

`define CLK_PERIORD        10        //时钟周期设置为10ns(100MHz)    


//接口申明
    

reg clk;
reg rest_n;
wire clk_10ms_en;
wire o_clk_out_1;
wire o_clk_out_2;
 
 
    
vlg_design        uut_vlg_design(
    .clk(clk),
    .rest_n(rest_n),
    .clk_10ms_en(clk_10ms_en),
    .o_clk_out_1(o_clk_out_1),
    .o_clk_out_2(o_clk_out_2)
    );    
    
//时钟和复位初始化、复位产生 
initial begin
clk <= 0;
rest_n <= 0;
#10;
rest_n <= 1;
end

//时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;    
    
 
//测试激励产生
initial begin

    @(posedge rest_n);    //等待复位完成
    @(posedge clk);
    #1_000_000_000;
    #1_000_000_000;
    $stop;
end

endmodule







仿真结果输出

对比发现:使用自己产生的是能造成了竞争冒险

2,BUFGMUX

BUFGMUX

全局时钟选择缓冲,它有I0和I1两个输入,一个控制端S,一个输出端O。当S为低电平时输出时钟为I0,反之为I1。需要指出的是BUFGMUX的应用十分灵活,I0和I1两个输入时钟甚至可以为异步关系。

作用:

BUFGMUX的主要作用包括:

  1. 数据缓冲:BUFGMUX可以管理输入和输出缓冲区,用于存储待传输的数据。它提供了读写操作,以便在缓冲区中存储和检索数据。
  2. 间隙管理:在高速数据传输中,数据传输速率可能不匹配,导致接收方无法立即处理所有接收到的数据。BUFGMUX可以管理这些间隙,通过插入空闲周期或等待周期来匹配发送和接收之间的速率。
  3. 流量控制:BUFGMUX可以与上层协议(如PCIe、Ethernet等)进行通信,以实现流量控制。它可以根据接收方的处理能力来调整发送速率,以避免接收方过载。

此外,BUFGMUX还可以用于构建文件存储和分发服务,实现文件共享功能,并作为应用开发的基础组件,帮助开发者快速构建文件存储功能等。

使用方法

vlg_design

/
/*FPGA系统时钟100MHz
FPGA系统快速时钟100MHz,慢速时钟1MHz
系统每秒进行一次数据的采集与处理,每次维持10ms,其余时间空闲
数据采集与处理时,FPGA工作在100MHz快时钟(10ms/s)
系统空闲时, FPGA工作在1MHz慢时钟(990ms/s)
使用Xilinx BUFGMUX原语实现此功能
编写Verilog代码
编写测试脚本,搭建仿真平台
运行仿真,查看波形

 */
/
`timescale 1ns/1ps
module vlg_design(
    input clk_in1,//100M
    input clk_in2,//1M
    input rest_n,
    output reg clk_10ms_en,
    output reg o_clk_out_1, //自己产生是能
    output  o_clk_out_2 // 使用原语
    );
    
`define Debug 
`ifdef  Debug
localparam CNT_1S_MAX             =  1_000_000 -1 ;  //10ms
localparam CNT_10MS_MAX         =  1_000    -1;   //10us
`else
localparam CNT_1S_MAX             =  100_000_000  -1  ;//1s
localparam CNT_10MS_MAX         =  1_000_000  -1    ; //10ms
`endif

reg [27:0]r_cnt_10ms;   
wire  r_clk_out_1;
wire  r_clk_out_2;
 
 //产生1s的计数
 always @(posedge clk_in1) begin
    if(!rest_n) r_cnt_10ms <='b0;
    else if (r_cnt_10ms < CNT_1S_MAX)  
              r_cnt_10ms <= r_cnt_10ms + 1'b1;
         else r_cnt_10ms <='b0;  
 end 
 
 //10ms以下是能
always @(posedge clk_in1) begin
    if(!rest_n)    clk_10ms_en <='b0;
    else if(r_cnt_10ms <= CNT_10MS_MAX) clk_10ms_en <=1'b1;
        else clk_10ms_en <='b0;
end    
    
 //10ms以下clk_out_1 按clk 输出
 always @(*) begin
    if(!rest_n) o_clk_out_1 <='b0;
    else if(clk_10ms_en) 
         o_clk_out_1 <= clk_in1 ;
         else o_clk_out_1 <= clk_in2;
end 
 
 
 
//使用原语例化代码
   BUFGMUX    BUFGMUX_inst (
      .O(o_clk_out_2),   // 1-bit output: Clock output
      .I0(clk_in2), // 1-bit input: Clock input (S=0) 低脉冲
      .I1(clk_in1), // 1-bit input: Clock input (S=1) 高脉冲
      .S(clk_10ms_en)    // 1-bit input: Clock select
   );

 


endmodule

testbench_top


`timescale 1ns/1ps
module testbench_top();
    

//参数定义

`define CLK_PERIORD        10        //时钟周期设置为10ns(100MHz)    


//接口申明
    
reg clk_in1;
reg clk_in2;
reg rest_n;
wire clk_10ms_en;
wire o_clk_out_1;
wire o_clk_out_2;
 
 
    
vlg_design        uut_vlg_design(
    .clk_in1(clk_in1),
    .clk_in2(clk_in2),
    .rest_n(rest_n),
    .clk_10ms_en(clk_10ms_en),
    .o_clk_out_1(o_clk_out_1),
    .o_clk_out_2(o_clk_out_2)
    );    
    
//时钟和复位初始化、复位产生 
initial begin
clk_in1 <= 0;
clk_in2 <= 0;
rest_n <= 0;
#10;
rest_n <= 1;
clk_in1 <= 1;
clk_in2 <= 1;
end

//时钟产生
always #(`CLK_PERIORD/2) clk_in1 = ~clk_in1;    
always #(`CLK_PERIORD*100/2) clk_in2 = ~clk_in2;    
    
 
//测试激励产生
initial begin

    @(posedge rest_n);    //等待复位完成
    @(posedge clk_in1);
    #1_000_000_000;
    #1_000_000_000;
    $stop;
end

endmodule

仿真结果输出

问题

使用原语例化的时候,

en=1,out 没有立刻等于in1.而是多等了半个in2 时钟

en =0时,out也没有立刻等于in2,而是多等了半个in1时钟

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐