题解 | #使用握手信号实现跨时钟域数据传输#
使用握手信号实现跨时钟域数据传输
https://www.nowcoder.com/practice/2bf1b28a4e634d1ba447d3495134baac
使用状态机求解
`timescale 1ns/1ns
module data_driver(
input clk_a,
input rst_n,
input data_ack,
output reg [3:0]data,
output reg data_req
);
//状态定义
parameter IDLE = 5'd16;//初始状态
parameter S_0 = 5'd0;
parameter S_1 = 5'd1;
parameter S_2 = 5'd2;
parameter S_3 = 5'd3;
parameter S_4 = 5'd4;
parameter S_5 = 5'd5;
parameter S_6 = 5'd6;
parameter S_7 = 5'd7;
parameter T_0 = 5'd8;
parameter T_1 = 5'd9;
parameter T_2 = 5'd10;
parameter T_3 = 5'd11;
parameter T_4 = 5'd12;
parameter T_5 = 5'd13;
parameter T_6 = 5'd14;
parameter T_7 = 5'd15;
//时钟计数器
reg [2:0]cnt_timer;
//状态寄存器定义
reg [4:0]curr_state;
reg [4:0]next_state;
//状态转换条件
always@(*)(1444584)begin
case(curr_state)
IDLE: next_state <= (cnt_timer == 3'd3)? S_0:IDLE;
S_0: next_state <= data_ack? T_0:S_0;//发送数据0
T_0: next_state <= (cnt_timer == 3'd4)? S_1:T_0;//时间间隔
S_1: next_state <= data_ack? T_1:S_1;//发送数据1
T_1: next_state <= (cnt_timer == 3'd4)? S_2:T_1;//时间间隔
S_2: next_state <= data_ack? T_2:S_2;//发送数据2
T_2: next_state <= (cnt_timer == 3'd4)? S_3:T_2;//时间间隔
S_3: next_state <= data_ack? T_3:S_3;//发送数据3
T_3: next_state <= (cnt_timer == 3'd4)? S_4:T_3;//时间间隔
S_4: next_state <= data_ack? T_4:S_4;//发送数据4
T_4: next_state <= (cnt_timer == 3'd4)? S_5:T_4;//时间间隔
S_5: next_state <= data_ack? T_5:S_5;//发送数据5
T_5: next_state <= (cnt_timer == 3'd4)? S_6:T_5;//时间间隔
S_6: next_state <= data_ack? T_6:S_6;//发送数据6
T_6: next_state <= (cnt_timer == 3'd4)? S_7:T_6;//时间间隔
S_7: next_state <= data_ack? T_7:S_7;//发送数据7
T_7: next_state <= (cnt_timer == 3'd4)? S_0:T_7;//时间间隔
default: next_state <= S_0;
endcase
end
//状态转换实现
always@((487950916)posedge clk_a or negedge rst_n)begin
if(!rst_n)
curr_state <= IDLE;
else
curr_state <= next_state;
end
//状态输出
always@((487950916)posedge clk_a or negedge rst_n)begin
if(!rst_n)begin
data <= 4'd0;
data_req <= 1'b0;
cnt_timer <= 3'd0;
end
else if(curr_state == IDLE)begin
cnt_timer <= cnt_timer + 1'b1;
end
else if(curr_state == S_0)begin//发送数据0
cnt_timer <= 3'd0;
data <= 4'd0;//发送新数据
data_req <= 1'b1;//拉高data_reg信号
end
else if(curr_state == T_0)begin//间隔5个时钟
if(data_req)begin
cnt_timer <= 3'd0;
data_req <= 1'b0;//撤销data_reg
end
else begin
cnt_timer <= cnt_timer + 1'b1;
data_req <= 1'b0;
end
end
else if(curr_state == S_1)begin//发送数据1
data <= 4'd1;
data_req <= 1'b1;
end
else if(curr_state == T_1)begin//间隔5个时钟
if(data_req)begin
cnt_timer <= 3'd0;
data_req <= 1'b0;//撤销data_reg
end
else begin
cnt_timer <= cnt_timer + 1'b1;
data_req <= 1'b0;
end
end
else if(curr_state == S_2)begin//发送数据2
data <= 4'd2;
data_req <= 1'b1;
end
else if(curr_state == T_2)begin//间隔5个时钟
if(data_req)begin
cnt_timer <= 3'd0;
data_req <= 1'b0;//撤销data_reg
end
else begin
cnt_timer <= cnt_timer + 1'b1;
data_req <= 1'b0;
end
end
else if(curr_state == S_3)begin//发送数据3
data <= 4'd3;
data_req <= 1'b1;
end
else if(curr_state == T_3)begin//间隔5个时钟
if(data_req)begin
cnt_timer <= 3'd0;
data_req <= 1'b0;//撤销data_reg
end
else begin
cnt_timer <= cnt_timer + 1'b1;
data_req <= 1'b0;
end
end
else if(curr_state == S_4)begin//发送数据4
data <= 4'd4;
data_req <= 1'b1;
end
else if(curr_state == T_4)begin//间隔5个时钟
if(data_req)begin
cnt_timer <= 3'd0;
data_req <= 1'b0;//撤销data_reg
end
else begin
cnt_timer <= cnt_timer + 1'b1;
data_req <= 1'b0;
end
end
else if(curr_state == S_5)begin//发送数据5
data <= 4'd5;
data_req <= 1'b1;
end
else if(curr_state == T_5)begin//间隔5个时钟
if(data_req)begin
cnt_timer <= 3'd0;
data_req <= 1'b0;//撤销data_reg
end
else begin
cnt_timer <= cnt_timer + 1'b1;
data_req <= 1'b0;
end
end
else if(curr_state == S_6)begin//发送数据6
data <= 4'd6;
data_req <= 1'b1;
end
else if(curr_state == T_6)begin//间隔5个时钟
if(data_req)begin
cnt_timer <= 3'd0;
data_req <= 1'b0;//撤销data_reg
end
else begin
cnt_timer <= cnt_timer + 1'b1;
data_req <= 1'b0;
end
end
else if(curr_state == S_7)begin//发送数据7
data <= 4'd7;
data_req <= 1'b1;
end
else if(curr_state == T_7)begin//间隔5个时钟
if(data_req)begin
cnt_timer <= 3'd0;
data_req <= 1'b0;//撤销data_reg
end
else begin
cnt_timer <= cnt_timer + 1'b1;
data_req <= 1'b0;
end
end
end
endmodule
//数据接收模块
module data_receiver(
input clk_b,
input rst_n,
input [3:0]data,
input data_req,
output reg data_ack
);
reg [3:0]data_reg;
always@((487950916)posedge clk_b or negedge rst_n)begin
if(!rst_n)
data_ack <= 1'b0;
else if(data_req)begin//检测到此刻的data数据有效,拉高data_ack
data_reg <= data;//储存数据
data_ack <= 1'b1;
end
else
data_ack <= 1'b0;
end
endmodule
