From 080b8788b19cfcfdfd1a5c42b8a23558c3767ee2 Mon Sep 17 00:00:00 2001 From: Raptor Engineering Development Team Date: Fri, 19 Jan 2018 07:09:07 -0600 Subject: Add I2C write capability Add front panel LED override --- I2C_SLAVE_LICENSE | 1 + i2c_slave.v | 11 +++++++++-- main.v | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/I2C_SLAVE_LICENSE b/I2C_SLAVE_LICENSE index 1ae7d03..6b96e26 100644 --- a/I2C_SLAVE_LICENSE +++ b/I2C_SLAVE_LICENSE @@ -1,6 +1,7 @@ MIT License Copyright (c) 2014-2016 Peter Samarin +Copyright (c) 2017-2018 Raptor Engineering, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/i2c_slave.v b/i2c_slave.v index 14c97f6..ca1b687 100644 --- a/i2c_slave.v +++ b/i2c_slave.v @@ -1,5 +1,5 @@ // Copyright © 2014-2016 Peter Samarin -// Copyright © 2017 Raptor Engineering, LLC +// Copyright © 2017-2018 Raptor Engineering, LLC // All Rights Reserved // // See I2C_SLAVE_LICENSE file for licensing details @@ -20,7 +20,8 @@ module i2c_slave( output wire read_req, input wire [7:0] data_to_master, output wire data_valid, - output wire [7:0] data_from_master + output wire [7:0] data_from_master, + output wire [7:0] write_cycle_count ); parameter [6:0] SLAVE_ADDR = 0; @@ -47,6 +48,7 @@ module i2c_slave( reg scl_falling_reg = 1'b0; // Address and data received from master reg [6:0] addr_reg = 1'b0; reg [7:0] data_reg = 1'b0; // Delayed SCL (by 1 clock cycle, and by 2 clock cycles) + reg [7:0] wr_cyc_count_reg = 8'b00000000; reg scl_reg = 1'b1; reg scl_prev_reg = 1'b1; // Slave writes on scl wire scl_wen_reg = 1'b0; @@ -110,6 +112,7 @@ module i2c_slave( if (start_reg == 1'b1) begin state_reg <= i2c_get_address_and_cmd; bits_processed_reg <= 0; + wr_cyc_count_reg <= 0; end end i2c_get_address_and_cmd : begin @@ -163,6 +166,7 @@ module i2c_slave( end if (bits_processed_reg == 7) begin data_valid_reg <= 1'b1; + wr_cyc_count_reg <= wr_cyc_count_reg + 1; end end if (scl_falling_reg == 1'b1 && bits_processed_reg == 8) begin @@ -231,10 +235,12 @@ module i2c_slave( if (start_reg == 1'b1) begin state_reg <= i2c_get_address_and_cmd; bits_processed_reg <= 0; + wr_cyc_count_reg <= 0; end if (stop_reg == 1'b1) begin state_reg <= i2c_idle; bits_processed_reg <= 0; + wr_cyc_count_reg <= 0; end if (rst == 1'b1) begin state_reg <= i2c_idle; @@ -254,6 +260,7 @@ module i2c_slave( // Master writes assign data_valid = data_valid_reg; assign data_from_master = data_reg; + assign write_cycle_count = wr_cyc_count_reg; // Master reads assign read_req = read_req_reg; diff --git a/main.v b/main.v index 1ccc6be..fc3b4a0 100644 --- a/main.v +++ b/main.v @@ -253,6 +253,7 @@ module system_fpga_top wire i2c_read_req; reg [7:0] i2c_data_to_master = 8'b00000000; wire [7:0] i2c_data_from_master; + wire [7:0] i2c_write_cycle_count; wire i2c_data_valid; wire i2c_rst = 1'b0; reg [7:0] i2c_reg_cur = 8'b00000000; @@ -270,8 +271,10 @@ module system_fpga_top parameter i2c_vendor_id_reg_addr2 = i2c_vendor_id_reg_addr1 + 1; parameter i2c_vendor_id_reg_addr3 = i2c_vendor_id_reg_addr1 + 2; parameter i2c_vendor_id_reg_addr4 = i2c_vendor_id_reg_addr1 + 3; + parameter i2c_led_override_reg_addr = 8'b00010000; reg [15:0] i2c_pg_reg = 1'b0; reg i2c_clr_err = 1'b0; + reg [7:0] i2c_write_reg_latch = 0; // Front panel control signals wire panel_nic1_led_cathode_std; @@ -281,6 +284,10 @@ module system_fpga_top reg [2:0] bmc_startup_fader = 3'b000; reg [2:0] bmc_startup_staggered_fader = 3'b000; reg bmc_startup_staggered_fader_common = 1'b0; + reg hostboot_startup_fader_common_low_internal = 1'b0; + reg hostboot_startup_fader_common_low = 1'b0; + reg hostboot_startup_fader_common_high = 1'b0; + reg [7:0] led_override_request = 8'b00000000; // Implement nasty ring oscillator for fallback use when main system clock is offline // Thanks to Clifford Wolf for the idea and basic code! @@ -338,7 +345,8 @@ module system_fpga_top .read_req(i2c_read_req), .data_to_master(i2c_data_to_master), .data_valid(i2c_data_valid), - .data_from_master(i2c_data_from_master) + .data_from_master(i2c_data_from_master), + .write_cycle_count(i2c_write_cycle_count) ); // Generate BMC startup "Knight Rider" display for front panel @@ -414,6 +422,16 @@ module system_fpga_top end else begin bmc_startup_staggered_fader_common = 1'b1; end + if (fader_pwm_counter >= 32) begin + hostboot_startup_fader_common_low_internal = 1'b0; + end else begin + hostboot_startup_fader_common_low_internal = 1'b1; + end + if (fader_pwm_counter >= (fader_pwm_level >> 1) + 32) begin + hostboot_startup_fader_common_high = 1'b0; + end else begin + hostboot_startup_fader_common_high = 1'b1; + end end always @(posedge clk_in) begin @@ -430,6 +448,14 @@ module system_fpga_top bmc_startup_staggered_fader[1] = 1'b0; bmc_startup_staggered_fader[2] = bmc_startup_staggered_fader_common; end + + if (fader_sequence_step == 0) begin + hostboot_startup_fader_common_low = hostboot_startup_fader_common_high; + end else if (fader_sequence_step == 1) begin + hostboot_startup_fader_common_low = hostboot_startup_fader_common_low_internal; + end else begin + hostboot_startup_fader_common_low = hostboot_startup_fader_common_low_internal; + end end // Determine BMC boot phase @@ -451,7 +477,6 @@ module system_fpga_top assign i2c_rst = 1'b0; // Handle I2C - // 2 8-bit registers with PGOOD state on error always @(posedge clk_in) begin i2c_clr_err <= 1'b0; @@ -463,6 +488,17 @@ module system_fpga_top if (((i2c_data_from_master) == i2c_clr_err_addr)) begin i2c_clr_err <= 1'b1; end + + // handle write setup + if (i2c_write_cycle_count == 1) begin + i2c_write_reg_latch <= i2c_data_from_master; + end else if (i2c_write_cycle_count == 2) begin + case (i2c_write_reg_latch) + i2c_led_override_reg_addr: begin + led_override_request <= i2c_data_from_master; + end + endcase + end end else if (i2c_read_req == 1'b1) begin i2c_reg_cur <= i2c_reg_cur + 1; @@ -907,9 +943,21 @@ module system_fpga_top panel_nic2_led_cathode = ~bmc_startup_fader[1]; panel_uid_led = ~bmc_startup_fader[2]; end else if (bmc_boot_phase == 2) begin - panel_nic1_led_cathode = panel_nic1_led_cathode_std; - panel_nic2_led_cathode = panel_nic2_led_cathode_std; - panel_uid_led = panel_uid_led_std; + if (led_override_request != 0) begin + if (led_override_request[3]) begin + panel_nic1_led_cathode = ~(led_override_request[0] & hostboot_startup_fader_common_high); + panel_nic2_led_cathode = ~(led_override_request[1] & hostboot_startup_fader_common_high); + panel_uid_led = ~(led_override_request[2] & hostboot_startup_fader_common_high); + end else begin + panel_nic1_led_cathode = ~(led_override_request[0] & hostboot_startup_fader_common_low); + panel_nic2_led_cathode = ~(led_override_request[1] & hostboot_startup_fader_common_low); + panel_uid_led = ~(led_override_request[2] & hostboot_startup_fader_common_low); + end + end else begin + panel_nic1_led_cathode = panel_nic1_led_cathode_std; + panel_nic2_led_cathode = panel_nic2_led_cathode_std; + panel_uid_led = panel_uid_led_std; + end end else begin panel_nic1_led_cathode = 1'b1; panel_nic2_led_cathode = 1'b1; -- cgit v1.2.1