Files
b210-k7-fpga/lib/control/serial_to_settings.v
T
Ben Hilburn 29086f9001 b2xx: Updating FPGA source with recent bugfixes.
Original-commit: 4b4365a517938b365af57674a3ab1462432c2c3a
2013-12-03 10:35:35 -08:00

112 lines
2.2 KiB
Verilog

module serial_to_settings
(
input clk,
input reset,
// Serial signals (async)
input scl,
input sda,
// Settngs bus out
output reg set_stb,
output reg [7:0] set_addr,
output reg [31:0] set_data
);
reg [2:0] state;
localparam SEARCH = 3'h0;
localparam ADDRESS = 3'h1;
localparam DATA = 3'h2;
localparam STOP1 = 3'h3;
localparam STOP2 = 3'h4;
reg scl_pre_reg, scl_reg, scl_reg2;
reg sda_pre_reg, sda_reg, sda_reg2;
reg [4:0] counter;
always @(posedge clk) begin
scl_reg2 <= scl_reg;
scl_reg <= scl_pre_reg;
scl_pre_reg <= scl;
sda_reg2 <= sda_reg;
sda_reg <= sda_pre_reg;
sda_pre_reg <= sda;
end
always @(posedge clk)
if (reset) begin
state <= SEARCH;
counter <= 0;
set_addr <= 0;
set_data <= 0;
set_stb <= 0;
end else begin
case(state)
//
// Search for I2C like start indication: SDA goes low whilst clock is high.
//
SEARCH: begin
set_stb <= 0;
// Look for START.
if (scl_reg && scl_reg2 && !sda_reg && sda_reg2) begin
state <= ADDRESS;
counter <= 0;
end
end
//
// Count 8 Address bits.
// Master changes SDA on falling edge of SCL, we sample on the rising edge.
//
ADDRESS: begin
if (scl_reg && !scl_reg2) begin
set_addr[7:0] <= {set_addr[6:0],sda_reg};
if (counter == 7) begin
state <= DATA;
counter <= 0;
end else
counter <= counter + 1;
end
end
//
// Count 32 data bits.
// Master changes SDA on falling edge of SCL, we sample on the rising edge.
//
DATA: begin
if (scl_reg && !scl_reg2) begin
set_data[31:0] <= {set_data[30:0],sda_reg};
if (counter == 31) begin
state <= STOP1;
counter <= 0;
end else
counter <= counter + 1;
end
end
//
// Looks for rising SCL edge before STOP bit.
//
STOP1: begin
if (scl_reg && !scl_reg2) begin
state <= STOP2;
end
end
//
// Looks for STOP bit
//
STOP2: begin
if (scl_reg && scl_reg2 && sda_reg && !sda_reg2) begin
state <= SEARCH;
counter <= 0;
set_stb <= 1;
end
end
endcase // case(state)
end // else: !if(reset)
endmodule // serial_to_settings