1`timescale 1ns / 1ps
2/*
3 * This software is Copyright (c) 2016 Denis Burykin
4 * [denis_burykin yahoo com], [denis-burykin2014 yandex ru]
5 * and it is hereby released to the general public under the following terms:
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted.
8 *
9 */
10
11//***********************************************************
12//
13// Vendor Command / Vendor Request feature
14// Commands or requests are sent to EZ-USB via USB EP0
15// and handled by EZ-USB processor.
16//
17//***********************************************************
18
19//***********************************************************
20//
21// New feature: cmd 0x00 disables the interface, allows
22// usage of raw I/O port PC[7:0]. A pulse on clk_vcr_addr returns from raw mode.
23//
24// There's up to 256 VCR addresses (subsystems) for read or(and) write.
25// Sequential multi-byte read or/and write is possible.
26// For some actions, there's no need to read or write, just select address.
27//
28// EZ-USB uses 11 lines to FPGA. Typical exchange is as follows:
29// 1. set direction towards FPGA (vcr_dir=0). Assert CPU I/O controls accordingly.
30// 2. assert address on [7:0] vcr_inout.
31// 3. assert vcr_set_addr, then deassert vcr_set_addr. This selects address.
32// Optionally write:
33// 4. setup data byte on [7:0] vcr_inout.
34// 5. assert vcr_set_data, then deassert vcr_set_data. This performs write of the byte from step 4.
35// 6. go to step 4 if nesessary.
36// Optionally read:
37// 7. set direction for input from FPGA (vcr_dir=1). Assert CPU I/O controls accordingly.
38// 8. read data byte from [7:0] vcr_inout.
39// 9. assert vcr_set_data, then deassert vcr_set_data. This let next data byte appear on [7:0] vcr_inout.
40// 10. go to step 7 if necessary.
41//
42//***********************************************************
43
44module vcr(
45	input CS,
46
47	input [7:0] vcr_in, //  Vendor Command/Request (VCR) address/data
48	output [7:0] vcr_out,
49	input clk_vcr_addr, // on posedge, set (internal to FPGA) VCR IO address
50	input clk_vcr_data, // on posedge, perform write or synchronous read
51
52	input IFCLK,
53
54	input [2:0] FPGA_ID,
55	input [7:0] hs_io_timeout,
56	input hs_input_prog_full,
57	//input output_err_overflow,
58	input sfifo_not_empty,
59	input io_fsm_error, io_err_write,
60	input [15:0] output_limit,
61	input output_limit_not_done,
62	input progdone_inv,
63	input [7:0] app_status,
64	input [7:0] pkt_comm_status, debug2, debug3,
65	//input [255:0] debug,
66
67	//
68	// Defaults for various controls; see also VCR_RESET
69	//
70	output reg inout_raw = 0, // use PC[7:0] in raw mode
71	output reg hs_en = 0, // enable high-speed i/o
72	output reg output_mode_limit = 1, // output_limit
73	output reg reg_output_limit = 0, // with respect to IFCLK
74	output reg [7:0] app_mode = 0 // default mode: 0
75	);
76
77	wire ENABLE = CS;
78
79	// VCR address definitions
80	localparam VCR_SET_HS_IO_ENABLE = 8'h80;
81	localparam VCR_SET_HS_IO_DISABLE = 8'h81;
82	localparam VCR_SET_APP_MODE = 8'h82;
83	localparam VCR_GET_IO_STATUS = 8'h84;
84	// registers output limit (in output_limit_fifo words); starts
85	// output of that many via high-speed interface
86	localparam VCR_REG_OUTPUT_LIMIT = 8'h85;
87	localparam VCR_SET_OUTPUT_LIMIT_ENABLE = 8'h86;
88	localparam VCR_SET_OUTPUT_LIMIT_DISABLE = 8'h87;
89	localparam VCR_ECHO_REQUEST = 8'h88;
90	localparam VCR_GET_FPGA_ID = 8'h8A;
91	localparam VCR_RESET = 8'h8B;
92	localparam VCR_GET_ID_DATA = 8'hA1;
93	//localparam VCR_ = 8'h;
94
95	async2sync sync_addr_inst( .async(clk_vcr_addr), .clk(IFCLK), .clk_en(clk_addr_en) );
96	async2sync sync_data_inst( .async(clk_vcr_data), .clk(IFCLK), .clk_en(clk_data_en) );
97
98	reg [7:0] vcr_addr;
99	reg [5:0] vcr_state = 0;
100
101	/////////////////////////////////////////////////////////
102	//
103	// declarations for Command / Request specific stuff
104	//
105	/////////////////////////////////////////////////////////
106	localparam [15:0] BITSTREAM_TYPE = `BITSTREAM_TYPE;
107
108	reg [7:0] echo_content [3:0];
109	reg RESET_R = 0;
110
111	// declarations for Command / Request specific stuff end
112
113
114	/////////////////////////////////////////////////////////
115	//
116	// Input
117	//
118	/////////////////////////////////////////////////////////
119
120	always @(posedge IFCLK) begin
121		if (ENABLE && clk_addr_en) begin
122			vcr_addr <= vcr_in;
123			vcr_state <= 0;
124
125			if (inout_raw)
126				inout_raw <= 0;
127			else if (vcr_in == 8'h00)
128				inout_raw <= 1;
129			else if (vcr_in == VCR_SET_HS_IO_ENABLE)
130				hs_en <= 1;
131			else if (vcr_in == VCR_SET_HS_IO_DISABLE)
132				hs_en <= 0;
133			else if (vcr_in == VCR_SET_OUTPUT_LIMIT_ENABLE)
134				output_mode_limit <= 1;
135			else if (vcr_in == VCR_SET_OUTPUT_LIMIT_DISABLE)
136				output_mode_limit <= 0;
137			else if (vcr_in == VCR_RESET)
138				RESET_R <= 1;
139			else if (vcr_in == VCR_REG_OUTPUT_LIMIT)
140				reg_output_limit <= 1;
141
142		end // clk_addr_en
143
144		else if (ENABLE && clk_data_en) begin
145			vcr_state <= vcr_state + 1'b1;
146
147			if (vcr_addr == VCR_ECHO_REQUEST)
148				echo_content[ vcr_state[1:0] ] <= vcr_in;
149			else if (vcr_addr == VCR_SET_APP_MODE)
150				app_mode <= vcr_in;
151		end // clk_data_en
152
153		else begin // !ENABLE
154			if (reg_output_limit)
155				reg_output_limit <= 0;
156
157		end
158	end
159
160
161
162	/////////////////////////////////////////////////////////
163	//
164	// Output
165	//
166	/////////////////////////////////////////////////////////
167
168	assign vcr_out =
169		(vcr_addr == VCR_REG_OUTPUT_LIMIT && vcr_state == 0) ? output_limit[7:0] :
170		(vcr_addr == VCR_REG_OUTPUT_LIMIT && vcr_state == 1) ? output_limit[15:8] :
171
172		(vcr_addr == VCR_GET_IO_STATUS && vcr_state == 0) ? {
173			progdone_inv, 1'b0, io_err_write, io_fsm_error,
174			sfifo_not_empty, 1'b0, output_limit_not_done, hs_input_prog_full
175		} :
176		(vcr_addr == VCR_GET_IO_STATUS && vcr_state == 1) ? hs_io_timeout :
177		(vcr_addr == VCR_GET_IO_STATUS && vcr_state == 2) ? app_status :
178		(vcr_addr == VCR_GET_IO_STATUS && vcr_state == 3) ? pkt_comm_status :
179		(vcr_addr == VCR_GET_IO_STATUS && vcr_state == 4) ? debug2 :
180		(vcr_addr == VCR_GET_IO_STATUS && vcr_state == 5) ? debug3 :
181
182		(vcr_addr == VCR_ECHO_REQUEST) ? echo_content[ vcr_state[1:0] ] ^ 8'h5A :
183
184		(vcr_addr == VCR_GET_ID_DATA && vcr_state == 0) ? BITSTREAM_TYPE[7:0] :
185		(vcr_addr == VCR_GET_ID_DATA && vcr_state == 1) ? BITSTREAM_TYPE[15:8] :
186
187		(vcr_addr == VCR_GET_FPGA_ID) ? { {5{1'b0}}, FPGA_ID } :
188		//(vcr_addr ==  && vcr_state == ) ?  :
189		8'b0;
190
191
192	startup_spartan6 startup_spartan6(.rst(RESET_R));
193
194endmodule
195