请选择 进入手机版 | 继续访问电脑版

risc-v中文社区

 找回密码
 立即注册
查看: 1636|回复: 2

[原创] chisel分频器(1)---偶分频

  [复制链接]

345

主题

562

帖子

2145

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2145
发表于 2021-10-5 15:58:46 | 显示全部楼层 |阅读模式
假设原时钟是clk,分频之后的输出时钟为clk_div,clk是clk_div频率的N倍且N为偶数
以2分频画时序图如下:


计数器的计数范围为0到(N/2)-1,当计数到(N/2)-1之后复位,同时将clk_div反转。
因有同步和异步复位电路,在此以同步复位为例:
import chisel3.util._
class EvenFreq(val N:Int) extends Module{ //偶分频
  val io = IO(new Bundle {
    val clk_div = Output(Bool())
  })
  require(N>0 && (N%2 ==0),"N必须要大于0且为偶数")
  val cntReg = RegInit(0.U(log2Ceil(N).W))
  val outReg = RegInit(false.B)
  io.clk_div := outReg
when(cntReg === ((N/2)-1).U) {
    cntReg := 0.U
    outReg := ~outReg
}.otherwise {
    cntReg := cntReg + 1.U
  }
}
用2分频来实验:
Driver.execute(Array("--target-dir","generated"),()=>new EvenFreq(2))


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

345

主题

562

帖子

2145

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2145
 楼主| 发表于 2021-10-5 16:00:08 | 显示全部楼层
产生的verilog文件内容如下:
module EvenFreq(
  input   clock,
  input   reset,
  output  io_clk_div
);
  reg  cntReg; // @[EvenFreq.scala 15:23]
  reg [31:0] _RAND_0;
  reg  outReg; // @[EvenFreq.scala 16:23]
  reg [31:0] _RAND_1;
  wire  _T = ~cntReg; // @[EvenFreq.scala 19:15]
  wire  _T_1 = ~outReg; // @[EvenFreq.scala 21:15]
  wire  _T_3 = cntReg + 1'h1; // @[EvenFreq.scala 23:22]
  assign io_clk_div = outReg; // @[EvenFreq.scala 17:14]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INIT
  integer initvar;
`endif
`ifndef SYNTHESIS
initial begin
  `ifdef RANDOMIZE
    `ifdef INIT_RANDOM
      `INIT_RANDOM
    `endif
    `ifndef VERILATOR
      `ifdef RANDOMIZE_DELAY
        #`RANDOMIZE_DELAY begin end
      `else
        #0.002 begin end
      `endif
    `endif
  `ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{`RANDOM}};
  cntReg = _RAND_0[0:0];
  `endif // RANDOMIZE_REG_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_1 = {1{`RANDOM}};
  outReg = _RAND_1[0:0];
  `endif // RANDOMIZE_REG_INIT
  `endif // RANDOMIZE
end // initial
`endif // SYNTHESIS
  always @(posedge clock) begin
    if (reset) begin
      cntReg <= 1'h0;
    end else if (_T) begin
      cntReg <= 1'h0;
    end else begin
      cntReg <= _T_3;
    end
    if (reset) begin
      outReg <= 1'h0;
    end else if (_T) begin
      outReg <= _T_1;
    end
  end
endmodule
回复

使用道具 举报

345

主题

562

帖子

2145

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2145
 楼主| 发表于 2021-10-9 14:04:12 | 显示全部楼层
偶分频50%占空比,还可以采用最高bit位输出法:
/**
  * @Author Joe_Liang
  * @Date 2021/10/9 14:02
  * @Version 1.0
  */
import chisel3._
import chisel3.util._
class MSBDivFreq(val N:Int) extends Module{
  val io = IO(new Bundle{
    val clk_div = Output(Bool())
  })
  require(N>1,"N必须大于1")
  withReset(reset.asAsyncReset()) {
    val cnt = RegInit(0.U(log2Ceil(N).W)) //计数范围0~N-1
    when(cnt === (N-1).U) {
      cnt := 0.U
    }.otherwise {
      cnt := cnt + 1.U
    }
    io.clk_div := cnt(log2Ceil(N) - 1) //最高bit位
  }
}
举例分析:
最大计数长度为8的计数器即从0计数到7,需要的bit位数是log2Ceil(8)=3,最高位为bit(2)
000~011                100~111 对于bit(2)来说,前四个时钟周期0,后四个周期为1,但计数器值判断时用cnt === (8-1).U则cnt := 0.U,输出始终是out:=cnt(2),
                                这样前四个时钟000~011输出为0,后四个时钟100~111输出为1,占空比为50%的输出
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



Archiver|手机版|小黑屋|risc-v中文社区

GMT+8, 2023-12-2 03:48 , Processed in 0.014771 second(s), 18 queries .

risc-v中文社区论坛 官方网站

Copyright © 2018-2021, risc-v open source

快速回复 返回顶部 返回列表