transmit端
module transmit(tclk,reset_tclk,t_rdy,data_avail,transmit_data,t_data,r_ack);
input tclk;
input reset_tclk;
input data_avail;
input [31:0] transmit_data;
input r_ack;
output t_rdy;
output t_data;
localparam IDLE_T = 2'd0,
ASSERT_T_RDY = 2'd1,
DEASSERT_T_RDY = 2'd2;
reg [1:0] t_hndshk_state,t_hndshk_state_nxt;
reg t_rdy,t_rdy_nxt;
reg [31:0] t_data,t_data_nxt;
reg r_ack_tclk;
always@(*)begin
t_hndshk_state_nxt = t_hndshk_state;
t_rdy_nxt = 1'b0;
t_data_nxt = t_data;
case(t_hndshk_state)
IDLE_T:begin
if(data_avail) begin
t_rdy_nxt = 1'b1;
t_hndshk_state_nxt = ASSERT_T_RDY;
t_data_nxt = transmit_data;
end
end
ASSERT_T_RDY:begin
if(r_ack_tclk)begin
t_rdy_nxt = 1'b0;
t_hndshk_state_nxt = DEASSERT_T_RDY;
t_data_nxt = 'd0;
end
else begin
t_rdy_nxt = 1'b1;
t_data_nxt = transmit_data;
end
end
DEASSERT_T_RDY:begin
if(!r_ack_tclk)begin
if(data_avail)begin
t_rdy_nxt = 1'b1;
t_hndshk_state_nxt = ASSERT_T_RDY;
t_data_nxt = transmit_data;
end
else begin
t_hndshk_state_nxt = IDLE_T;
end
end
end
endcase
end
always@(posedge tclk or negedge reset_tclk)begin
if(!reset_tclk)begin
t_rdy <= 1'b0;
t_hndshk_state <= IDLE_T;
t_data <= 32'h00000000;
r_ack_tclk <= 1'b0;
end
else begin
t_rdy <= t_rdy_nxt;
t_hndshk_state <= t_hndshk_state_nxt;
t_data <= t_data_nxt;
r_ack_tclk <= r_ack;
end
end
endmodule
reciver端
module receiver(rclk,reset_rclk,t_rdy,t_data,r_ack);
input rclk,reset_rclk;
input t_rdy;
input[31:0] t_data;
output r_ack;
reg r_hndshk_state,r_hndshk_state_nxt;
reg t_rdy_rclk;
reg[31:0] t_data_rclk,t_data_rclk_nxt;
reg r_ack,r_ack_nxt;
localparam IDLE_R = 1'b0,
ASSERT_ACK = 1'b1;
always@(*)begin
r_hndshk_state_nxt = r_hndshk_state;
r_ack_nxt = 1'b0;
t_data_rclk_nxt = t_data_rclk;
case(r_hndshk_state)
IDLE_R:begin
if(t_rdy_rclk)begin
r_hndshk_state_nxt = ASSERT_ACK;
t_data_rclk_nxt = t_data;
r_ack_nxt = 1'b1;
end
end
ASSERT_ACK:begin
if(!t_rdy_rclk)begin
r_hndshk_state_nxt = IDLE_R;
r_ack_nxt = 1'b0;
end
else begin
r_ack_nxt = 1'b1;
end
end
endcase
end
always@(posedge rclk or negedge reset_rclk)begin
if(!reset_rclk)begin
r_hndshk_state <= IDLE_R;
t_data_rclk <= 1'b0;
t_rdy_rclk <= 1'b0;
r_ack <= 1'b0;
end
else begin
r_hndshk_state <= r_hndshk_state_nxt;
t_data_rclk <= t_data_rclk_nxt;
t_rdy_rclk <= t_rdy;
r_ack <= r_ack_nxt;
end
end
endmodule
textbench
`timescale 1ns/1ns
module testbench;
reg tclk_tb,rclk_tb;
reg [31:0] transmit_data_tb;
reg reset_tclk_tb,reset_rclk_tb;
reg data_avail_tb;
wire t_rdy_tb;
wire [31:0] t_data_tb;
wire r_ack_tb;
parameter CLK_HALF_PERIOD1 = 5;
parameter CLK_HALF_PERIOD2 = 10;
parameter RESET_DELAY = 100;
transmit transmit_inst
(.tclk(tclk_tb),
.reset_tclk(reset_tclk_tb),
.t_rdy(t_rdy_tb),
.data_avail(data_avail_tb),
.transmit_data(transmit_data_tb),
.t_data(t_data_tb),
.r_ack(r_ack_tb));
receiver receiver_inst
(.rclk(rclk_tb),
.reset_rclk(reset_rclk_tb),
.t_rdy(t_rdy_tb),
.t_data(t_data_tb),
.r_ack(r_ack_tb));
initial begin
tclk_tb = 0;
rclk_tb = 0;
end
always #CLK_HALF_PERIOD1 tclk_tb = ~tclk_tb;
always #CLK_HALF_PERIOD2 rclk_tb = ~rclk_tb;
initial begin
reset_rclk_tb = 0;
reset_tclk_tb = 0;
#RESET_DELAY reset_rclk_tb = 1;
reset_tclk_tb = 1;
end
//gen transmit valid and data
initial begin
#300;
repeat(20) begin
data_avail_tb = 1;
transmit_data_tb = 32'h96431346;
#200;
data_avail_tb = 0;
transmit_data_tb = $random();
#300;
data_avail_tb = 1;
transmit_data_tb = $random();
#200;
end
#1000;
$finish();
end
initial begin
$fsdbDumpfile("jacky");
$fsdbDumpvars;
$vcdpluson;
end
endmodule