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

基于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
http://www.xdnf.cn/news/9095.html

相关文章:

  • Qt popup窗口半透明背景
  • mac for vscode集成的源代码管理 撤销和删除文件报错Permission denied
  • 【Macos】安装前端环境rust+node环境
  • 从界面设计到设备互联:基于Qt的ARM Linux自动化控制面板开发全解析
  • 【图像处理基石】什么是色彩模式?
  • 深度学习在建筑物提取中的应用综述
  • 【Qt开发】输入类控件
  • C语言初阶--结构体
  • 高性能排行榜系统架构实战
  • 解码词向量:让AI语言模型更透明
  • Leetcode 3563. Lexicographically Smallest String After Adjacent Removals
  • 基于Flask实现当当网书籍数据分析大屏
  • 清除谷歌浏览器中的“您的浏览器由所属组织/贵单位管理”
  • 《软件工程》第 2 章 -UML 与 RUP 统一过程
  • GitHub Page填写域名显示被占用
  • (转)Docker与K8S的区别
  • Java中Map集合的遍历方式详解
  • 【监控】PromQL 查询语言
  • vscode连接的linux服务器,上传项目至github
  • 开启MySQL的binlog日志
  • 每天掌握一个Linux命令 - ab(Apache Benchmark)
  • 进程IO之 进程
  • 组态王KingSCADA4.0连接1200PLC实战教程以及麒麟版问题说明
  • 【Spring Boot 实战】使用 HTTP 响应压缩优化接口性能
  • webtrees——在线协作家谱
  • Cursor 对话回答如何设置成中文
  • Pypy3 和 Python3 的区别
  • 如何做好一份技术文档:从精准导航到持续迭代的实践指南
  • Prompt Engineering 提示工程介绍与使用/调试技巧
  • uniapp开发小程序,如何根据权限动态配置按钮或页面内容