自定义时钟域
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许可协议。转载请注明出处!