玩命加载中 . . .

SpinalHDL基础-跨时钟域


自定义时钟域

class top extends Module{
    val io = new Bundle {
    val clk_a = in Bool()
    val rst_a_n = in Bool()
    val clk_b = in Bool()
    val rst_b_n = in Bool()
    }
    noIoPrefix()

    //1、创建clockDomain
    val cd_a = ClockDomain(io.clk_a, io.rst_a_n, config = ClockDomainConfig(resetActiveLevel = LOW))
    val cd_b = ClockDomain(io.clk_b, io.rst_b_n, config = ClockDomainConfig(resetActiveLevel = LOW))

    //2、clockDomain a logic
    val cnt_a = cd_a on UInt(8 bits) setAsReg() init 0
    val wr_en_a = cd_a on Bool()
    when(wr_en_a) {
        cnt_a := cnt_a + 1
    }
    val cnt_a_gray = toGray(cnt_a)

    //3、clockDomain b logic
    val cnt_b = cd_b on UInt(8 bits) setAsReg() init 0
    val wr_en_b = cd_b on Bool()
    when(wr_en_b) {
        cnt_b := cnt_b + 1
    }

    //4、clockDomain cross logic
    val cnt_a2b = cd_b on RegNext(cnt_a_gray) init 0 addTag(crossClockDomain)
    val cnt_a2b_sync1 = cd_b on RegNext(cnt_a2b) init 0
    val cnt_a2b_sync2 = cd_b on RegNext(cnt_a2b_sync1) init 0
}
module top (
  input               clk_a,
  input               rst_a_n,
  input               clk_b,
  input               rst_b_n
);

  wire       [7:0]    cnt_a_gray_bits;
  reg        [7:0]    cnt_a;
  wire                wr_en_a;
  wire       [7:0]    cnt_a_gray;
  reg        [7:0]    cnt_b;
  wire                wr_en_b;
  (* async_reg = "true" *) reg        [7:0]    cnt_a2b;
  reg        [7:0]    cnt_a2b_sync1;
  reg        [7:0]    cnt_a2b_sync2;

  assign cnt_a_gray_bits = (cnt_a >>> 1'b1);
  assign cnt_a_gray = (cnt_a_gray_bits ^ cnt_a);
  always @(posedge clk_a or negedge rst_a_n) begin
    if(!rst_a_n) begin
      cnt_a <= 8'h0;
    end else begin
      if(wr_en_a) begin
        cnt_a <= (cnt_a + 8'h01);
      end
    end
  end

  always @(posedge clk_b or negedge rst_b_n) begin
    if(!rst_b_n) begin
      cnt_b <= 8'h0;
      cnt_a2b <= 8'h0;
      cnt_a2b_sync1 <= 8'h0;
      cnt_a2b_sync2 <= 8'h0;
    end else begin
      if(wr_en_b) begin
        cnt_b <= (cnt_b + 8'h01);
      end
      cnt_a2b <= cnt_a_gray;
      cnt_a2b_sync1 <= cnt_a2b;
      cnt_a2b_sync2 <= cnt_a2b_sync1;
    end
  end


endmodule

ClockingArea

class top extends Module{
    val io = new Bundle {
    val clk_a = in Bool()
    val rst_a_n = in Bool()
    val clk_b = in Bool()
    val rst_b_n = in Bool()
    }
    noIoPrefix()

    //1、创建clockDomain
    val cd_a = ClockDomain(io.clk_a, io.rst_a_n, config = ClockDomainConfig(resetActiveLevel = LOW))
    val cd_b = ClockDomain(io.clk_b, io.rst_b_n, config = ClockDomainConfig(resetActiveLevel = LOW))

    //2、clockDomain a logic
    val a = new ClockingArea(cd_a) {
    val cnt = UInt(8 bits) setAsReg() init 0
    val wr_en = Bool()
    when(wr_en) {
      cnt := cnt + 1
    }
    val cnt_gray = toGray(cnt)
    }

    //3、clockDomain b logic
    val b =  new ClockingArea(cd_b) {
        val cnt = UInt(8 bits) setAsReg() init 0
        val wr_en = Bool()
        when(wr_en) {
            cnt := cnt + 1
        }

        //4、clockDomain cross logic
        val cnt_sync = RegNext(a.cnt_gray) init 0 addTag (crossClockDomain)
        val cnt_sync1 = RegNext(cnt_sync) init 0
        val cnt_sync2 = RegNext(cnt_sync1) init 0
    }
}
module top (
  input               clk_a,
  input               rst_a_n,
  input               clk_b,
  input               rst_b_n
);

  wire       [7:0]    a_cnt_gray_bits;
  reg        [7:0]    a_cnt;
  wire                a_wr_en;
  wire       [7:0]    a_cnt_gray;
  reg        [7:0]    b_cnt;
  wire                b_wr_en;
  (* async_reg = "true" *) reg        [7:0]    b_cnt_sync;
  reg        [7:0]    b_cnt_sync1;
  reg        [7:0]    b_cnt_sync2;

  assign a_cnt_gray_bits = (a_cnt >>> 1'b1);
  assign a_cnt_gray = (a_cnt_gray_bits ^ a_cnt);
  always @(posedge clk_a or negedge rst_a_n) begin
    if(!rst_a_n) begin
      a_cnt <= 8'h0;
    end else begin
      if(a_wr_en) begin
        a_cnt <= (a_cnt + 8'h01);
      end
    end
  end

  always @(posedge clk_b or negedge rst_b_n) begin
    if(!rst_b_n) begin
      b_cnt <= 8'h0;
      b_cnt_sync <= 8'h0;
      b_cnt_sync1 <= 8'h0;
      b_cnt_sync2 <= 8'h0;
    end else begin
      if(b_wr_en) begin
        b_cnt <= (b_cnt + 8'h01);
      end
      b_cnt_sync <= a_cnt_gray;
      b_cnt_sync1 <= b_cnt_sync;
      b_cnt_sync2 <= b_cnt_sync1;
    end
  end


endmodule

本文作者: 董续胜

本文链接: https://dxsm.github.io/p/spinalhdl-clockdomain.html

版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0许可协议。转载请注明出处!


 评论