程序主体部分完成与外部程序的接口、与总线上外部节点的连线、完成程序内部各个寄存器的构建、控制字节传输控制模块等功能。代码如下:
- `include "timescale.v"
- `include "i2c_master_defines.v"
- //模块定义
- module i2c_master_top(
- wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o,
- wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o,
- scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o );
- // 参数
- parameter ARST_LVL = 1'b0; // 异步 reset 信号
- // 输入、输出信号
- // 连接到外部接口的信号
- input clk_i; // 主节点时钟信号
- input rst_i; // 同步 reset 信号,高有效
- input arst_i; // 异步 reset 信号
- input [2:0] adr_i; // 低位地址信号
- input [7:0] dat_i; // 数据总线输入
- output [7:0] dat_o; // 数据总线输出
- input we_i; // 输入使能信号
- input stb_i; // 触发信号
- input cyc_i; // 总线周期输入
- output ack_o; // 应答信号输出
- output inta_o; // 中断请求信号输出
- reg [7:0] wb_dat_o;
- reg wb_ack_o;
- reg wb_inta_o;
- // I²C 信号
- // I²C 时钟信号线
- input scl_pad_i; // SCL 输入
- output scl_pad_o; // SCL 输出
- output scl_padoen_o; // SCL 输出使能
- // I²C 数据线
- input sda_pad_i; // SDA 输入
- output sda_pad_o; // SDA 输出
- output sda_padoen_o; // SDA 输出使能
- // 变量申明
- // 寄存器
- reg [15:0] prer; // 时钟分频寄存器
- reg [ 7:0] ctr; // 控制寄存器
- reg [ 7:0] txr; // 数据传输寄存器
- wire [ 7:0] rxr; // 数据接收寄存器
- reg [ 7:0] cr; // 命令寄存器
- wire [ 7:0] sr; // 状态寄存器
- // 完成信号,命令完成后清除命令寄存器
- wire done;
- // 模块使能信号
- wire core_en;
- wire ien;
- // 状态寄存器信号
- wire irxack;
- reg rxack; // 从从节点接收应答信号
- reg tip; // 传输进行标志
- reg irq_flag; // 中断挂起标志
- wire i2c_busy; // 总线忙标志
- wire i2c_al; // 总线仲裁丢失
- reg al; // 状态寄存器仲裁丢失位
- // 模块主体
- // 产生内部 reset
- wire rst_i = arst_i ^ ARST_LVL;
- wire wacc = cyc_i & stb_i & we_i;
- // 产生应答输出信号
- always @(posedge clk_i)
- wb_ack_o <= #1 cyc_i & stb_i & ~ack_o;
- // 数据输出
- always @(posedge clk_i)
- begin
- case (adr_i)
- 3'b000: wb_dat_o = prer[ 7:0];
- 3'b001: wb_dat_o = prer[15:8];
- 3'b010: wb_dat_o = ctr;
- 3'b011: wb_dat_o = rxr; // 写数据传输寄存器
- 3'b100: wb_dat_o = sr; // 写命令寄存器
- 3'b101: wb_dat_o = txr;
- 3'b110: wb_dat_o = cr;
- 3'b111: wb_dat_o = 0; // 保留位
- endcase
- end
- // 产生寄存器
- always @(posedge wb_clk_i or negedge rst_i)
- if (!rst_i)
- begin
- prer <= #1 16'hffff;
- ctr <= #1 8'h0;
- txr <= #1 8'h0;
- end
- else if (wb_rst_i)
- begin
- prer <= #1 16'hffff;
- ctr <= #1 8'h0;
- txr <= #1 8'h0;
- end
- else
- if (wb_wacc)
- case (wb_adr_i) // synopsis full_case parallel_case
- 3'b000 : prer [ 7:0] <= #1 wb_dat_i;
- 3'b001 : prer [15:8] <= #1 wb_dat_i;
- 3'b010 : ctr <= #1 wb_dat_i;
- 3'b011 : txr <= #1 wb_dat_i;
- endcase
- // 产生命令寄存器
- always @(posedge wb_clk_i or negedge rst_i)
- if (~rst_i)
- cr <= #1 8'h0;
- else if (wb_rst_i)
- cr <= #1 8'h0;
- else if (wb_wacc)
- begin
- if (core_en & (wb_adr_i == 3'b100) )
- cr <= #1 wb_dat_i;
- end
- else
- begin
- if (done | i2c_al)
- cr[7:4] <= #1 4'h0; // 命令完成或者仲裁丢失时清除命令寄存器内容
- cr[2:1] <= #1 2'b0; // 保留位
- cr[0] <= #1 2'b0; // 清除 IRQ_ACK 位
- end
- // 译码命令寄存器
- wire sta = cr[7];
- wire sto = cr[6];
- wire rd = cr[5];
- wire wr = cr[4];
- wire ack = cr[3];
- wire iack = cr[0];
- // 译码控制寄存器
- assign core_en = ctr[7];
- assign ien = ctr[6];
- // 连接字节控制模块
- i2c_master_byte_ctrl byte_controller (
- .clk ( wb_clk_i ),
- .rst ( wb_rst_i ),
- .nReset ( rst_i ),
- .ena ( core_en ),
- .clk_cnt ( prer ),
- .start ( sta ),
- .stop ( sto ),
- .read ( rd ),
- .write ( wr ),
- .ack_in ( ack ),
- .din ( txr ),
- .cmd_ack ( done ),
- .ack_out ( irxack ),
- .dout ( rxr ),
- .i2c_busy ( i2c_busy ),
- .i2c_al ( i2c_al ),
- .scl_i ( scl_pad_i ),
- .scl_o ( scl_pad_o ),
- .scl_oen ( scl_padoen_o ),
- .sda_i ( sda_pad_i ),
- .sda_o ( sda_pad_o ),
- .sda_oen ( sda_padoen_o )
- );
- // 状态寄存器部分和中断请求信号
- always @(posedge wb_clk_i or negedge rst_i)
- if (!rst_i)
- begin
- al <= #1 1'b0;
- rxack <= #1 1'b0;
- tip <= #1 1'b0;
- irq_flag <= #1 1'b0;
- end
- else if (wb_rst_i)
- begin
- al <= #1 1'b0;
- rxack <= #1 1'b0;
- tip <= #1 1'b0;
- irq_flag <= #1 1'b0;
- end
- else
- begin
- al <= #1 i2c_al | (al & ~sta);
- rxack <= #1 irxack;
- tip <= #1 (rd | wr);
- irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack;
- // 中断请求标志
- end
- // 产生中断请求信号
- always @(posedge wb_clk_i or negedge rst_i)
- if (!rst_i)
- wb_inta_o <= #1 1'b0;
- else if (wb_rst_i)
- wb_inta_o <= #1 1'b0;
- else
- wb_inta_o <= #1 irq_flag && ien; //中断使能位 IEN 设置后产生中断信号
- assign sr[7] = rxack;
- assign sr[6] = i2c_busy;
- assign sr[5] = al;
- assign sr[4:2] = 3'h0; // reserved
- assign sr[1] = tip;
- assign sr[0] = irq_flag;
- endmodule
复制代码
0
|
|
|
|