From 9620173d39dcd3bf54fa794c0571a1e4bab183e2 Mon Sep 17 00:00:00 2001 From: Dobrica Pavlinusic Date: Thu, 30 Dec 2021 17:24:49 +0100 Subject: [PATCH] i2c passthru bridge from rpi to tuner --- i2c.v | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ i2c_bridge.v | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 i2c.v create mode 100644 i2c_bridge.v diff --git a/i2c.v b/i2c.v new file mode 100644 index 0000000..079b4e3 --- /dev/null +++ b/i2c.v @@ -0,0 +1,58 @@ +`include "i2c_bridge.v" + +module top( + input clk, + + inout rtc_sda, + inout rtc_scl, + + inout tuner_sda, + inout tuner_scl, + + output green_led_d7, + output orange_led_d8, + output red_led_d5, + output yellow_led_d6 +); + + assign green_led_d7 = 1; + assign orange_led_d8 = 1; + assign red_led_d5 = 1; + assign yellow_led_d6 = 1; + + localparam bridge_clk_div = 3; // div = 1+2^n, 24/(1+2^2)=4 MHz + reg [bridge_clk_div:0] bridge_cnt; + always @(posedge clk) // 24 MHz + begin + if(bridge_cnt[bridge_clk_div]) + bridge_cnt <= 0; + else + bridge_cnt <= bridge_cnt + 1; + end + wire clk_bridge_en = bridge_cnt[bridge_clk_div]; + + wire [1:0] i2c_sda_i = {rtc_sda, tuner_sda}; + wire [1:0] i2c_sda_t; + i2c_bridge i2c_sda_bridge_i + ( + .clk(clk), + .clk_en(clk_bridge_en), + .i(i2c_sda_i), + .t(i2c_sda_t) + ); + assign rtc_sda = i2c_sda_t[1] ? 1'bz : 1'b0; + assign tuner_sda = i2c_sda_t[0] ? 1'bz : 1'b0; + + wire [1:0] i2c_scl_i = {rtc_scl, tuner_scl}; + wire [1:0] i2c_scl_t; + i2c_bridge i2c_scl_bridge_i + ( + .clk(clk), + .clk_en(clk_bridge_en), + .i(i2c_scl_i), + .t(i2c_scl_t) + ); + assign rtc_scl = i2c_scl_t[1] ? 1'bz : 1'b0; + assign tuner_scl = i2c_scl_t[0] ? 1'bz : 1'b0; + +endmodule diff --git a/i2c_bridge.v b/i2c_bridge.v new file mode 100644 index 0000000..643bce9 --- /dev/null +++ b/i2c_bridge.v @@ -0,0 +1,44 @@ +`default_nettype none +module i2c_bridge +( + input wire clk, // any + input wire clk_en, // 1-clk pulse, repeats 1.5-6 MHz + input wire [1:0] i, // inputs + output wire [1:0] t // tristate 0->0 1->Z +); + reg [1:0] state, next_state; + + always @(posedge clk) + case(state) + 2'd0: begin + if(i[0]) + next_state <= 3; + else + next_state <= 0; + end + + 2'd1: begin + if(i[1]) + next_state <= 3; + else + next_state <= 1; + end + + default: begin + if(i[0]==0 && i[1]==1) + next_state <= 0; + else if(i[1]==0 && i[0]==1) + next_state <= 1; + else + next_state <= 3; + end + endcase + + always @(posedge clk) + if(clk_en) + state <= next_state; + + assign t[1] = state == 2'd0 ? 0:1; + assign t[0] = state == 2'd1 ? 0:1; + +endmodule -- 2.20.1