diff options
Diffstat (limited to 'fpga/usrp3/lib/control/serial_to_settings.v')
-rw-r--r-- | fpga/usrp3/lib/control/serial_to_settings.v | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/control/serial_to_settings.v b/fpga/usrp3/lib/control/serial_to_settings.v new file mode 100644 index 000000000..53e112a62 --- /dev/null +++ b/fpga/usrp3/lib/control/serial_to_settings.v @@ -0,0 +1,111 @@ + + +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 |