summaryrefslogtreecommitdiffstats
path: root/fpga/xilinx/digilent/spartan_6/s6_remotefpga_test/main.v
blob: 85c08be23ca56a828062bd432349243607472262 (plain)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 			Raptor Engineering
// Engineer: 			Timothy Pearson
// 
// Design Name:			Remote Access Sample Design
// Module Name:    		sample_demo
// Project Name: 		Remote Access Sample Design
// Target Devices: 		Any
// Description: 		Remote Access Sample Design
//
// Dependencies: 
//
// (c) 2007-2013 Timothy Pearson, Raptor Engineering
// Released into the Public Domain
//
//////////////////////////////////////////////////////////////////////////////////
module main(
	input clk,				// 100MHz clock
	
	// Serial port
	input serial_input,
	output serial_output);

	parameter RAM_ADDR_BITS = 14;

	wire [7:0] four_bit_output;		// Output from the user program to the remote access module
	wire [7:0] four_bit_input;		// Input to the user program from the remote access module
	wire [7:0] eight_bit_output;		// Output from the user program to the remote access module
	wire [7:0] eight_bit_input;		// Input to the user program from the remote access module
	wire [15:0] sixteen_bit_output;		// Output from the user program to the remote access module
	wire [15:0] sixteen_bit_input;		// Input to the user program from the remote access module
	
	wire [7:0] remote_access_local_input;
	
	reg [7:0] serial_data_to_write;
	wire sieze_serial_tx;
	reg serial_tx_strobe = 0;
	wire serial_data_received;
	wire serial_rx_strobe;
	
	wire [5:0] lcd_data_in_address;
	wire [7:0] lcd_data_in_data;
	wire lcd_data_in_enable;

	wire [7:0] led_segment_bus;
	wire [3:0] led_digit_select;
	
	//-------------------------------------------------------------------------------------------------------
	//
	// Generate a 50MHz clock for the remote access module
	//
	//-------------------------------------------------------------------------------------------------------
	
	reg main_fifty_clock = 0;
	always @(posedge clk) begin
		main_fifty_clock = !main_fifty_clock;
	end
	
	//-------------------------------------------------------------------------------------------------------
	//
	// Generate a 25MHz clock for the user progam
	//
	//-------------------------------------------------------------------------------------------------------
	
	reg clk_div_by_two = 0;
	always @(posedge main_fifty_clock) begin
		clk_div_by_two = !clk_div_by_two;
	end

	//-------------------------------------------------------------------------------------------------------
	//
	// Remote Access Module
	//
	// Inputs:
	// .clk: 							50MHz clock
	// .four_bit_input						4-bit input to the user program from the remote access module
	// .eight_bit_input						8-bit input to the user program from the remote access module
	// .sixteen_bit_input						16-bit input to the user program from the remote access module
	// .serial_port_receiver					Input from the serial port's RxD (receive data) pin
	// .remote_access_input_enable					Toggle remote access input vs. local input mode
	// .local_input							Local input to the remote program
	// .seize_serial_tx						Sieze control of the serial transmitter from the remote control system
	// .serial_tx_data						Byte to be transmitted on transmit strobe if control has been siezed
	// .serial_tx_strobe						Transmit serial data on posedge if transmit control has been siezed
	// .lcd_data_in_address						LCD character address (0-32) to write character code to
	// .lcd_data_in_data						LCD character code to write to the address specified
	// .lcd_data_in_enable						Enable LCD data write
	// .sram_wren_in						Synchronous SRAM write enable (1=write, 0=read)
	// .sram_clock_in						Synchronous SRAM clock input
	// .sram_data_in						Synchronous SRAM data input (8-bit)
	// .sram_address_in						Synchronous SRAM address input (14-bit by default)
	// .sram_processing_done					When 1, signal release of user control of synchronous SRAM
	// .led_segment_bus						Connect directly to the 8 bits controlling the LED display segments
	// .led_digit_select						Connect directly to the 4 bits enabling the LED display digits
	//
	// Outputs:
	// .four_bit_output						4-bit output from the user program to the remote access module
	// .eight_bit_output						8-bit output from the user program to the remote access module
	// .sixteen_bit_output						16-bit output from the user program to the remote access module
	// .lcd_data_out						Data output to the LCD
	// .lcd_rs_out							RS signal output to the LCD
	// .lcd_rw_out							RW signal output to the LCD
	// .lcd_enable_out						ENABLE signal output to the LCD
	// .serial_port_transmitter					Output to the serial port's TxD (transmit data) pin
	// .serial_rx_data						The last received serial data
	// .serial_rx_strobe						Recevied serial data valid while this signal is 1
	// .sram_data_out						Synchronous SRAM data output (8-bit)
	// .sram_available						Synchronous SRAM under user control
	//
	//-------------------------------------------------------------------------------------------------------

	wire sram_wren_in;
	wire sram_clock_in;
	wire [7:0] sram_data_in;
	wire [(RAM_ADDR_BITS-1):0] sram_address_in;
	wire [7:0] sram_data_out;
	wire sram_available;
	wire sram_processing_done;

	// Uncomment this block if no image processing module is provided
	// assign sram_wren_in = 0;
	// assign sram_data_in = 0;
	// assign sram_address_in = 0;
	// assign sram_processing_done = 1;
	
	assign sram_clock_in = main_fifty_clock;

	remote_access #(RAM_ADDR_BITS) remote_access(.main_fifty_clock(main_fifty_clock), .remote_access_4_bit_output(four_bit_output),
		.remote_access_4_bit_input(four_bit_input), .remote_access_8_bit_output(eight_bit_output),
		.remote_access_8_bit_input(eight_bit_input), .remote_access_16_bit_output(sixteen_bit_output),
		.remote_access_16_bit_input(sixteen_bit_input),
		.serial_port_receiver(serial_input), .serial_port_transmitter(serial_output), .remote_access_input_enable(btn_center),
		.local_input(remote_access_local_input), .seize_serial_tx(sieze_serial_tx), .serial_tx_data(serial_data_to_write),
		.serial_tx_strobe(serial_tx_strobe), .serial_rx_data(serial_data_received), .serial_rx_strobe(serial_rx_strobe),
		.lcd_data_in_address(lcd_data_in_address), .lcd_data_in_data(lcd_data_in_data), .lcd_data_in_enable(lcd_data_in_enable),
		.sram_wren_in(sram_wren_in), .sram_clock_in(sram_clock_in), .sram_data_in(sram_data_in), .sram_address_in(sram_address_in),
		.sram_data_out(sram_data_out), .sram_available(sram_available), .sram_processing_done(sram_processing_done),
		.led_segment_bus(led_segment_bus), .led_digit_select(led_digit_select));
	
	assign remote_access_local_input[7:4] = 0;					// Local inputs
	assign remote_access_local_input[3:0] = 0;					// Local inputs
	assign led_bank = eight_bit_input;						// Mirror input to the LEDs
	assign sieze_serial_tx = 0;							// Allow the remote control module to use the serial port
											// If the user module must access the serial port directly, delete
											// this assign statement and control this wire with your module.
	
	//-------------------------------------------------------------------------------------------------------
	//
	// User Module Instantiation
	//
	// Instantiate the simple user module to display remote access input values on the LEDs and to feed 
	// button presses to the remote access module.  The 16-bit remote access lines are in loopback.
	// Feel free to delete this instantiation and the module below to replace it with your module.
	//
	//-------------------------------------------------------------------------------------------------------
	
	sample_demo sample_demo(.clk(clk_div_by_two), .four_bit_input(four_bit_input), .four_bit_output(four_bit_output),
		.eight_bit_input(eight_bit_input), .eight_bit_output(eight_bit_output), .sixteen_bit_input(sixteen_bit_input),
		.sixteen_bit_output(sixteen_bit_output), .lcd_data_in_address(lcd_data_in_address),
		.lcd_data_in_data(lcd_data_in_data), .lcd_data_in_enable(lcd_data_in_enable),
		.led_segment_bus(led_segment_bus), .led_digit_select(led_digit_select));

	//-------------------------------------------------------------------------------------------------------
	//
	// User Image Processing Module Instantiation
	//
	// Instantiate the simple userimage processing module to invert the bits in any images sent to the FPGA
	//
	//-------------------------------------------------------------------------------------------------------

	sample_image_processing_demo sample_image_processing_demo(.clk(clk_div_by_two), .wren(sram_wren_in), .dout(sram_data_in), .addr(sram_address_in),
		.din(sram_data_out), .enable(sram_available), .done(sram_processing_done));

