129 lines
4.0 KiB
Systemverilog
129 lines
4.0 KiB
Systemverilog
|
/*
|
||
|
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||
|
|
||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
you may not use this file except in compliance with the License.
|
||
|
You may obtain a copy of the License at
|
||
|
|
||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
Unless required by applicable law or agreed to in writing, software
|
||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
See the License for the specific language governing permissions and
|
||
|
limitations under the License.
|
||
|
*/
|
||
|
|
||
|
// 数据接收端模块
|
||
|
// 跨时钟域传输,全(四次)握手协议
|
||
|
// req = 1
|
||
|
// ack_o = 1
|
||
|
// req = 0
|
||
|
// ack_o = 0
|
||
|
module full_handshake_rx #(
|
||
|
parameter DW = 32)( // RX要接收数据的位宽
|
||
|
|
||
|
input wire clk, // RX端时钟信号
|
||
|
input wire rst_n, // RX端复位信号
|
||
|
|
||
|
// from tx
|
||
|
input wire req_i, // TX端请求信号
|
||
|
input wire[DW-1:0] req_data_i, // TX端输入数据
|
||
|
|
||
|
// to tx
|
||
|
output wire ack_o, // RX端应答TX端信号
|
||
|
|
||
|
// to rx
|
||
|
output wire[DW-1:0] recv_data_o,// RX端接收到的数据
|
||
|
output wire recv_rdy_o // RX端是否接收到数据信号
|
||
|
|
||
|
);
|
||
|
|
||
|
localparam STATE_IDLE = 2'b01;
|
||
|
localparam STATE_DEASSERT = 2'b10;
|
||
|
|
||
|
reg[1:0] state;
|
||
|
reg[1:0] state_next;
|
||
|
|
||
|
always @ (posedge clk or negedge rst_n) begin
|
||
|
if (!rst_n) begin
|
||
|
state <= STATE_IDLE;
|
||
|
end else begin
|
||
|
state <= state_next;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @ (*) begin
|
||
|
case (state)
|
||
|
// 等待TX请求信号req=1
|
||
|
STATE_IDLE: begin
|
||
|
if (req == 1'b1) begin
|
||
|
state_next = STATE_DEASSERT;
|
||
|
end else begin
|
||
|
state_next = STATE_IDLE;
|
||
|
end
|
||
|
end
|
||
|
// 等待req=0
|
||
|
STATE_DEASSERT: begin
|
||
|
if (req) begin
|
||
|
state_next = STATE_DEASSERT;
|
||
|
end else begin
|
||
|
state_next = STATE_IDLE;
|
||
|
end
|
||
|
end
|
||
|
default: begin
|
||
|
state_next = STATE_IDLE;
|
||
|
end
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
reg req_d;
|
||
|
reg req;
|
||
|
|
||
|
// 将请求信号打两拍进行同步
|
||
|
always @ (posedge clk or negedge rst_n) begin
|
||
|
if (!rst_n) begin
|
||
|
req_d <= 1'b0;
|
||
|
req <= 1'b0;
|
||
|
end else begin
|
||
|
req_d <= req_i;
|
||
|
req <= req_d;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
reg[DW-1:0] recv_data;
|
||
|
reg recv_rdy;
|
||
|
reg ack;
|
||
|
|
||
|
always @ (posedge clk or negedge rst_n) begin
|
||
|
if (!rst_n) begin
|
||
|
ack <= 1'b0;
|
||
|
recv_rdy <= 1'b0;
|
||
|
recv_data <= {(DW){1'b0}};
|
||
|
end else begin
|
||
|
case (state)
|
||
|
STATE_IDLE: begin
|
||
|
if (req == 1'b1) begin
|
||
|
ack <= 1'b1;
|
||
|
recv_rdy <= 1'b1; // 这个信号只会持续一个时钟
|
||
|
recv_data <= req_data_i; // 这个信号只会持续一个时钟
|
||
|
end
|
||
|
end
|
||
|
STATE_DEASSERT: begin
|
||
|
recv_rdy <= 1'b0;
|
||
|
recv_data <= {(DW){1'b0}};
|
||
|
// req撤销后ack也撤销
|
||
|
if (req == 1'b0) begin
|
||
|
ack <= 1'b0;
|
||
|
end
|
||
|
end
|
||
|
endcase
|
||
|
end
|
||
|
end
|
||
|
|
||
|
assign ack_o = ack;
|
||
|
assign recv_rdy_o = recv_rdy;
|
||
|
assign recv_data_o = recv_data;
|
||
|
|
||
|
endmodule
|