-
Notifications
You must be signed in to change notification settings - Fork 0
/
c5g_2hdmi.sv
258 lines (201 loc) · 8.08 KB
/
c5g_2hdmi.sv
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
// Copyright 2022 Douglas P. Fields, Jr. All Rights Reserved.
// See README.md for detailed information.
// IMPORTANT: There are two clock domains here:
// - 50 MHz main system clock
// - HDMI Clock (speed depends on video mode, but generally 75+ MHz)
// Currently there is no domain crossing, but if there is to be
// information displayed, we will need to do some CDC work, or FIFOs,
// or use block RAMs that are differently clocked, etc.
// At the very least, we will want to ensure we don't change what is being
// output during the output of the frame, possibly by some sort of VSYNC
// framebuffer flipping.
`ifdef IS_QUARTUS // Defined in Assignments -> Settings -> ... -> Verilog HDL Input
// This doesn't work in Questa for some reason. vlog-2892 errors.
`default_nettype none // Disable implicit creation of undeclared nets
`endif
// This module definition originally generated by Terasic System Builder
module C5G_2HDMI (
//////////// CLOCK //////////
input logic CLOCK_125_p,
input logic CLOCK_50_B5B,
input logic CLOCK_50_B6A,
input logic CLOCK_50_B7A,
input logic CLOCK_50_B8A,
//////////// LED //////////
output logic [7:0] LEDG,
output logic [9:0] LEDR,
//////////// KEY //////////
input logic CPU_RESET_n,
input logic [3:0] KEY, // Positive when not pushed
//////////// SW //////////
input logic [9:0] SW, // Negative when "down"
//////////// SEG7 //////////
output logic [6:0] HEX0,
output logic [6:0] HEX1,
// HEX2-3 overlap on GPIO 22-35; see below
//////////// HDMI-TX //////////
output logic HDMI_TX_CLK,
output logic [23:0] HDMI_TX_D, // Data
output logic HDMI_TX_DE, // Data enable (true when data is sending visible information)
output logic HDMI_TX_HS,
output logic HDMI_TX_VS,
input logic HDMI_TX_INT,
//////////// I2C for Audio/HDMI-TX/Si5338/HSMC //////////
// These do not work with the ALTIOBUF if they are declared as "logic"
inout wire I2C_SCL, // inout for clock stretching
inout wire I2C_SDA, // Needs "OPEN DRAIN" ALTIOBUF
//////////// Uart to USB //////////
input logic UART_RX,
output logic UART_TX,
//////////// SRAM //////////
output logic [17:0] SRAM_A,
output logic SRAM_CE_n,
output logic SRAM_LB_n,
output logic SRAM_OE_n,
output logic SRAM_UB_n,
output logic SRAM_WE_n,
inout logic [15:0] SRAM_D,
//////////// GPIO, GPIO connect to GPIO Default //////////
inout logic [35:0] GPIO
// 0, 2 = Dedicated clock input
// 3-18 = Arduino IO 0-15
// 16, 18 = PLL Clock Output (??)
// 22-35 = HEX2 & HEX3 0-6
);
//////////////////////////////////////////////////////////////////////
// signal declarations
logic reset; // Global reset (most things implement a synchronous reset)
logic [7:0] pattern; // Pattern formed from switches 3-0
logic hdmiclk; // 1080p HDMI Clock of 148.5 MHz generated by PLL
//////////////////////////////////////////////////////////////////////
// I2C Declarations
// The internal wires for I2C bus, which need to be connected
// to a tri-state external pin with open drain
logic scl_i, scl_o, scl_e;
logic sda_i, sda_o, sda_e;
// Status of I2C controller; Abort/Success are not implemented yet
logic i2c_busy, i2c_abort, i2c_success;
// Debugging outputs of I2C controller
logic i2c_start, i2c_stop, i2c_ack;
// I2C Controller inputs
logic i2c_activate;
logic i2c_readnotwrite;
logic [6:0] i2c_address;
logic [7:0] i2c_location, i2c_data;
//////////////////////////////////////////////////////////////////////
// Structural coding
// Our overall reset will be for KEY[3], which is high when unpressed
assign reset = ~KEY[3];
// Create a 1080p Clock of 148.5MHz from an input clock of 50MHz
pll50to148 clk1080p (
.refclk(CLOCK_50_B5B),
.rst(reset),
.outclk_0(hdmiclk),
.locked(LEDR[9]) // Show the lock on the LED
);
// TODO: The C5G_HDMI_VPG demo application takes the "locked" output
// of the PLL as a reset in to the VPG (Video Pattern Generator)
// Our selected pattern is based on our first four switches
assign pattern[7:4] = 0;
assign pattern[3:0] = SW[3:0];
// Generate our 1080p HDMI pattern
top_sync_vg_pattern hdmi_signals (
.clk(hdmiclk),
.reset(reset), // "resetb" would be a negative reset
.pattern(pattern), // What pattern to generate
.adv7513_hs(HDMI_TX_HS),
.adv7513_vs(HDMI_TX_VS),
.adv7513_d (HDMI_TX_D), // 24-bit data
.adv7513_de(HDMI_TX_DE), // Data enable
.adv7513_clk() // Unconnected Instead of HDMI_TX_CLK
);
// Not sure why the clock should be inverted or not
assign HDMI_TX_CLK = hdmiclk; // Instead of the adv7513_clk, which is ~hdmiclk
// Instantiate our I2C controller.
// This defaults to a parameter to divide the clock by 32, which
// will give about ~1.6 MHz clock for a 50 MHz input clock.
I2C_CONTROLLER i2c_c (
// Controller clock & reset
.clk(CLOCK_50_B5B),
.reset(reset),
// External I2C Bus connections
.scl_i(scl_i), .scl_o(scl_o), .scl_e(scl_e),
.sda_i(sda_i), .sda_o(sda_o), .sda_e(sda_e),
// I2C controller status
.busy(i2c_busy),
.abort(i2c_abort), .success(i2c_success),
// I2C request inputs
.activate(i2c_activate),
.read(i2c_readnotwrite),
.address (i2c_address),
.location(i2c_location),
.data (i2c_data),
.data_repeat(0), // How many times to repeat the data byte
// I2C Controller debugging outputs
.start_pulse(i2c_start),
.stop_pulse (i2c_stop),
.got_ack (i2c_ack)
);
// Watch the I2C Controller externally
assign LEDG[0] = i2c_busy;
assign LEDG[1] = i2c_abort;
assign LEDG[2] = i2c_success;
assign LEDG[3] = i2c_start || i2c_stop;
assign LEDG[4] = i2c_ack;
// Instantiate our state machine to program the ADV7513,
// which does it via I2C
adv7513_setup adv7513_setup(
.clk(CLOCK_50_B5B),
.rst(reset),
.i2c_activate(i2c_activate),
.i2c_busy(i2c_busy),
.i2c_address(i2c_address),
.i2c_readnotwrite(i2c_readnotwrite),
.i2c_byte1(i2c_location),
.i2c_byte2(i2c_data),
// Watch the Setup process externally with LED connections
.active(LEDR[8]),
.done (LEDR[7]),
// Debug outputs
.is_busywait(LEDR[6]),
.is_busyseen(LEDR[5])
);
// Add the I2C BIDI OUTPUT BUFFER
// The I2C I/O buffer from Altera IP Library ALTIOBUF.
// This is set with OPEN DRAIN as per necessary with I2C.
//
// Some references:
// https://community.intel.com/t5/Intel-Quartus-Prime-Software/Warning-18029-Output-pin-cannot-be-tri-stated/td-p/139634
// https://electronics.stackexchange.com/questions/286741/why-do-i2c-lines-use-open-drain-driver-instead-of-tri-state-drivers
// https://www.intel.com/content/www/us/en/docs/programmable/683471/19-1/ip-core-user-guide.html
i2ciobuf i2ciobuf_sda (
.dataio ( I2C_SDA ),
.oe ( sda_e ),
.datain ( sda_o ), // In to the BUFFER from the FPGA then out to the world
.dataout ( sda_i ) // Out from the BUFFER to the FPGA (and in from the world)
);
i2ciobuf i2ciobuf_scl (
.dataio ( I2C_SCL ),
.oe ( scl_e ),
.datain ( scl_o ), // In to the BUFFER from the FPGA then out to the world
.dataout ( scl_i ) // Out from the BUFFER to the FPGA (and in from the world)
);
// Let's mirror these I2C signals to GPIO for debugging
assign GPIO[5:3] = { scl_e, scl_o, scl_i };
assign GPIO[8:6] = { sda_e, sda_o, sda_i };
assign GPIO[9] = i2c_ack;
assign GPIO[10] = i2c_success; // This signal is not yet implemented
// SET some LEDs to demonstrate it working
assign HEX0[6:0] = 7'b0101010;
assign HEX1[6:0] = 7'b1010101;
// Watch the RESET button
assign LEDG[7] = KEY[3]; // KEY[3] is also our reset key
assign LEDG[6] = ~KEY[3]; // KEYs are logic true when not pushed
endmodule
`ifdef IS_QUARTUS // Defined in Assignments -> Settings -> ... -> Verilog HDL Input
// Restore the default_nettype to prevent side effects
// See: https://front-end-verification.blogspot.com/2010/10/implicit-net-declartions-in-verilog-and.html
// and: https://sutherland-hdl.com/papers/2006-SNUG-Boston_standard_gotchas_presentation.pdf
`default_nettype wire // turn implicit nets on again to avoid side-effects
`endif
// Found a similar project: https://github.com/nhasbun/de10nano_vgaHdmi_chip