牛客网Verilog刷题——VL48
- 题目
- 答案
题目
在data_en为高期间,data_in将保持不变,data_en为高至少保持3个B时钟周期。表明,当data_en为高时,可将数据进行同步。本题中data_in端数据变化频率很低,相邻两个数据间的变化,至少间隔10个B时钟周期。
电路的接口如下图所示:
端口说明如下表所示:
本题考察的就是多比特跨时钟域处理,但是题目中没有指出是快时钟域到慢时钟域还是慢时钟域到快时钟域,只是明确指出data_en至少保持3个clk_b时钟周期,data_in至少保持10个clk_b时钟周期,也就是说,时钟域clk_a下的信号同步到时钟域clk_b下,在clk_b的上升沿处,肯定能被采集到,不会出现像我们常见的快时钟域到慢时钟域处理中,出现的慢时钟域采集不到快时钟域信号的情况,所以本题只需要简单的将单比特的使能信号进行跨时钟域处理后,再作为多比特跨时钟域处理打拍中的使能信号即可。
答案
module mux(
input clk_a ,
input clk_b ,
input arstn ,
input brstn ,
input [3:0] data_in ,
input data_en ,
output reg [3:0] dataout
);
reg [3:0] data_reg; //输入数据打拍(时钟域clk_a)
reg data_en_reg_a; //输入使能信号打拍(时钟域clk_a)
reg data_en_reg1_b, data_en_reg2_b; //打两拍跨时钟域处理(时钟域clk_b)
//输入数据在clk_a时钟域下打一拍,消除毛刺
always@(posedge clk_a or negedge arstn) begin
if(~arstn)
data_reg <= 0;
else
data_reg <= data_in;
end
//使能信号在clk_a时钟域下打一拍,消除毛刺
always@(posedge clk_a or negedge arstn) begin
if(~arstn)
data_en_reg_a <= 0;
else
data_en_reg_a <= data_en;
end
//时钟域clk_a下使能信号同步到时钟域clk_b下(打两拍,防止亚稳态)
always@(posedge clk_b or negedge brstn) begin
if(~brstn) begin
data_en_reg1_b <= 0;
data_en_reg2_b <= 0;
end
else begin
data_en_reg1_b <= data_en_reg_a;
data_en_reg2_b <= data_en_reg1_b;
end
end
//时钟域clk_b下,根据同步后的使能信号进行取值
always@(posedge clk_b or negedge brstn) begin
if(~brstn)
dataout <= 0;
else
dataout <= data_en_reg2_b? data_reg: dataout;
end
endmodule