risc-v中文社区

 找回密码
 立即注册
查看: 1415|回复: 1

[原创] chisel 异步且低电平复位

[复制链接]

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2021-10-8 22:47:45 | 显示全部楼层 |阅读模式
chisel3.2中默认的时钟和复位都是上拉有效,且复位是同步复位,有时候需要用异步复位,要想用异步复位,一般做法是extends MultiIOModule或RawModule,然后再用withReset(reset.asAsyncReset){具体逻辑块},当然,如果是想用下降沿复位,则withReset((~reset.asUInt()).asBool().asAsyncReset){...},实验代码如下:
/**
  * @Author Joe_Liang
  * @Date 2021/10/8 15:55
  * @Version 1.0
  */
import chisel3._
import chisel3.util._

class AsyncResetOddFreq(val N:Int) extends MultiIOModule {
  val io = IO(new Bundle{
    val clk_div = Output(Bool())
  })
  require(N>1 && (N % 2 == 1),"N必须大于1且N是奇数")
  withReset((~reset.asUInt()).asBool().asAsyncReset()) {  //查看verilog发现全部是异步复位
    val cnt = RegInit(0.U(log2Ceil(N).W)) //计数范围0~N-1
    val cnt1 = RegInit(0.U(log2Ceil(N).W)) //计数器cnt1在时钟上升沿加1,cnt1计数值为0到N/2时clk_div_pos为0,cnt1计数值为N/2+1到N-1时clk_div_pos为1
    val clk_div_pos = RegInit(false.B)
    val cnt2wire = Wire(UInt(log2Ceil(N).W)) //用wire连接withClock块中的信号,纯粹满足语法作用, 要不然不能在块外引用块内信号
    val clk_div_neg_wire = Wire(UInt(1.W))//同上
   
    withClock((~clock.asUInt()).asBool().asClock()){ //默认用时钟上升沿和高有效复位,此处用时钟下降沿,复位还是高有效
      val cnt2 = RegInit(0.U(log2Ceil(N).W)) //cnt2计数器也在时钟下降沿加1,cnt2计数值为0到N/2时clk_div_neg为0,cnt2计数值为N/2+1到N-1时clk_div_neg为1
    val clk_div_neg = RegInit(false.B)
      when(cnt2 === (N-1).U) {
        cnt2 := 0.U
      }.otherwise{
        cnt2 := cnt2 + 1.U
      }
      cnt2wire := cnt2
      clk_div_neg_wire := clk_div_neg
      when(cnt2 < (N/2).U) {
        clk_div_neg := false.B
      }.otherwise {
        clk_div_neg := true.B
      }
    }
    when(cnt === (N-1).U) {
      cnt := 0.U
    }.otherwise{
      cnt := cnt + 1.U
    }
    when(cnt1 === (N-1).U) {
      cnt1 := 0.U
    }.otherwise{
      cnt1 := cnt1 + 1.U
    }
    when(cnt1 < (N/2).U) {
      clk_div_pos := false.B
    }.otherwise {
      clk_div_pos := true.B
    }

    io.clk_div := clk_div_pos | clk_div_neg_wire
  }

}
回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
 楼主| 发表于 2021-10-8 22:49:56 | 显示全部楼层
生成的verilog如下 :
module AsyncResetOddFreq(
  input   clock,
  input   reset,
  output  io_clk_div
);
  wire _T_2 = ~reset; // @[AsyncResetOddFreq.scala 16:52]
  reg [1:0] _T_4; // @[AsyncResetOddFreq.scala 18:23]
  reg [31:0] _RAND_0;
  reg  _T_5; // @[AsyncResetOddFreq.scala 19:30]
  reg [31:0] _RAND_1;
  wire  _T_11 = ~clock; // @[AsyncResetOddFreq.scala 23:49]
  reg [1:0] _T_12; // @[AsyncResetOddFreq.scala 24:25]
  reg [31:0] _RAND_2;
  reg  _T_13; // @[AsyncResetOddFreq.scala 25:30]
  reg [31:0] _RAND_3;
  wire  _T_14 = _T_12 == 2'h2; // @[AsyncResetOddFreq.scala 26:17]
  wire [1:0] _T_16 = _T_12 + 2'h1; // @[AsyncResetOddFreq.scala 29:22]
  wire  _T_17 = _T_12 < 2'h1; // @[AsyncResetOddFreq.scala 33:17]
  wire  _T_21 = _T_4 == 2'h2; // @[AsyncResetOddFreq.scala 44:15]
  wire [1:0] _T_23 = _T_4 + 2'h1; // @[AsyncResetOddFreq.scala 47:20]
  wire  _T_24 = _T_4 < 2'h1; // @[AsyncResetOddFreq.scala 49:15]
  assign io_clk_div = _T_5 | _T_13; // @[AsyncResetOddFreq.scala 55:16]
`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}};
  _T_4 = _RAND_0[1:0];
  `endif // RANDOMIZE_REG_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_1 = {1{`RANDOM}};
  _T_5 = _RAND_1[0:0];
  `endif // RANDOMIZE_REG_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_2 = {1{`RANDOM}};
  _T_12 = _RAND_2[1:0];
  `endif // RANDOMIZE_REG_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_3 = {1{`RANDOM}};
  _T_13 = _RAND_3[0:0];
  `endif // RANDOMIZE_REG_INIT
  if (_T_2) begin
    _T_4 = 2'h0;
  end
  if (_T_2) begin
    _T_5 = 1'h0;
  end
  if (_T_2) begin
    _T_12 = 2'h0;
  end
  if (_T_2) begin
    _T_13 = 1'h0;
  end
  `endif // RANDOMIZE
end // initial
`endif // SYNTHESIS
  always @(posedge clock or posedge _T_2) begin
    if (_T_2) begin
      _T_4 <= 2'h0;
    end else if (_T_21) begin
      _T_4 <= 2'h0;
    end else begin
      _T_4 <= _T_23;
    end
  end
  always @(posedge clock or posedge _T_2) begin
    if (_T_2) begin
      _T_5 <= 1'h0;
    end else if (_T_24) begin
      _T_5 <= 1'h0;
    end else begin
      _T_5 <= 1'h1;
    end
  end
  always @(posedge _T_11 or posedge _T_2) begin
    if (_T_2) begin
      _T_12 <= 2'h0;
    end else if (_T_14) begin
      _T_12 <= 2'h0;
    end else begin
      _T_12 <= _T_16;
    end
  end
  always @(posedge _T_11 or posedge _T_2) begin
    if (_T_2) begin
      _T_13 <= 1'h0;
    end else if (_T_17) begin
      _T_13 <= 1'h0;
    end else begin
      _T_13 <= 1'h1;
    end
  end
endmodule


回复

使用道具 举报

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

本版积分规则



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

GMT+8, 2024-5-5 11:11 , Processed in 0.017451 second(s), 17 queries .

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

Copyright © 2018-2021, risc-v open source

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