main.v 82.8 KB
Newer Older
1 2 3 4 5
// © 2017 - 2020 Raptor Engineering, LLC
//
// Released under the terms of the AGPL v3
// See the LICENSE file for full details

6
`define LPC_SLAVE_DEBUG
7
`define RESYNTHESIZE_LPC_CLOCK
8
// `define ENABLE_LPC_PULLUPS
9
`define ENABLE_SERIAL_IRQ_SUPPORT
10 11 12 13

// Move diagnostic ports off of 81h/82h and disable firmware memory cycle decoding
// `define SWITCH_TO_PARALLEL_OPERATION_WITH_BMC

14 15 16 17 18
// Block writes to GUARD partition
// Useful for debug or in situations where failed hardware
// should be automatically retried on the next IPL
`define BLOCK_GUARD_PARTITION_WRITES

19
// Block writes to everything except DJVPD / MVPD / CVPD / NVRAM
20
// This implicitly blocks GUARD partition writes
21 22
`define BLOCK_NONESSENTIAL_WRITES

23 24 25
// Block writes to NVRAM partition
// `define BLOCK_NVRAM_PARTITION_WRITES

26 27 28 29
`ifdef BLOCK_NONESSENTIAL_WRITES
`undef BLOCK_GUARD_PARTITION_WRITES
`endif

30 31 32
`ifdef SWITCH_TO_PARALLEL_OPERATION_WITH_BMC
`define DISABLE_FIRMWARE_MEMORY_CYCLES
`endif
33

