当前位置: 首页 > news >正文

基于FPGA的IIC多通道选择器(IIC Switch/Bridge)

基于FPGA的IIC多通道选择器(IIC Switch/Bridge)

  • 1,背景
  • 2,系统框图
  • 3,完整模块代码

1,背景

在项目中,一个FPGA芯片上接了一路IIC Master,至少一路IIC Slave,当IIC Master想要直接访问IIC slave的时候,在FPGA中并不能直接将SCL和SDA端口直接连接,原因是SDA是inout的端口(SCL由主机提供,可以作为单独的input或output),不支持直接相连,否则编译器会报错。为解决这个小尴尬,简单写了一个verilog的IIC switch模块,在此记录一下。使用该模块可以轻松将IIC链路通过FPGA连接,实现通信。

2,系统框图

使用 iic_switch.v 模块,可在FPGA中选择MCU的IIC接到设备端的那一路IIC端口。
在这里插入图片描述

3,完整模块代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: QSJ
// 
// Create Date: 2025/05/21 9:12:00
// Design Name: 
// Module Name: iic_switch
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module iic_switch(input         	   clk            // 100MHz,input         	   rst_n          ,input wire [3:0]   iv_channel_sel,input         	    i_master_scl        ,inout         	   io_master_sda   ,output reg         o_slave_0_scl      ,inout              io_slave_0_sda     ,output reg          o_slave_1_scl      ,inout              io_slave_1_sda     ,output reg          o_slave_2_scl      ,inout              io_slave_2_sda     ,output reg          o_slave_3_scl      ,inout              io_slave_3_sda     ,output reg          o_slave_4_scl      ,inout              io_slave_4_sda     ,output reg          o_slave_5_scl      ,inout              io_slave_5_sda     ,output reg          o_slave_6_scl      ,inout              io_slave_6_sda     ,output reg          o_slave_7_scl      ,inout              io_slave_7_sda     
);reg master_scl_n;
reg master_sda_n;
reg scl_rising  ;
reg scl_falling ;
reg sda_rsiing  ;
reg sda_falling ;always @(posedge clk)beginif(!rst_n)beginmaster_scl_n   <= 1'b1;master_sda_n   <= 1'b1;end else beginmaster_scl_n   <= i_master_scl;master_sda_n   <= io_master_sda;scl_rising  <= (master_scl_n!=i_master_scl) & (master_scl_n==0);scl_falling <= (master_scl_n!=i_master_scl) & (master_scl_n==1); sda_rsiing  <= (master_sda_n!=io_master_sda) & (master_sda_n==0); sda_falling <= (master_sda_n!=io_master_sda) & (master_sda_n==1); end
endreg [7:0] bit_cnt     ;
reg       first_start ;
reg       iic_start   ;
reg       iic_stop    ;always @(posedge clk)beginif(!rst_n)beginbit_cnt        <=  'd0;first_start    <=  'b0;iic_start      <=  'b0;iic_stop       <=  'b0;end else beginif((i_master_scl==1) & sda_falling)begin //IIC Startbit_cnt        <= 0;first_start    <=  'b1;iic_start      <=  'b1;iic_stop       <=  'b0;end else if((i_master_scl==1) & sda_rsiing)begin //IIC Stopbit_cnt        <= 0;first_start    <=  'b0;iic_start      <=  'b0;iic_stop       <=  'b1;end else if(bit_cnt==10)beginbit_cnt        <= 1;first_start    <=  'b0;iic_start      <=  'b0;iic_stop       <=  'b0;end else beginbit_cnt        <= bit_cnt + scl_falling;first_start    <=  first_start;iic_start      <=  'b0;iic_stop       <=  'b0;end end
endreg rw_bit;
reg ack_bit_vld;
reg ack_bit_vld_n;
wire ack_bit_vld_falling = (ack_bit_vld_n!=ack_bit_vld) & (ack_bit_vld_n==1); 
always @(posedge clk)beginif(!rst_n)beginack_bit_vld         <= 1'b0;ack_bit_vld_n       <= 1'b0;end else beginack_bit_vld         <= bit_cnt==9;ack_bit_vld_n       <= ack_bit_vld;end
endreg rw_bit_p;
reg master_ack;
always @(posedge clk)beginif(!rst_n)beginmaster_ack  <= 1'b0;end else beginif(rw_bit_p)beginif(ack_bit_vld_n & scl_rising)beginmaster_ack        <= master_sda_n;end else beginmaster_ack        <= master_ack;end end else beginmaster_ack        <= 0;end end
endreg bit_vld;
always @(posedge clk)beginif(!rst_n)beginbit_vld   <= 'b0;rw_bit    <= 'b0;rw_bit_p  <= 'b0;end else beginbit_vld   <= scl_rising;rw_bit_p  <= ((bit_cnt==8) & bit_vld & first_start) ? io_master_sda : iic_stop ? 1'b0 : rw_bit_p;rw_bit    <= ack_bit_vld_falling ? master_ack ? 1'b0 : rw_bit_p  : rw_bit;endendreg master_sda_oe;
always @(posedge clk)beginif(!rst_n)beginmaster_sda_oe     <= 1'b0;end else beginmaster_sda_oe     <= rw_bit ? ~ack_bit_vld_n :  ack_bit_vld_n;end
end
wire slave_sda_oe = ~master_sda_oe;assign io_slave_0_sda = iv_channel_sel==0 ? slave_sda_oe ? io_master_sda : 1'bz : 1'bz;
assign io_slave_1_sda = iv_channel_sel==1 ? slave_sda_oe ? io_master_sda : 1'bz : 1'bz;
assign io_slave_2_sda = iv_channel_sel==2 ? slave_sda_oe ? io_master_sda : 1'bz : 1'bz;
assign io_slave_3_sda = iv_channel_sel==3 ? slave_sda_oe ? io_master_sda : 1'bz : 1'bz;
assign io_slave_4_sda = iv_channel_sel==4 ? slave_sda_oe ? io_master_sda : 1'bz : 1'bz;
assign io_slave_5_sda = iv_channel_sel==5 ? slave_sda_oe ? io_master_sda : 1'bz : 1'bz;
assign io_slave_6_sda = iv_channel_sel==6 ? slave_sda_oe ? io_master_sda : 1'bz : 1'bz;
assign io_slave_7_sda = iv_channel_sel==7 ? slave_sda_oe ? io_master_sda : 1'bz : 1'bz;assign io_master_sda  =  master_sda_oe ? iv_channel_sel==0 ? io_slave_0_sda : iv_channel_sel==1 ? io_slave_1_sda : iv_channel_sel==2 ? io_slave_2_sda : iv_channel_sel==3 ? io_slave_3_sda : iv_channel_sel==4 ? io_slave_4_sda : iv_channel_sel==5 ? io_slave_5_sda : iv_channel_sel==6 ? io_slave_6_sda : iv_channel_sel==7 ? io_slave_7_sda : 1'bz: 1'bz;always @(*)begincase(iv_channel_sel)0:begino_slave_0_scl = i_master_scl;o_slave_1_scl = 1'bz;o_slave_2_scl = 1'bz;o_slave_3_scl = 1'bz;o_slave_4_scl = 1'bz;o_slave_5_scl = 1'bz;o_slave_6_scl = 1'bz;o_slave_7_scl = 1'bz;end1:begino_slave_0_scl = 1'bz;o_slave_1_scl = i_master_scl;o_slave_2_scl = 1'bz;o_slave_3_scl = 1'bz;o_slave_4_scl = 1'bz;o_slave_5_scl = 1'bz;o_slave_6_scl = 1'bz;o_slave_7_scl = 1'bz;end2:begino_slave_0_scl = 1'bz;o_slave_1_scl = 1'bz;o_slave_2_scl = i_master_scl;o_slave_3_scl = 1'bz;o_slave_4_scl = 1'bz;o_slave_5_scl = 1'bz;o_slave_6_scl = 1'bz;o_slave_7_scl = 1'bz;end3:begino_slave_0_scl = 1'bz;o_slave_1_scl = 1'bz;o_slave_2_scl = 1'bz;o_slave_3_scl = i_master_scl;o_slave_4_scl = 1'bz;o_slave_5_scl = 1'bz;o_slave_6_scl = 1'bz;o_slave_7_scl = 1'bz;end4:begino_slave_0_scl = 1'bz;o_slave_1_scl = 1'bz;o_slave_2_scl = 1'bz;o_slave_3_scl = 1'bz;o_slave_4_scl = i_master_scl;o_slave_5_scl = 1'bz;o_slave_6_scl = 1'bz;o_slave_7_scl = 1'bz;end5:begino_slave_0_scl = 1'bz;o_slave_1_scl = 1'bz;o_slave_2_scl = 1'bz;o_slave_3_scl = 1'bz;o_slave_4_scl = 1'bz;o_slave_5_scl = i_master_scl;o_slave_6_scl = 1'bz;o_slave_7_scl = 1'bz;end6:begino_slave_0_scl = 1'bz;o_slave_1_scl = 1'bz;o_slave_2_scl = 1'bz;o_slave_3_scl = 1'bz;o_slave_4_scl = 1'bz;o_slave_5_scl = 1'bz;o_slave_6_scl = i_master_scl;o_slave_7_scl = 1'bz;end7:begino_slave_0_scl = 1'bz;o_slave_1_scl = 1'bz;o_slave_2_scl = 1'bz;o_slave_3_scl = 1'bz;o_slave_4_scl = 1'bz;o_slave_5_scl = 1'bz;o_slave_6_scl = 1'bz;o_slave_7_scl = i_master_scl;enddefault:begin o_slave_0_scl = i_master_scl;o_slave_1_scl = 1'bz;o_slave_2_scl = 1'bz;o_slave_3_scl = 1'bz;o_slave_4_scl = 1'bz;o_slave_5_scl = 1'bz;o_slave_6_scl = 1'bz;o_slave_7_scl = 1'bz; endendcaseendendmodule