endmodule

//-------------------------------------------------------------------------------------------------------
//
// Demo User Module
//
//-------------------------------------------------------------------------------------------------------

module sample_demo(clk, four_bit_input, four_bit_output, eight_bit_input, eight_bit_output, sixteen_bit_input, sixteen_bit_output, lcd_data_in_address, lcd_data_in_data, lcd_data_in_enable, led_segment_bus, led_digit_select);
	input clk;
	
	input [3:0] four_bit_input;
	output reg [3:0] four_bit_output;
	input [7:0] eight_bit_input;
	output reg [7:0] eight_bit_output;
	input [15:0] sixteen_bit_input;
	output reg [15:0] sixteen_bit_output;
	
	output reg [5:0] lcd_data_in_address;
	output reg [7:0] lcd_data_in_data;
	output reg lcd_data_in_enable;

	output reg [7:0] led_segment_bus;
	output reg [3:0] led_digit_select;

	reg [7:0] lcd_sample_counter = 48;							// Create a sample LCD display counter register
	reg [31:0] lcd_character_change_timer = 0;						// Wait a certain number of cycles before loading a new character
	reg [5:0] lcd_current_character = 0;							// The current character's address
	
	always @(posedge clk) begin
		four_bit_output = four_bit_input;						// Loopback
		eight_bit_output = eight_bit_input[3:0] + eight_bit_input[7:4];			// Sample adder
		sixteen_bit_output = sixteen_bit_input[15:8] * sixteen_bit_input[7:0];		// Sample multiplier
		
		// Sample LCD display routine		
		lcd_data_in_address = lcd_current_character;					// Character location on the LCD display
		lcd_data_in_data = lcd_sample_counter;						// Character code to display
		lcd_data_in_enable = 1;								// Enable data transmission
		
		// Cycle through all character positions
		lcd_current_character = lcd_current_character + 1;
		if (lcd_current_character > 31) begin
			lcd_current_character = 16;
		end
		
		// Cycle through the numbers 0 to 9 at one second intervals
		lcd_character_change_timer = lcd_character_change_timer + 1;
		if (lcd_character_change_timer > 25000000) begin				// Wait one second in between character changes
			lcd_character_change_timer = 0;
			lcd_sample_counter = lcd_sample_counter + 1;
			if (lcd_sample_counter > 57) begin					// Character code for the digit 9
				lcd_sample_counter = 48;					// Character code for the digit 0
			end
		end
	end

	// 7-segment LED display driver clock generator
	reg sseg_clock;
	reg [4:0] sseg_clock_counter;

	always @(posedge clk) begin
		sseg_clock_counter = sseg_clock_counter + 1;
		if (sseg_clock_counter > 16) begin
			sseg_clock_counter = 0;
			sseg_clock = ~sseg_clock;
		end
	end

	// 7-segment LED display driver
	// led_segment_bus and led_digit_select are active low
	// The bit sequence, MSB to LSB, is dp a b c d e f g
	// Segment letters are taken from ug130.pdf page 15

	// 0: 8'b10000001
	// 1: 8'b11001111
	// 2: 8'b10010010
	// 3: 8'b10000110
	reg [2:0] current_anode;
	always @(posedge sseg_clock) begin
		current_anode = current_anode + 1;
		if (current_anode > 3) begin
			current_anode = 0;
		end

		case (current_anode)
			0: begin
				led_digit_select = 4'b1110;
				led_segment_bus = 8'b10000001;
			end
			1: begin
				led_digit_select = 4'b1101;
				led_segment_bus = 8'b11001111;
			end
			2: begin
				led_digit_select = 4'b1011;
				led_segment_bus = 8'b10010010;
			end
			3: begin
				led_digit_select = 4'b0111;
				led_segment_bus = 8'b10000110;
			end
		endcase
	end
endmodule

//-------------------------------------------------------------------------------------------------------
//
// Demo User Image Processing Module
//
//-------------------------------------------------------------------------------------------------------

module sample_image_processing_demo(clk, wren, dout, addr, din, enable, done);
	input clk;

	output reg wren;
	output reg [7:0] dout;
	output reg [(RAM_ADDR_BITS-1):0] addr;
	input [7:0] din;
	input enable;
	output reg done;

	reg prev_enable;
	reg [(RAM_ADDR_BITS-1):0] counter;
	reg toggler;

	always @(posedge clk) begin
		if ((enable == 1) && (prev_enable == 0)) begin
			counter = 0;
			toggler = 0;
		end
		if ((enable == 1) && (done == 0)) begin
			if (toggler == 0) begin
				wren = 0;
				addr = counter;
				toggler = 1;
			end else begin
				dout = ~din;
				wren = 1;
				addr = counter;
				counter = counter + 1;
				if (counter > (2**RAM_ADDR_BITS)) begin
					done = 1;
				end
				toggler = 0;
			end
		end
		if (enable == 0) begin
			done = 0;
			addr = 0;
			toggler = 0;
		end
		prev_enable = enable;
	end
endmodule