aboutsummaryrefslogtreecommitdiff
path: root/rtl/src/verilog/eim_arbiter_cdc.v
blob: 6a60552a7c9702c4624148df6cf81ceb53476542 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
`timescale 1ns / 1ps

module eim_arbiter_cdc
	(
		eim_clk, eim_req, eim_ack, eim_din, eim_dout,
		sys_clk, sys_addr,
		sys_wren, sys_data_out,
		sys_rden, sys_data_in
	);
	

	input		wire				eim_clk;			// eim clock
	input		wire				eim_req;			// eim transaction request
	output	wire				eim_ack;			// eim transaction acknowledge
	input		wire	[47: 0]	eim_din;			// data from cpu to fpga (write access)
	output	wire	[31: 0]	eim_dout;		// data from fpga to cpu (read access)
	
	input		wire				sys_clk;			// user internal clock
	output	wire	[13: 0]	sys_addr;		// user access address
	output	wire				sys_wren;		// user write flag
	output	wire	[31: 0]	sys_data_out;	// user write data
	output	wire				sys_rden;		// user read flag
	input		wire	[31: 0]	sys_data_in;	// user read data


		//
		// EIM_CLK -> SYS_CLK Request
		//
	wire				sys_req;		// request pulse in sys_clk clock domain
	wire	[47: 0]	sys_dout;	// transaction data in sys_clk clock domain
	
	cdc_bus_pulse #
	(
		.DATA_WIDTH		(48)	// {write, read, addr, data}
	)
	cdc_eim_sys
	(
		.src_clk			(eim_clk),
		.src_din			(eim_din),
		.src_req			(eim_req),
		
		.dst_clk			(sys_clk),
		.dst_dout		(sys_dout),
		.dst_pulse		(sys_req)
	);
	
	
		//
		// Output Registers
		//
	reg	[13: 0]	sys_addr_reg		= {14{1'bX}};	//
	reg				sys_wren_reg		= 1'b0;			//
	reg	[31: 0]	sys_data_out_reg	= {32{1'bX}};	//
	reg				sys_rden_reg		= 1'b0;			//
	
	assign sys_addr		= sys_addr_reg;
	assign sys_wren		= sys_wren_reg;
	assign sys_data_out	= sys_data_out_reg;
	assign sys_rden		= sys_rden_reg;
	
	
		//
		// System (User) Clock Access Handler
		//
	always @(posedge sys_clk)
		//
		if (sys_req) begin									// request detected?
			sys_wren_reg		<= sys_dout[47];				// set write flag if needed
			sys_addr_reg		<= sys_dout[45:32];			// set operation address
			sys_data_out_reg	<= sys_dout[31: 0];			// set data to write
			sys_rden_reg		<= sys_dout[46];				// set read flag if needed
		end else begin											// no request active
			sys_wren_reg		<=  1'b0;						// clear write flag
			sys_rden_reg		<=  1'b0;						// clear read flag
		end
	
	
		//
		// System Request 2-cycle delay to compensate registered mux delay in user-side logic
		//
	reg	[ 1: 0]	sys_req_dly		= 2'b00;
	
	always @(posedge sys_clk)
		sys_req_dly <= {sys_req_dly[0], sys_req};
	

		//
		// SYS_CLK -> EIM_CLK Acknowledge
		//	
	cdc_bus_pulse #
	(
		.DATA_WIDTH		(32)	// {data}
	)
	cdc_sys_eim
	(
		.src_clk			(sys_clk),
		.src_din			(sys_data_in),
		.src_req			(sys_req_dly[1]),
		
		.dst_clk			(eim_clk),
		.dst_dout		(eim_dout),
		.dst_pulse		(eim_ack)
	);


endmodule