相关文章:

  • 网站移动页面怎么做的如何做网站优化seo
  • 网站建设商虎小程序买淘宝店铺多少钱一个
  • 申请域名后可以做自己的网站吗杭州网站搜索排名
  • 网站开发和c语言网站推广排名服务
  • 中国数据网站空间seo关键词排名优化官网
  • 自定义导航网站 源码友情链接属于免费推广吗
  • 三、Docker目录挂载、卷映射、网络
  • OpenCV CUDA模块图像过滤------创建一个 Sobel 滤波器函数createSobelFilter()
  • Qt6无法识别OpenCV(Windows端开发)
  • 新一代WebP2P视频物联技术:EasyRTC嵌入式音视频通信SDK助力音视频实时通信场景应用
  • 蜂鸟E203与PicoRV32两款RISC-V处理器的对比分析
  • 紫光同创FPGA实现视频采集转USB2.0输出,基于CY7C68013芯片,提供PDS工程源码和技术支持和QT上位机
  • 05-jenkins学习之旅-vue前项目部署实践
  • hadoop异构存储
  • crc32代码设计
  • Docker基础 -- 构建 RK3588 Debian 根文件系统
  • 海思3519V200ARM Linux 下移植 Qt5.8.0
  • EPT(Efficient Prompt Tuning)方法,旨在解决提示调优(Prompt Tuning)中效率与准确性平衡和跨任务一致性的问题
  • Android studio进阶开发(六)--如何用真机通过okhttp连接服务器
  • 20250526惠普HP锐14 AMD锐龙 14英寸轻薄笔记本电脑(八核R7-7730U)的显卡驱动下载
  • Linux_编辑器Vim基本使用
  • 【iOS】 锁
  • Linux(Centos 7.6)命令详解:tar
  • jEasyUI 表单的 CRUD 应用
  • pgsql 一些用法
  • 【C++指南】string(四):编码