34
// Main modules
35
`include "clock_generator.v"
36
`include "lpc_interface.v"
37
`include "spi_master.v"
38
`include "ipmi_bt_slave.v"
39
`include "flash_block_cache.v"
40

41 42 43
// Third party modules
`include "third_party/uart/uart_top.v"

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
module lpc_bridge_top(
		// Main 12MHz platform clock
		input wire primary_platform_clock,

		// Debug / GPIO connections
		output wire led_7,
		output wire led_6,
		output wire led_5,
		output wire led_4,
		output wire led_3,
		output wire led_2,
		output wire led_1,
		output wire led_0,

		// Debug port 2
		output wire led_15,
		output wire led_14,
		output wire led_13,
		output wire led_12,
		output wire led_11,
		output wire led_10,
		output wire led_9,
		output wire led_8,

		// LPC slave interface
		inout lpc_slave_addrdata_3,
		inout lpc_slave_addrdata_2,
		inout lpc_slave_addrdata_1,
		inout lpc_slave_addrdata_0,
73 74 75 76
		inout lpc_slave_addrdata_3_2,
		inout lpc_slave_addrdata_2_2,
		inout lpc_slave_addrdata_1_2,
		inout lpc_slave_addrdata_0_2,
77 78
`ifdef ENABLE_SERIAL_IRQ_SUPPORT
		inout lpc_slave_serirq,
79
		inout lpc_slave_serirq_2,
80 81
`else
		input lpc_slave_serirq,
82
		input lpc_slave_serirq_2,
83 84 85 86 87 88 89 90
`endif

		input wire lpc_slave_pwrdn_n,
		input wire lpc_slave_clkrun_n,
		input wire lpc_slave_frame_n,
		input wire lpc_slave_reset_n,
		input wire lpc_slave_tpm_gpio0,
		input wire lpc_slave_clock,
91 92
		input wire lpc_slave_frame_n_2,
		input wire lpc_slave_reset_n_2,
93 94 95 96 97

		// SPI external master interface
		output wire spi_external_master_clock,
		output wire spi_external_master_mosi,
		input wire spi_external_master_miso,
98 99
		output wire spi_external_master_ss_n,
		output wire spi_external_master_hold_n,
100
		output wire spi_external_master_wp_n,
101
		output wire spi_external_master_reset_n,
102 103

		// LPC debug mirror port
104 105
		output wire lpc_debug_mirror_clock,
		output wire lpc_debug_mirror_clock_extern_uart,
106 107 108 109 110
		output wire lpc_debug_mirror_clock_dbl,

		// Host 16550 UART
		input wire host_uart_rx,
		output wire host_uart_tx
111 112
	);

113
`ifndef SWITCH_TO_PARALLEL_OPERATION_WITH_BMC
114 115
	parameter DEBUG_PORT_ADDRESS_HIGH = 16'h0081;
	parameter DEBUG_PORT_ADDRESS_LOW = 16'h0082;
116
	parameter IPMI_BT_PORT_BASE_ADDRESS = 16'h00e4;
117
	parameter IPMI_BT_IRQ = 10;
118 119
	parameter HOST_UART_BASE_ADDRESS = 16'h03f8;
	parameter HOST_UART_IRQ = 4;
120 121 122
`else
	parameter DEBUG_PORT_ADDRESS_HIGH = 16'h0083;
	parameter DEBUG_PORT_ADDRESS_LOW = 16'h0084;
123
	parameter IPMI_BT_PORT_BASE_ADDRESS = 16'h00d4;
124
	parameter IPMI_BT_IRQ = 11;
125
	parameter HOST_UART_BASE_ADDRESS = 16'h02f8;
126
	parameter HOST_UART_IRQ = 3;
127
`endif
128

129 130
	parameter HIOMAP_MAX_CACHE_SIZE_BYTES = 4096;

131 132 133 134 135
`ifdef BLOCK_GUARD_PARTITION_WRITES
	parameter GUARD_PARTITION_START_ADDRESS = 28'h2c000;
	parameter GUARD_PARTITION_END_ADDRESS =   28'h5cfff;
`endif

136 137 138
`ifdef BLOCK_NONESSENTIAL_WRITES
	parameter VPD_PARTITION_START_ADDRESS =   28'h0e5000;
	parameter VPD_PARTITION_END_ADDRESS =     28'h204fff;
139 140
	parameter NVRAM_PARTITION_START_ADDRESS = 28'h031000;
	parameter NVRAM_PARTITION_END_ADDRESS =   28'h0c0fff;
141 142
`endif

143 144 145 146 147 148
	// Up to 108MHz clock rate on SPI outgoing clock (Flash device default)
	//parameter SPI_FAST_READ_DUMMY_CLOCK_CYCLES = 10;

	// Up to 30MHz clock rate on SPI outgoing clock
	parameter SPI_FAST_READ_DUMMY_CLOCK_CYCLES = 1;

149 150 151
	// Fully isolate / power down host interfaces on external request
	reg drive_host_interfaces = 1;

152 153
	// LPC reset signal
	wire lpc_slave_reset_n_buffered;
154
	reg lpc_slave_reset_n_buffered_gated = 0;
155 156

`ifdef RESYNTHESIZE_LPC_CLOCK
157
	// Clean up incoming LPC clock (33.33MHz)
158
	wire lpc_pll_lock;
159
	wire lpc_slave_tx_clock_resynthesized;
160
	wire lpc_slave_clock_resynthesized;
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
`ifdef ENABLE_EXPERIMENTAL_RECLOCKING_PLL_DOUBLING
	// NOTE:
	// The iCE40 PLL is very poorly documented in the
	// external feedback path.  Discussion follows:
	//
	// In the iCE40 Ultra Plus documentation, it is mentioned
	// that EXTERNAL_DIVIDE_FACTOR actually influences the clock
	// synthesis by acting as a multiplier for GENCLK.
	// Therefore, to get a doubled frequency along with the phase
	// aligned / duty cycle corrected original frequency, the PLL
	// needs to be set for 1:1 clock synthesis and the feedback
	// path division factor needs to be set to 2.  Feeding the
	// GENCLK_HALF signal back into the feedback pin then seems
	// to work as intended -- the original clock is aligned, and
	// a doubled clock is available on port B via the GENCLK route.
	//
	// Unfortunately, even with this inferred information, the PLL
	// is not exactly phase matching its output with the input.
	// Since this is apparently a little used feature of the iCE40
	// PLLs, it's probably not worth debugging in this context.
	// Larger devices like the ECP5 have four PLLs to work with,
	// making the use of a second PLL to generate the SPI clock
	// more reasonable.
	wire lpc_slave_clock_doubled;
	SB_PLL40_2F_PAD #(
		.FEEDBACK_PATH("EXTERNAL"),
		.PLLOUT_SELECT_PORTA("GENCLK_HALF"),
		.PLLOUT_SELECT_PORTB("GENCLK"),
		.EXTERNAL_DIVIDE_FACTOR(2'b10),
		.SHIFTREG_DIV_MODE(1'b0),
		.DIVR(4'b0000),
		.DIVF(7'b0000000),
		.DIVQ(3'b100),
		.FILTER_RANGE(3'b011)
	) lpc_slave_pll (
		.LOCK(lpc_pll_lock),
		.EXTFEEDBACK(lpc_slave_clock_resynthesized),
		.RESETB(lpc_slave_reset_n_buffered_gated),
		.BYPASS(1'b0),
		.PACKAGEPIN(lpc_slave_clock),
		.PLLOUTGLOBALA(lpc_slave_clock_resynthesized),
		.PLLOUTGLOBALB(lpc_slave_clock_doubled)
	);
`else
205
	SB_PLL40_2F_PAD #(
206
		.FEEDBACK_PATH("PHASE_AND_DELAY"),
207
		.PLLOUT_SELECT_PORTA("SHIFTREG_0deg"),
208 209
		.PLLOUT_SELECT_PORTB("SHIFTREG_0deg"),
		.SHIFTREG_DIV_MODE(1'b0),
210 211
		.DIVR(4'b0000),
		.DIVF(7'b0000000),
212
		.DIVQ(3'b100),
213 214 215
		.FILTER_RANGE(3'b011)
	) lpc_slave_pll (
		.LOCK(lpc_pll_lock),
216
		.RESETB(lpc_slave_reset_n_buffered_gated),
217
		.BYPASS(1'b0),
218
		.PACKAGEPIN(lpc_slave_clock),
219
		.PLLOUTGLOBALA(lpc_slave_clock_resynthesized)
220
	);
221
`endif
222
	assign lpc_slave_tx_clock_resynthesized = lpc_slave_clock_resynthesized;
223 224
`else
	wire lpc_slave_clock_buffered;
225
	wire lpc_slave_tx_clock_resynthesized;
226
	wire lpc_slave_clock_resynthesized;
227
	assign lpc_slave_tx_clock_resynthesized = lpc_slave_clock_buffered;
228 229 230
	assign lpc_slave_clock_resynthesized = lpc_slave_clock_buffered;
`endif

231
	// Not enough PLLs on the iCE40 to actually double this clock
232
	assign lpc_debug_mirror_clock_dbl = lpc_slave_clock_resynthesized;
233

234
	// Debug port
235 236 237
`ifdef LPC_SLAVE_DEBUG
	wire [15:0] debug_leds;
`else
238
	reg [15:0] debug_leds = 0;
239
`endif
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257

	assign led_15 = debug_leds[15];
	assign led_14 = debug_leds[14];
	assign led_13 = debug_leds[13];
	assign led_12 = debug_leds[12];
	assign led_11 = debug_leds[11];
	assign led_10 = debug_leds[10];
	assign led_9 = debug_leds[9];
	assign led_8 = debug_leds[8];
	assign led_7 = debug_leds[7];
	assign led_6 = debug_leds[6];
	assign led_5 = debug_leds[5];
	assign led_4 = debug_leds[4];
	assign led_3 = debug_leds[3];
	assign led_2 = debug_leds[2];
	assign led_1 = debug_leds[1];
	assign led_0 = debug_leds[0];

258
	// LPC debug mirror port
259 260
	assign lpc_debug_mirror_clock = lpc_slave_clock_resynthesized;
	assign lpc_debug_mirror_clock_extern_uart = lpc_slave_clock_resynthesized;
261

262
	// Instantiate clock generator
263
	wire spi_core_pll_lock;
264
	wire platform_pll_unstable;
265
	wire slow_1843khz_uart_clock;
266 267 268 269
	wire slow_175khz_platform_clock;
	wire slow_183hz_platform_clock;
	wire slow_11hz_platform_clock;

270
	wire sequencer_clock;
271
	wire spi_core_clock;
272

273
`ifdef RESYNTHESIZE_LPC_CLOCK
274
	assign platform_pll_unstable = ~lpc_pll_lock;
275
`else
276
	assign platform_pll_unstable = 0;
277
`endif
278 279 280 281

	clock_generator clock_generator(
		// Main 12MHz platform clock
		.platform_clock(primary_platform_clock),
282
		.spi_core_pll_lock(spi_core_pll_lock),
283
		.slow_1843khz_uart_clock(slow_1843khz_uart_clock),
284 285 286 287
		.slow_175khz_platform_clock(slow_175khz_platform_clock),
		.slow_183hz_platform_clock(slow_183hz_platform_clock),
		.slow_11hz_platform_clock(slow_11hz_platform_clock),

288 289 290
		// Main 33MHz LPC clock
		.lpc_clock(lpc_slave_clock_resynthesized),
		.sequencer_clock(sequencer_clock),
291 292
		.spi_core_clock(spi_core_clock),
		.reset_lpc_derived_plls(~lpc_pll_lock)
293 294 295
	);

	// Generate power-on reset signals
296 297
	wire fpga_power_on_reset;
	reg fpga_power_on_reset_internal = 1;
298
	reg [3:0] fpga_power_on_reset_counter = 0;
299
	assign fpga_power_on_reset = fpga_power_on_reset_internal | platform_pll_unstable;
300 301
	always @(posedge primary_platform_clock or posedge platform_pll_unstable) begin
		if (platform_pll_unstable) begin
302
			fpga_power_on_reset_internal <= 1;
303 304 305 306
			fpga_power_on_reset_counter <= 0;
		end else begin
			if (fpga_power_on_reset_counter < 10) begin
				fpga_power_on_reset_counter <= fpga_power_on_reset_counter + 1;
307
				fpga_power_on_reset_internal <= 1;
308
			end else begin
309
				fpga_power_on_reset_internal <= 0;
310 311 312 313
			end
		end
	end

314
	// Instantiate LPC slave interface
315
	wire [27:0] lpc_slave_address;
316 317 318
	wire [7:0] lpc_slave_rx_data;
	reg [7:0] lpc_slave_tx_data;
	wire lpc_slave_tpm_cycle;
319
	wire lpc_slave_firmware_cycle;
320 321 322 323 324
	reg lpc_slave_continue = 0;
	reg lpc_slave_data_ack = 0;
	reg lpc_slave_exception_ack = 0;
	wire lpc_slave_address_ready;
	wire lpc_slave_data_ready;
325
	wire [2:0] lpc_slave_exception;
326 327 328 329 330 331 332 333
	wire lpc_slave_cycle_direction;
	reg [16:0] lpc_slave_irq_request = 0;
	reg lpc_slave_irq_tx_ready = 0;

`ifdef ENABLE_SERIAL_IRQ_SUPPORT
	wire lpc_slave_irq_tx_queued;
`endif

334 335 336 337 338 339 340 341 342 343
	reg [8:0] lpc_fw_input_xfer_write_addr;
	reg [7:0] lpc_fw_input_xfer_write_data;
	reg lpc_fw_input_xfer_write_wren;
	reg [8:0] lpc_fw_output_xfer_read_addr;
	reg [8:0] lpc_fw_output_xfer_read_addr_prev;
	wire [7:0] lpc_fw_output_xfer_read_data;

	wire [3:0] lpc_slave_fw_idsel;
	wire [3:0] lpc_slave_fw_msize;

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
`ifdef LPC_SLAVE_DEBUG
	wire [15:0] lpc_slave_debug_port;
`endif

	wire lpc_slave_data_direction;
	wire lpc_slave_irq_direction;
	wire [3:0] lpc_slave_data_out;
	wire [3:0] lpc_slave_data_in;

`ifdef ENABLE_SERIAL_IRQ_SUPPORT
	wire lpc_slave_irq_out;
	wire lpc_slave_irq_in;
`endif

	wire lpc_slave_frame_n_buffered;

360 361
	lpc_slave_interface #(
		.LPC_PERIPHERAL_ADDRESS_BASE_1(DEBUG_PORT_ADDRESS_HIGH),
362
		.LPC_PERIPHERAL_ADDRESS_BASE_2(DEBUG_PORT_ADDRESS_LOW),
363 364
		.LPC_PERIPHERAL_ADDRESS_BASE_3(IPMI_BT_PORT_BASE_ADDRESS),
		.LPC_PERIPHERAL_ADDRESS_BASE_5(HOST_UART_BASE_ADDRESS)
365
	) lpc_slave_interface (
366 367 368 369
		.address(lpc_slave_address),
		.tx_data(lpc_slave_tx_data),
		.rx_data(lpc_slave_rx_data),
		.tpm_cycle(lpc_slave_tpm_cycle),
370
		.firmware_cycle(lpc_slave_firmware_cycle),
371 372 373 374 375 376 377 378 379 380 381 382 383 384
		.continue(lpc_slave_continue),
		.data_ack(lpc_slave_data_ack),
		.exception_ack(lpc_slave_exception_ack),
		.address_ready(lpc_slave_address_ready),
		.data_ready(lpc_slave_data_ready),
		.exception(lpc_slave_exception),
		.data_direction(lpc_slave_cycle_direction),

`ifdef ENABLE_SERIAL_IRQ_SUPPORT
		.irq_request(lpc_slave_irq_request),
		.irq_tx_ready(lpc_slave_irq_tx_ready),
		.irq_tx_queued(lpc_slave_irq_tx_queued),
`endif

385 386
		.lpc_fw_input_xfer_write_addr(lpc_fw_input_xfer_write_addr),
		.lpc_fw_input_xfer_write_data(lpc_fw_input_xfer_write_data),
387
		.lpc_fw_input_xfer_write_clk(sequencer_clock),
388 389 390
		.lpc_fw_input_xfer_write_wren(lpc_fw_input_xfer_write_wren),
		.lpc_fw_output_xfer_read_addr(lpc_fw_output_xfer_read_addr),
		.lpc_fw_output_xfer_read_data(lpc_fw_output_xfer_read_data),
391
		.lpc_fw_output_xfer_read_clk(sequencer_clock),
392 393 394 395

		.fw_idsel(lpc_slave_fw_idsel),
		.fw_msize(lpc_slave_fw_msize),

396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
`ifdef LPC_SLAVE_DEBUG
		.debug_port(lpc_slave_debug_port),
`endif

		.lpc_data_out(lpc_slave_data_out),
		.lpc_data_in(lpc_slave_data_in),
		.lpc_data_direction(lpc_slave_data_direction),

`ifdef ENABLE_SERIAL_IRQ_SUPPORT
		.lpc_irq_out(lpc_slave_irq_out),
		.lpc_irq_in(lpc_slave_irq_in),
		.lpc_irq_direction(lpc_slave_irq_direction),
`endif

		.lpc_frame_n(lpc_slave_frame_n_buffered),
411
		.lpc_reset_n(lpc_slave_reset_n_buffered_gated),
412 413
		.lpc_rx_clock(lpc_slave_clock_resynthesized),
		.lpc_tx_clock(lpc_slave_tx_clock_resynthesized)
414 415
	);

416 417 418 419
`ifdef LPC_SLAVE_DEBUG
	assign debug_leds = lpc_slave_debug_port;
`endif

420 421 422
	// Control bidirectional interface
	// Work around yosys / arachne-pnr issues by instantiating each SB_IO manually
	SB_IO #(
423
		.PIN_TYPE(6'b100100),
424 425 426
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
427
		.PULLUP(1'b0),
428
`endif
429
		.NEG_TRIGGER(1'b0)
430 431 432
	) lpc_slave_addrdata_3_io (
		.PACKAGE_PIN(lpc_slave_addrdata_3),
		.OUTPUT_ENABLE(lpc_slave_data_direction & drive_host_interfaces),
433
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
434
		.D_OUT_0(lpc_slave_data_out[3]),
435
		.INPUT_CLK(lpc_slave_clock_resynthesized),
436 437
		.D_IN_0(lpc_slave_data_in[3]),
		.CLOCK_ENABLE(1'b1)
438 439
	);
	SB_IO #(
440
		.PIN_TYPE(6'b100100),
441 442 443
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
444
		.PULLUP(1'b0),
445
`endif
446
		.NEG_TRIGGER(1'b0)
447 448 449
	) lpc_slave_addrdata_2_io (
		.PACKAGE_PIN(lpc_slave_addrdata_2),
		.OUTPUT_ENABLE(lpc_slave_data_direction & drive_host_interfaces),
450
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
451
		.D_OUT_0(lpc_slave_data_out[2]),
452
		.INPUT_CLK(lpc_slave_clock_resynthesized),
453 454
		.D_IN_0(lpc_slave_data_in[2]),
		.CLOCK_ENABLE(1'b1)
455 456
	);
	SB_IO #(
457
		.PIN_TYPE(6'b100100),
458 459 460
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
461
		.PULLUP(1'b0),
462
`endif
463
		.NEG_TRIGGER(1'b0)
464 465 466
	) lpc_slave_addrdata_1_io (
		.PACKAGE_PIN(lpc_slave_addrdata_1),
		.OUTPUT_ENABLE(lpc_slave_data_direction & drive_host_interfaces),
467
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
468
		.D_OUT_0(lpc_slave_data_out[1]),
469
		.INPUT_CLK(lpc_slave_clock_resynthesized),
470 471
		.D_IN_0(lpc_slave_data_in[1]),
		.CLOCK_ENABLE(1'b1)
472 473
	);
	SB_IO #(
474
		.PIN_TYPE(6'b100100),
475 476 477
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
478
		.PULLUP(1'b0),
479
`endif
480
		.NEG_TRIGGER(1'b0)
481 482 483
	) lpc_slave_addrdata_0_io (
		.PACKAGE_PIN(lpc_slave_addrdata_0),
		.OUTPUT_ENABLE(lpc_slave_data_direction & drive_host_interfaces),
484
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
485
		.D_OUT_0(lpc_slave_data_out[0]),
486
		.INPUT_CLK(lpc_slave_clock_resynthesized),
487 488
		.D_IN_0(lpc_slave_data_in[0]),
		.CLOCK_ENABLE(1'b1)
489 490 491
	);
`ifdef ENABLE_SERIAL_IRQ_SUPPORT
	SB_IO #(
492
		.PIN_TYPE(6'b110101),
493 494 495
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
496
		.PULLUP(1'b0),
497
`endif
498
		.NEG_TRIGGER(1'b0)
499 500 501
	) lpc_slave_serirq_io (
		.PACKAGE_PIN(lpc_slave_serirq),
		.OUTPUT_ENABLE(lpc_slave_irq_direction & drive_host_interfaces),
502
		.INPUT_CLK(lpc_slave_clock_resynthesized),
503
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
504
		.D_OUT_0(lpc_slave_irq_out),
505 506
		.D_IN_0(lpc_slave_irq_in),
		.CLOCK_ENABLE(1'b1)
507 508 509 510 511 512 513 514 515
	);
`else
	SB_IO #(
		.PIN_TYPE(6'b000001),
		.PULLUP(1'b0)
	) lpc_slave_serirq_io (
		.PACKAGE_PIN(lpc_slave_serirq),
		.OUTPUT_ENABLE(1'b0)
	);
516 517
`endif
	SB_IO #(
518
		.PIN_TYPE(6'b100101),
519 520 521 522 523 524 525 526 527
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
		.PULLUP(1'b0),
`endif
		.NEG_TRIGGER(1'b0)
	) lpc_slave_addrdata_3_2_io (
		.PACKAGE_PIN(lpc_slave_addrdata_3_2),
		.OUTPUT_ENABLE(lpc_slave_data_direction & drive_host_interfaces),
528
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
529 530 531 532
		.D_OUT_0(lpc_slave_data_out[3]),
		.CLOCK_ENABLE(1'b1)
	);
	SB_IO #(
533
		.PIN_TYPE(6'b100101),
534 535 536 537 538 539 540 541 542
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
		.PULLUP(1'b0),
`endif
		.NEG_TRIGGER(1'b0)
	) lpc_slave_addrdata_2_2_io (
		.PACKAGE_PIN(lpc_slave_addrdata_2_2),
		.OUTPUT_ENABLE(lpc_slave_data_direction & drive_host_interfaces),
543
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
544 545 546 547
		.D_OUT_0(lpc_slave_data_out[2]),
		.CLOCK_ENABLE(1'b1)
	);
	SB_IO #(
548
		.PIN_TYPE(6'b100101),
549 550 551 552 553 554 555 556 557
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
		.PULLUP(1'b0),
`endif
		.NEG_TRIGGER(1'b0)
	) lpc_slave_addrdata_1_2_io (
		.PACKAGE_PIN(lpc_slave_addrdata_1_2),
		.OUTPUT_ENABLE(lpc_slave_data_direction & drive_host_interfaces),
558
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
559 560 561 562
		.D_OUT_0(lpc_slave_data_out[1]),
		.CLOCK_ENABLE(1'b1)
	);
	SB_IO #(
563
		.PIN_TYPE(6'b100101),
564 565 566 567 568 569 570 571 572
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
		.PULLUP(1'b0),
`endif
		.NEG_TRIGGER(1'b0)
	) lpc_slave_addrdata_0_2_io (
		.PACKAGE_PIN(lpc_slave_addrdata_0_2),
		.OUTPUT_ENABLE(lpc_slave_data_direction & drive_host_interfaces),
573
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
574 575 576 577 578
		.D_OUT_0(lpc_slave_data_out[0]),
		.CLOCK_ENABLE(1'b1)
	);
`ifdef ENABLE_SERIAL_IRQ_SUPPORT
	SB_IO #(
579
		.PIN_TYPE(6'b100101),
580 581 582 583 584 585 586 587 588
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
		.PULLUP(1'b0),
`endif
		.NEG_TRIGGER(1'b0)
	) lpc_slave_serirq_2_io (
		.PACKAGE_PIN(lpc_slave_serirq_2),
		.OUTPUT_ENABLE(lpc_slave_irq_direction & drive_host_interfaces),
589
		.OUTPUT_CLK(lpc_slave_tx_clock_resynthesized),
590 591 592 593 594 595 596 597 598 599 600
		.D_OUT_0(lpc_slave_irq_out),
		.CLOCK_ENABLE(1'b1)
	);
`else
	SB_IO #(
		.PIN_TYPE(6'b000001),
		.PULLUP(1'b0)
	) lpc_slave_serirq_2_io (
		.PACKAGE_PIN(lpc_slave_serirq_2),
		.OUTPUT_ENABLE(1'b0)
	);
601
`endif
602
`ifndef RESYNTHESIZE_LPC_CLOCK
603 604 605 606 607 608
	SB_PLL40_PAD #(
	) lpc_slave_pll (
		.RESETB(1'b1),
		.BYPASS(1'b1),
		.PACKAGEPIN(lpc_slave_clock),
		.PLLOUTGLOBAL(lpc_slave_clock_buffered)
609
	);
610
`endif
611 612
	SB_IO #(
		.PIN_TYPE(6'b000000),
613 614 615
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
616
		.PULLUP(1'b0),
617
`endif
618
		.NEG_TRIGGER(1'b0)
619 620 621
	) lpc_slave_frame_n_io (
		.PACKAGE_PIN(lpc_slave_frame_n),
		.OUTPUT_ENABLE(1'b0),
622
		.INPUT_CLK(lpc_slave_clock_resynthesized),
623 624
		.D_IN_0(lpc_slave_frame_n_buffered),
		.CLOCK_ENABLE(1'b1)
625 626
	);
	SB_IO #(
627
		.PIN_TYPE(6'b000000),
628 629 630
`ifdef ENABLE_LPC_PULLUPS
		.PULLUP(1'b1),
`else
631
		.PULLUP(1'b0),
632
`endif
633
		.NEG_TRIGGER(1'b0)
634 635 636
	) lpc_slave_reset_n_io (
		.PACKAGE_PIN(lpc_slave_reset_n),
		.OUTPUT_ENABLE(1'b0),
637
		.INPUT_CLK(primary_platform_clock),
638 639
		.D_IN_0(lpc_slave_reset_n_buffered),
		.CLOCK_ENABLE(1'b1)
640
	);
641

642
	// Instantiate SPI external master interface
643 644
	wire [31:0] spi_external_master_rx_data;
	reg [31:0] spi_external_master_tx_data = 0;
645
	reg [7:0] spi_external_master_dummy_cycle_count = 0;
646 647 648 649 650
	reg spi_external_master_cycle_start = 0;
	reg spi_external_master_hold_ss_active = 0;
	wire spi_external_master_transaction_complete;

	reg spi_external_master_passthrough = 0;
651
	reg spi_external_master_reset_n_buffered = 0;
652

653
	reg spi_external_master_qspi_mode_active = 0;
654
	reg spi_external_master_qspi_transfer_mode = 0;
655 656 657 658
	reg spi_external_master_qspi_transfer_direction = 0;
	wire spi_external_master_data_direction;
	wire spi_external_master_quad_mode_pin_enable;

659 660
	wire spi_external_master_clock_int;
	wire spi_external_master_mosi_int;
661
	wire spi_external_master_miso_int;
662
	wire spi_external_master_ss_n_int;
663 664
	wire spi_external_master_wp_n_int;
	wire spi_external_master_hold_n_int;
665

666
	wire spi_external_master_mosi_buffered;
667
	wire spi_external_master_miso_buffered;
668 669
	wire spi_external_master_wp_n_buffered;
	wire spi_external_master_hold_n_buffered;
670

671
	spi_master_interface_quad spi_master_interface_quad(
672
		.platform_clock(spi_core_clock),
673
		.reset(fpga_power_on_reset || (~lpc_slave_reset_n_buffered_gated)),
674 675
		.tx_data(spi_external_master_tx_data),
		.rx_data(spi_external_master_rx_data),
676 677
		.dummy_cycle_count(spi_external_master_dummy_cycle_count),
		.qspi_mode_active(spi_external_master_qspi_mode_active),
678
		.qspi_transfer_mode(spi_external_master_qspi_transfer_mode),
679
		.qspi_transfer_direction(spi_external_master_qspi_transfer_direction),
680 681 682 683 684
		.hold_ss_active(spi_external_master_hold_ss_active),
		.cycle_start(spi_external_master_cycle_start),
		.transaction_complete(spi_external_master_transaction_complete),

		.spi_clock(spi_external_master_clock_int),
685 686 687 688 689 690 691 692 693 694 695
		.spi_d0_out(spi_external_master_mosi_int),
		.spi_d0_in(spi_external_master_mosi_buffered),
		.spi_d1_out(spi_external_master_miso_int),
		.spi_d1_in(spi_external_master_miso_buffered),
		.spi_d2_out(spi_external_master_wp_n_int),
		.spi_d2_in(spi_external_master_wp_n_buffered),
		.spi_d3_out(spi_external_master_hold_n_int),
		.spi_d3_in(spi_external_master_hold_n_buffered),
		.spi_ss_n(spi_external_master_ss_n_int),
		.spi_data_direction(spi_external_master_data_direction),
		.spi_quad_mode_pin_enable(spi_external_master_quad_mode_pin_enable)
696 697
	);

698 699 700 701 702 703
	// Direct output pin assignments
	assign spi_external_master_clock = spi_external_master_clock_int;
	assign spi_external_master_ss_n = spi_external_master_ss_n_int;
	assign spi_external_master_reset_n = spi_external_master_reset_n_buffered;

	// Bidirectional I/O pin assignments
704
	SB_IO #(
705 706 707 708 709 710 711 712 713 714 715
		.PIN_TYPE(6'b101001),
		.PULLUP(1'b0)
	) spi_external_master_mosi_io (
		.PACKAGE_PIN(spi_external_master_mosi),
		.OUTPUT_ENABLE(!spi_external_master_quad_mode_pin_enable || (spi_external_master_data_direction & drive_host_interfaces)),
		.D_OUT_0(spi_external_master_mosi_int),
		.D_IN_0(spi_external_master_mosi_buffered)
	);

	SB_IO #(
		.PIN_TYPE(6'b101001),
716 717 718
		.PULLUP(1'b0)
	) spi_external_master_miso_io (
		.PACKAGE_PIN(spi_external_master_miso),
719 720
		.OUTPUT_ENABLE(spi_external_master_quad_mode_pin_enable && (spi_external_master_data_direction & drive_host_interfaces)),
		.D_OUT_0(spi_external_master_miso_int),
721 722 723
		.D_IN_0(spi_external_master_miso_buffered)
	);

724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
	SB_IO #(
		.PIN_TYPE(6'b101001),
		.PULLUP(1'b0)
	) spi_external_master_wp_n_io (
		.PACKAGE_PIN(spi_external_master_wp_n),
		.OUTPUT_ENABLE(!spi_external_master_quad_mode_pin_enable || (spi_external_master_data_direction & drive_host_interfaces)),
		.D_OUT_0(spi_external_master_wp_n_int),
		.D_IN_0(spi_external_master_wp_n_buffered)
	);

	SB_IO #(
		.PIN_TYPE(6'b101001),
		.PULLUP(1'b0)
	) spi_external_master_hold_n_io (
		.PACKAGE_PIN(spi_external_master_hold_n),
		.OUTPUT_ENABLE(!spi_external_master_quad_mode_pin_enable || (spi_external_master_data_direction & drive_host_interfaces)),
		.D_OUT_0(spi_external_master_hold_n_int),
		.D_IN_0(spi_external_master_hold_n_buffered)
	);

744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
	// Instantiate IPMI BT interface
	reg [8:0] ipmi_bt_input_xfer_write_addr_reg;
	reg [7:0] ipmi_bt_input_xfer_write_data_reg;
	reg ipmi_bt_input_xfer_write_wren_reg = 0;
	reg [8:0] ipmi_bt_output_xfer_read_addr;
	wire [7:0] ipmi_bt_output_xfer_read_data;

	reg ipmi_bt_bmc_to_host_ctl_sms_ack_reg = 0;
	reg ipmi_bt_bmc_to_host_ctl_attn_ack_reg = 0;
	reg ipmi_bt_host_to_bmc_ctl_attn_req_reg = 0;
	reg ipmi_bt_irq_ack_reg = 0;
	reg ipmi_bt_irq_bmc_reset_reg = 0;

	wire ipmi_bt_bmc_to_host_ctl_sms_req;
	wire ipmi_bt_bmc_to_host_ctl_attn_req;
	wire ipmi_bt_bmc_to_host_ctl_sms_ack_cont;
	wire ipmi_bt_bmc_to_host_ctl_attn_ack_cont;
	wire ipmi_bt_host_to_bmc_ctl_attn_req_cont;
	wire ipmi_bt_irq_ack_cont;
	wire ipmi_bt_irq_bmc_reset_cont;

	reg ipmi_bt_host_to_bmc_ctl_h_busy_reg = 0;
	wire ipmi_bt_bmc_to_host_ctl_b_busy;
	reg ipmi_bt_irq_enable = 0;
	wire ipmi_bt_irq_req;

770 771 772
	wire ipmi_bt_hiomap_new_window_req;
	reg ipmi_bt_hiomap_new_window_ack = 0;
	wire [27:0] ipmi_bt_hiomap_active_window_start_address;
773
	wire [27:0] ipmi_bt_hiomap_active_window_size_bytes;
774 775
	wire ipmi_bt_hiomap_window_type_write;

776 777
	wire ipmi_bt_hiomap_flush_req;
	reg ipmi_bt_hiomap_flush_ack = 0;
778
	wire [27:0] ipmi_bt_hiomap_flush_sector_count;
779
	wire ipmi_bt_hiomap_flush_type_erase;
780 781
	wire [27:0] ipmi_bt_hiomap_erase_address_offset;
	wire [27:0] ipmi_bt_hiomap_erase_sector_count;
782

783 784
	wire [27:0] ipmi_bt_hiomap_erase_address_step;
	wire [27:0] ipmi_bt_hiomap_program_address_step;
785
	wire [27:0] ipmi_bt_hiomap_def_win_size_bytes;
786

787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
	wire [7:0] ipmi_bt_slave_interface_debug_port;

	ipmi_bt_slave_interface ipmi_bt_slave_interface(
		.input_xfer_write_addr(ipmi_bt_input_xfer_write_addr_reg),
		.input_xfer_write_data(ipmi_bt_input_xfer_write_data_reg),
		.input_xfer_write_clk(sequencer_clock),
		.input_xfer_write_wren(ipmi_bt_input_xfer_write_wren_reg),
		.output_xfer_read_addr(ipmi_bt_output_xfer_read_addr),
		.output_xfer_read_data(ipmi_bt_output_xfer_read_data),
		.output_xfer_read_clk(sequencer_clock),

		.bmc_to_host_ctl_sms_req(ipmi_bt_bmc_to_host_ctl_sms_req),
		.bmc_to_host_ctl_sms_ack(ipmi_bt_bmc_to_host_ctl_sms_ack_reg),
		.bmc_to_host_ctl_attn_req(ipmi_bt_bmc_to_host_ctl_attn_req),
		.bmc_to_host_ctl_attn_ack(ipmi_bt_bmc_to_host_ctl_attn_ack_reg),
		.host_to_bmc_ctl_attn_req(ipmi_bt_host_to_bmc_ctl_attn_req_reg),
		.irq_ack(ipmi_bt_irq_ack_reg),
		.irq_bmc_reset(ipmi_bt_irq_bmc_reset_reg),

		.bmc_to_host_ctl_sms_ack_cont(ipmi_bt_bmc_to_host_ctl_sms_ack_cont),
		.bmc_to_host_ctl_attn_ack_cont(ipmi_bt_bmc_to_host_ctl_attn_ack_cont),
		.host_to_bmc_ctl_attn_req_cont(ipmi_bt_host_to_bmc_ctl_attn_req_cont),
		.irq_ack_cont(ipmi_bt_irq_ack_cont),
		.irq_bmc_reset_cont(ipmi_bt_irq_bmc_reset_cont),

		.h_busy(ipmi_bt_host_to_bmc_ctl_h_busy_reg),
		.b_busy(ipmi_bt_bmc_to_host_ctl_b_busy),

		.irq_enable(ipmi_bt_irq_enable),
		.irq_req(ipmi_bt_irq_req),

818 819 820 821 822 823
		.hiomap_new_window_req(ipmi_bt_hiomap_new_window_req),
		.hiomap_new_window_ack(ipmi_bt_hiomap_new_window_ack),
		.hiomap_active_window_start_address(ipmi_bt_hiomap_active_window_start_address),
		.hiomap_active_window_size_bytes(ipmi_bt_hiomap_active_window_size_bytes),
		.hiomap_window_type_write(ipmi_bt_hiomap_window_type_write),

824 825
		.hiomap_flush_req(ipmi_bt_hiomap_flush_req),
		.hiomap_flush_ack(ipmi_bt_hiomap_flush_ack),
826
		.hiomap_flush_sector_count(ipmi_bt_hiomap_flush_sector_count),
827
		.hiomap_flush_type_erase(ipmi_bt_hiomap_flush_type_erase),
828 829
		.hiomap_erase_address_offset(ipmi_bt_hiomap_erase_address_offset),
		.hiomap_erase_sector_count(ipmi_bt_hiomap_erase_sector_count),
830

831 832
		.hiomap_erase_address_step(ipmi_bt_hiomap_erase_address_step),
		.hiomap_program_address_step(ipmi_bt_hiomap_program_address_step),
833
		.hiomap_def_win_size_bytes(ipmi_bt_hiomap_def_win_size_bytes),
834

835 836
		.reset(fpga_power_on_reset || (~lpc_slave_reset_n_buffered_gated)),
		.logic_clk(sequencer_clock),
837
		.rtc_base_clock(primary_platform_clock),
838 839 840 841

		.debug_port(ipmi_bt_slave_interface_debug_port)
	);

842
	// Instantiate Flash block cache memory
843 844 845
	reg [27:0] flash_cache_addr_port_a;
	reg [27:0] flash_cache_addr_port_b;
	reg [27:0] flash_cache_read_addr;
846 847 848 849 850 851 852 853
	reg [7:0] flash_cache_write_data_port_a;
	reg [7:0] flash_cache_write_data_port_b;
	wire [7:0] flash_cache_read_data;
	reg flash_cache_wren_port_a = 0;
	reg flash_cache_wren_port_b = 0;
	reg flash_cache_port_ab_control_switch = 0;

	flash_block_cache flash_block_cache(
854 855 856
		.addr_port_a(flash_cache_addr_port_a[11:0]),
		.addr_port_b(flash_cache_addr_port_b[11:0]),
		.read_addr(flash_cache_read_addr[11:0]),
857 858 859 860 861 862 863 864 865
		.write_data_port_a(flash_cache_write_data_port_a),
		.write_data_port_b(flash_cache_write_data_port_b),
		.read_data(flash_cache_read_data),
		.wren_port_a(flash_cache_wren_port_a),
		.wren_port_b(flash_cache_wren_port_b),
		.port_ab_control_switch(flash_cache_port_ab_control_switch),
		.clk(sequencer_clock)
	);

866
	// Instantiate 16550-compatible UART
867 868 869 870 871 872 873 874
	reg [2:0] host_uart_3f8_address_reg = 0;
	reg [7:0] host_uart_3f8_data_out_reg = 0;
	wire [7:0] host_uart_3f8_data_in;
	reg host_uart_3f8_wren_reg = 0;
	reg host_uart_3f8_chip_select_reg = 0;
	reg host_uart_3f8_xfer_cycle_active_reg = 0;
	wire host_uart_3f8_ack;
	wire host_uart_3f8_irq;
875 876 877 878 879

	// WARNING: Hostboot expects a 1.8432MHz clock fed to the UART
	// This is the standard frequency used on the original PCs
	// Hostboot will blindly set the divisors assuming this is the
	// actual frequency fed to the UARTs...
880
	uart_top host_uart_3f8(
881 882 883
		.wb_clk_i(slow_1843khz_uart_clock),
		.wb_rst_i(fpga_power_on_reset || (~lpc_slave_reset_n_buffered_gated)),

884 885 886 887 888 889 890
		.wb_adr_i(host_uart_3f8_address_reg),
		.wb_dat_i(host_uart_3f8_data_out_reg),
		.wb_dat_o(host_uart_3f8_data_in),
		.wb_we_i(host_uart_3f8_wren_reg),
		.wb_stb_i(host_uart_3f8_chip_select_reg),
		.wb_cyc_i(host_uart_3f8_xfer_cycle_active_reg),
		.wb_ack_o(host_uart_3f8_ack),
891

892
		.int_o(host_uart_3f8_irq),
893 894 895 896 897 898 899 900 901 902 903

		.stx_pad_o(host_uart_tx),
		.srx_pad_i(host_uart_rx),

		// Not used
		.cts_pad_i(1'b0),
		.dsr_pad_i(1'b0),
		.ri_pad_i(1'b0),
		.dcd_pad_i(1'b0)
	);

904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
	reg [3:0] lpc_reset_gate_counter = 0;
`ifdef RESYNTHESIZE_LPC_CLOCK
	reg [15:0] pll_unlock_counter = 0;
`endif
	reg pll_reset_request = 0;
	reg [15:0] clock_watchdog_counter = 0;
	reg clock_watchdog_reset_request = 0;
`ifndef RESYNTHESIZE_LPC_CLOCK
	reg sequencer_clock_prev = 0;
`endif
	always @(posedge primary_platform_clock) begin
`ifdef RESYNTHESIZE_LPC_CLOCK
		if (!lpc_pll_lock) begin
			if (pll_unlock_counter < 1024) begin
				pll_unlock_counter <= pll_unlock_counter + 1;
				pll_reset_request <= 0;
			end else begin
				if (pll_unlock_counter < 2048) begin
					pll_unlock_counter <= pll_unlock_counter + 1;
					pll_reset_request <= 1;
				end else begin
					pll_unlock_counter <= 0;
					pll_reset_request <= 0;
				end
			end
		end else begin
			pll_unlock_counter <= 0;
			pll_reset_request <= 0;
		end
`endif
		if (!lpc_slave_reset_n_buffered || pll_reset_request || clock_watchdog_reset_request) begin
			if (pll_reset_request || clock_watchdog_reset_request) begin
				lpc_slave_reset_n_buffered_gated <= 0;
			end else begin
938
				if (lpc_reset_gate_counter < 4) begin
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
					lpc_reset_gate_counter <= lpc_reset_gate_counter + 1;
				end else begin
					lpc_slave_reset_n_buffered_gated <= 0;
				end
			end
		end else begin
			lpc_slave_reset_n_buffered_gated <= 1;
			lpc_reset_gate_counter <= 0;
		end

`ifndef RESYNTHESIZE_LPC_CLOCK
		if (sequencer_clock == sequencer_clock_prev) begin
			if (clock_watchdog_counter < 32) begin
				clock_watchdog_counter <= clock_watchdog_counter + 1;
				clock_watchdog_reset_request <= 0;
			end else begin
				clock_watchdog_reset_request <= 1;
			end
		end else begin
			clock_watchdog_counter <= 0;
		end
		sequencer_clock_prev <= sequencer_clock;
`endif
	end

964 965
	parameter LPC_BRIDGE_INITIALIZE_STATE_01 = 0;
	parameter LPC_BRIDGE_INITIALIZE_STATE_02 = 1;
966 967 968
	parameter LPC_BRIDGE_INITIALIZE_STATE_03 = 2;
	parameter LPC_BRIDGE_INITIALIZE_STATE_04 = 3;
	parameter LPC_BRIDGE_INITIALIZE_STATE_05 = 4;
969 970
	parameter LPC_BRIDGE_INITIALIZE_STATE_06 = 5;
	parameter LPC_BRIDGE_INITIALIZE_STATE_07 = 6;
971 972 973 974 975 976 977 978 979 980 981
	parameter LPC_BRIDGE_INITIALIZE_STATE_08 = 7;
	parameter LPC_BRIDGE_INITIALIZE_STATE_09 = 8;
	parameter LPC_BRIDGE_INITIALIZE_STATE_10 = 9;
	parameter LPC_BRIDGE_INITIALIZE_STATE_11 = 10;
	parameter LPC_BRIDGE_INITIALIZE_STATE_12 = 11;
	parameter LPC_BRIDGE_INITIALIZE_STATE_13 = 12;
	parameter LPC_BRIDGE_INITIALIZE_STATE_14 = 13;
	parameter LPC_BRIDGE_INITIALIZE_STATE_15 = 14;
	parameter LPC_BRIDGE_TRANSFER_STATE_IDLE = 16;
	parameter LPC_BRIDGE_TRANSFER_STATE_TR01 = 17;
	parameter LPC_BRIDGE_TRANSFER_STATE_IO01 = 18;
982 983 984 985
	parameter LPC_BRIDGE_TRANSFER_STATE_IW01 = 32;
	parameter LPC_BRIDGE_TRANSFER_STATE_IW02 = 33;
	parameter LPC_BRIDGE_TRANSFER_STATE_IW03 = 34;
	parameter LPC_BRIDGE_TRANSFER_STATE_IW04 = 35;
986
	parameter LPC_BRIDGE_TRANSFER_STATE_IW05 = 36;
987 988 989 990
	parameter LPC_BRIDGE_TRANSFER_STATE_IR01 = 64;
	parameter LPC_BRIDGE_TRANSFER_STATE_IR02 = 65;
	parameter LPC_BRIDGE_TRANSFER_STATE_IR03 = 66;
	parameter LPC_BRIDGE_TRANSFER_STATE_IR04 = 67;
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
	parameter LPC_BRIDGE_TRANSFER_STATE_WR01 = 128;
	parameter LPC_BRIDGE_TRANSFER_STATE_WR02 = 129;
	parameter LPC_BRIDGE_TRANSFER_STATE_WR03 = 130;
	parameter LPC_BRIDGE_TRANSFER_STATE_WR04 = 131;
	parameter LPC_BRIDGE_TRANSFER_STATE_WR05 = 132;
	parameter LPC_BRIDGE_TRANSFER_STATE_WR06 = 133;
	parameter LPC_BRIDGE_TRANSFER_STATE_WR07 = 134;
	parameter LPC_BRIDGE_TRANSFER_STATE_WR08 = 135;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD01 = 192;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD02 = 193;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD03 = 194;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD04 = 195;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD05 = 196;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD06 = 197;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD07 = 198;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD08 = 199;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD09 = 200;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD10 = 201;
	parameter LPC_BRIDGE_TRANSFER_STATE_RD11 = 202;
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
	parameter LPC_BRIDGE_TRANSFER_STATE_RC01 = 224;
	parameter LPC_BRIDGE_TRANSFER_STATE_RC02 = 225;
	parameter LPC_BRIDGE_TRANSFER_STATE_RC03 = 226;

	parameter BLOCK_CACHE_INITIALIZE_STATE_01 = 0;
	parameter BLOCK_CACHE_TRANSFER_STATE_IDLE = 8;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD01 = 16;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD02 = 17;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD03 = 18;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD04 = 19;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD05 = 20;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD06 = 21;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD07 = 22;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD08 = 23;
	parameter BLOCK_CACHE_TRANSFER_STATE_RD09 = 24;
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
	parameter BLOCK_CACHE_TRANSFER_STATE_EW01 = 64;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW02 = 65;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW03 = 66;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW04 = 67;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW05 = 68;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW06 = 69;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW07 = 70;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW08 = 71;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW09 = 72;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW10 = 73;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW11 = 74;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW12 = 75;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW13 = 76;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW14 = 77;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW15 = 78;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW16 = 79;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW17 = 80;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW18 = 81;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW19 = 82;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW20 = 83;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW21 = 84;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW22 = 85;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW23 = 86;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW24 = 87;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW25 = 88;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW26 = 89;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW27 = 90;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW28 = 91;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW29 = 92;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW30 = 93;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW31 = 94;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW32 = 95;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW33 = 96;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW34 = 97;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW35 = 98;
	parameter BLOCK_CACHE_TRANSFER_STATE_EW36 = 99;
1061
	parameter BLOCK_CACHE_TRANSFER_STATE_EW37 = 100;
1062
	parameter BLOCK_CACHE_TRANSFER_STATE_EW38 = 101;
1063
	parameter BLOCK_CACHE_TRANSFER_STATE_EW39 = 102;
1064 1065

	// Main sequencer
1066
	reg [7:0] fw_transfer_state = 0;
1067
	reg [7:0] spi_reset_counter = 0;
1068 1069
	reg [27:0] spi_byte_write_count = 0;
	reg [27:0] spi_byte_read_count = 0;
1070
	reg [27:0] lpc_slave_address_reg = 0;
1071
	reg [7:0] lpc_slave_rx_data_reg = 0;
1072
	reg [1:0] lpc_done_pulse_counter = 0;
1073

1074 1075 1076 1077 1078
	reg lpc_slave_address_ready_reg = 0;
	reg lpc_slave_data_ready_reg = 0;
	reg lpc_slave_tpm_cycle_reg = 0;
	reg lpc_slave_firmware_cycle_reg = 0;
	reg lpc_slave_cycle_direction_reg = 0;
1079
	reg lpc_slave_write_complete = 0;
1080

1081
	reg [27:0] hiomap_active_window_start_address = 0;
1082
	reg [27:0] hiomap_active_window_size_bytes = 0;
1083
	reg hiomap_window_type_write = 0;
1084
	reg hiomap_flush_type_erase = 0;
1085
	reg [27:0] hiomap_erase_address_offset = 0;
1086 1087 1088 1089

	// Flash block cache handler
	reg [7:0] cache_load_state = 0;
	reg use_flash_sector_cache = 0;
1090 1091 1092
	reg [27:0] hiomap_current_erase_address = 0;
	reg [27:0] hiomap_current_write_address = 0;
	reg [27:0] sector_count_erase = 0;
1093

1094 1095 1096 1097
`ifdef LPC_SLAVE_DEBUG
	reg [15:0] port_80h_register;
`endif

1098
	always @(posedge sequencer_clock) begin
1099
		if (fpga_power_on_reset || (~lpc_slave_reset_n_buffered_gated)) begin
1100
			fw_transfer_state <= LPC_BRIDGE_INITIALIZE_STATE_01;
1101
			cache_load_state <= BLOCK_CACHE_INITIALIZE_STATE_01;
1102
			spi_external_master_cycle_start <= 0;
1103
			spi_external_master_reset_n_buffered <= 1'b0;
1104
			spi_external_master_hold_ss_active <= 0;
1105
			lpc_fw_input_xfer_write_wren <= 0;
1106
			flash_cache_wren_port_b <= 0;
1107
			lpc_slave_irq_request <= 0;
1108
		end else begin
1109 1110
			case (cache_load_state)
				BLOCK_CACHE_INITIALIZE_STATE_01: begin
1111 1112 1113 1114 1115 1116 1117
					// Reset caching system
					use_flash_sector_cache <= 0;
					hiomap_active_window_start_address <= 0;
					hiomap_active_window_size_bytes <= ipmi_bt_hiomap_def_win_size_bytes;
					hiomap_window_type_write = 0;
					hiomap_flush_type_erase = 0;

1118 1119 1120 1121 1122 1123
					if (fw_transfer_state == LPC_BRIDGE_TRANSFER_STATE_IDLE) begin
						// Main sequencer initialized and ready
						cache_load_state <= BLOCK_CACHE_TRANSFER_STATE_IDLE;
					end
				end
				BLOCK_CACHE_TRANSFER_STATE_IDLE: begin
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
					if (fw_transfer_state == LPC_BRIDGE_TRANSFER_STATE_IDLE) begin
						// Main transfer state machine has returned to idle, it is now safe to take control of the SPI flash core if needed
						if (ipmi_bt_hiomap_new_window_req && flash_cache_port_ab_control_switch) begin
							// Latch current HIOMAP window status
							hiomap_active_window_start_address <= ipmi_bt_hiomap_active_window_start_address;
							hiomap_active_window_size_bytes <= ipmi_bt_hiomap_active_window_size_bytes;
							hiomap_window_type_write <= ipmi_bt_hiomap_window_type_write;

							// Determine if window is cacheable
							if ((ipmi_bt_hiomap_active_window_size_bytes > 0) && (ipmi_bt_hiomap_active_window_size_bytes <= HIOMAP_MAX_CACHE_SIZE_BYTES)) begin
								// Cacheable request
								use_flash_sector_cache <= 1;
								cache_load_state <= BLOCK_CACHE_TRANSFER_STATE_RD01;
							end else begin
								// Uncacheable request
								use_flash_sector_cache <= 0;
								ipmi_bt_hiomap_new_window_ack <= 1;
1141
								cache_load_state <= BLOCK_CACHE_TRANSFER_STATE_RD09;
1142
							end
1143
						end
1144
						if (ipmi_bt_hiomap_flush_req) begin
1145 1146 1147
							if (ipmi_bt_hiomap_window_type_write
								&& (!ipmi_bt_hiomap_flush_type_erase
									|| (ipmi_bt_hiomap_flush_type_erase && ((ipmi_bt_hiomap_erase_address_offset + ipmi_bt_hiomap_erase_sector_count) <= ipmi_bt_hiomap_active_window_size_bytes)))
1148
`ifdef BLOCK_GUARD_PARTITION_WRITES
1149 1150
								&& (((ipmi_bt_hiomap_active_window_start_address + ipmi_bt_hiomap_active_window_size_bytes) < GUARD_PARTITION_START_ADDRESS)
								|| (ipmi_bt_hiomap_active_window_start_address > GUARD_PARTITION_END_ADDRESS))
1151 1152
`endif
`ifdef BLOCK_NONESSENTIAL_WRITES
1153 1154 1155 1156 1157 1158 1159
								&& ((((ipmi_bt_hiomap_active_window_start_address + ipmi_bt_hiomap_active_window_size_bytes) >= VPD_PARTITION_START_ADDRESS)
									&& ((ipmi_bt_hiomap_active_window_start_address + ipmi_bt_hiomap_active_window_size_bytes) <= VPD_PARTITION_END_ADDRESS))
`ifndef BLOCK_NVRAM_PARTITION_WRITES
								|| (((ipmi_bt_hiomap_active_window_start_address + ipmi_bt_hiomap_active_window_size_bytes) >= NVRAM_PARTITION_START_ADDRESS)
									&& ((ipmi_bt_hiomap_active_window_start_address + ipmi_bt_hiomap_active_window_size_bytes) <= NVRAM_PARTITION_END_ADDRESS))
`endif
									)
1160 1161 1162
`endif
								) begin

1163
								// Latch request type and parameters
1164
								hiomap_flush_type_erase <= ipmi_bt_hiomap_flush_type_erase;
1165 1166 1167 1168 1169 1170
								hiomap_erase_address_offset <= ipmi_bt_hiomap_erase_address_offset;
								if (ipmi_bt_hiomap_flush_type_erase) begin
									sector_count_erase <= ipmi_bt_hiomap_erase_sector_count;
								end else begin
									sector_count_erase <= ipmi_bt_hiomap_flush_sector_count;
								end
1171

1172
								// Initialize erase and write pointers
1173 1174 1175 1176 1177 1178
								if (ipmi_bt_hiomap_flush_type_erase) begin
									hiomap_current_erase_address <= ipmi_bt_hiomap_active_window_start_address + ipmi_bt_hiomap_erase_address_offset;
								end else begin
									hiomap_current_erase_address <= ipmi_bt_hiomap_active_window_start_address;
								end
								hiomap_current_write_address <= ipmi_bt_hiomap_active_window_start_address;
1179

1180 1181 1182 1183 1184
								// Initiate subsector erase
								cache_load_state <= BLOCK_CACHE_TRANSFER_STATE_EW01;
							end else begin
								// Silently fail write to avoid system deadlock
								ipmi_bt_hiomap_flush_ack <= 1;
1185
								cache_load_state <= BLOCK_CACHE_TRANSFER_STATE_EW38;
1186
							end
1187
						end
1188
					end
1189 1190
				end
				BLOCK_CACHE_TRANSFER_STATE_RD01: begin