跨时钟域信号处理
2017-01-30 14:58
351 查看
一、慢速多周期信号
Signal-in为clkA时钟域多周期信号。此时只需要用clkB打两拍即可。
module Signal_CrossDomain( input rst_p; input clkA, // we actually don't need clkA in that example, but it is here for completeness as we'll need it in further examples input SignalIn_clkA, input clkB, output SignalOut_clkB ); // We use a two-stages shift-register to synchronize SignalIn_clkA to the clkB clock domain reg [1:0] SyncA_clkB; always @(posedge clkB) begin if(rst_p == 1'b1) SyncA_clkB[0] <= 1'b0; else SyncA_clkB[0] <= SignalIn_clkA; // notice that we use clkB end always @(posedge clkB) begin if(rst_p == 1'b1) SyncA_clkB[1] <= 1'b0; else SyncA_clkB[1] <= SyncA_clkB[0]; // notice that we use clkB end assign SignalOut_clkB = SyncA_clkB[1]; // new signal synchronized to (=ready to be used in) clkB domain endmodule
二、单周期信号
FlagIn(代码里表示为FlagIn_clkA)此时为clkA时钟域产生的单周期信号。
module Flag_CrossDomain( input rst_p; input clkA, input FlagIn_clkA, // this is a one-clock pulse from the clkA domain input clkB, output FlagOut_clkB // from which we generate a one-clock pulse in clkB domain ); reg FlagToggle_clkA = 1'b0; reg [2:0] SyncA_clkB = 3'b000; always @(posedge clkA) bein if(rst_p == 1'b1) FlagToggle_clkA <= 1'b0; else FlagToggle_clkA <= FlagToggle_clkA ^ FlagIn_clkA; // when flag is asserted, this signal toggles (clkA domain) end always @(posedge clkB) begin if(rst_p == 1'b1) SyncA_clkB <= 3'b000; else SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA}; // now we cross the clock domains end assign FlagOut_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]); // and create the clkB flag
如果clkA端需要知道clkB端是否接收到了信号,可以添加一个busy信号
module Flag_CrossDomain( input rst_p, input clkA, input FlagIn_clkA, // this is a one-clock pulse from the clkA domain output Busy_clkA, input clkB, output FlagOut_clkB // from which we generate a one-clock pulse in clkB domain ); reg FlagToggle_clkA; reg [2:0] SyncA_clkB; reg [1:0] SyncB_clkA; always @(posedge clkA)begin if(rst_p == 1'b1) FlagToggle_clkA <= 1'b0; else FlagToggle_clkA <= FlagToggle_clkA ^ (FlagIn_clkA & ~Busy_clkA); end always @(posedge clkB)begin if(rst_p == 1'b1) SyncA_clkB <= 3'b000; else SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA}; end always @(posedge clkA)begin if(rst_p == 1'b1) SyncB_clkA <= 2'b00; else SyncB_clkA <= {SyncB_clkA[0], SyncA_clkB[2]}; end assign FlagOut_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]); assign Busy_clkA = FlagToggle_clkA ^ SyncB_clkA[1]; endmodule
三、Task
如果clkA时钟域中有一个任务需要在clkB时钟域完成,可以遵循以下设计module TaskAck_CrossDomain( input clkA, input TaskStart_clkA, output TaskBusy_clkA, TaskDone_clkA, input clkB, output TaskStart_clkB, TaskBusy_clkB, input TaskDone_clkB ); reg FlagToggle_clkA, FlagToggle_clkB, Busyhold_clkB; reg [2:0] SyncA_clkB, SyncB_clkA; always @(posedge clkA) FlagToggle_clkA <= FlagToggle_clkA ^ (TaskStart_clkA & ~TaskBusy_clkA); always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA}; assign TaskStart_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]); assign TaskBusy_clkB = TaskStart_clkB | Busyhold_clkB; always @(posedge clkB) Busyhold_clkB <= ~TaskDone_clkB & TaskBusy_clkB; always @(posedge clkB) if(TaskBusy_clkB & TaskDone_clkB) FlagToggle_clkB <= FlagToggle_clkA; always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[1:0], FlagToggle_clkB}; assign TaskBusy_clkA = FlagToggle_clkA ^ SyncB_clkA[2]; assign TaskDone_clkA = SyncB_clkA[2] ^ SyncB_clkA[1]; endmodule
相关文章推荐
- 跨时钟域信号处理
- 基于FPGA的跨时钟域信号处理——MCU
- IC设计基础系列之CDC篇4:跨时钟域信号如何处理(来自百度经验)
- 基于FPGA的跨时钟域信号处理——专用握手信号
- IC设计基础系列之CDC篇5:跨时钟域信号处理 (发起请求信号和回传确定信号,有状态图,有代码)
- 基于FPGA的跨时钟域信号处理——专用握手信号
- FPGA中跨时钟域的信号处理--异步FI…
- 基于FPGA的跨时钟域信号处理——专用握手信号
- Linux信号处理与时钟
- 基于FPGA的跨时钟域信号处理——专用握手信号
- 基于FPGA的跨时钟域信号处理——同步设计的重要
- 基于FPGA的跨时钟域信号处理——同步设计的重要
- 跨时钟域信号处理——专用握手信号
- 基于FPGA的跨时钟域信号处理——专用握手信号
- 基于FPGA的跨时钟域信号处理——借助存储器
- 基于FPGA的跨时钟域信号处理——借助存储器
- 巧用QSignalMapper分类有序地处理大量信号
- Python signal 信号处理模块
- Linux信号处理的一般方法
- Linux 信号signal处理机制