FPGA通过ADS1110采集模拟数据,串口方式上传到上位机(1)
parameterSYS_CLK_FREQ=26'd50_000_000,//输入系统时钟频率。parameterUART_BPS=26'd1_000_000,//串口波特率。parameterCLK_FREQ=26'd50_000_000//时钟频率。
直接上代码:
`timescale 1ns/1ns
module i2c_ctrl_adc
#(
parameter DEVICE_ADDR = 7'b1001_000 , //i2c设备地址
parameter SYS_CLK_FREQ = 26'd50_000_000 , //输入系统时钟频率
parameter SCL_FREQ = 18'd250_000 , //i2c设备scl时钟频率
parameter UART_BPS = 26'd1_000_000 , //串口波特率
parameter CLK_FREQ = 26'd50_000_000 //时钟频率
)
(
input wire sys_clk , //输入系统时钟,50MHz
input wire sys_rst_n , //输入复位信号,低电平有效
output reg i2c_scl , //输出至i2c设备的串行时钟信号scl
inout wire i2c_sda , //输出至i2c设备的串行数据信号sda
output reg tx //串转并后的1bit数据
);
//************************************************************************//
//******************** Parameter and Internal Signal *********************//
//************************************************************************//
// parameter define
parameter CNT_CLK_MAX = (SYS_CLK_FREQ/SCL_FREQ) >> 2'd3 ; //cnt_clk计数器计数最大值
parameter CNT_START_MAX = 8'd100; //cnt_start计数器计数最大值
parameter IDLE = 5'd00, //初始状态
START_WR = 5'd01, //开始状态
SEND_WR_ADDR = 5'd02, //设备地址写入状态 + 控制写
ACK_WADDR = 5'd03, //应答状态
SEND_B_ADDR_H = 5'd04, //字节地址高八位写入状态
ACK_2 = 5'd05, //应答状态
SEND_B_ADDR_L = 5'd06, //字节地址低八位写入状态
ACK_3 = 5'd07, //应答状态
WR_DATA = 5'd08, //写数据状态
ACK_WD = 5'd09, //应答状态
START_RD = 5'd10, //开始状态
SEND_RD_ADDR = 5'd11, //设备地址写入状态 + 控制读
ACK_RADDR = 5'd12, //应答状态
ACK_MRD = 5'd13, //应答状态
RD_DATA = 5'd14, //读数据状态
N_ACK = 5'd15, //非应答状态
STOP_WR = 5'd16, //结束状态
STOP_RD = 5'd17; //结束状态
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS;
// wire define
wire sda_in ; //sda输入数据寄存
wire sda_en ; //sda数据写入使能信号
// reg define
reg [7:0] cnt_clk ; //系统时钟计数器,控制生成clk_i2c时钟信号
reg [4:0] state ; //状态机状态
reg [1:0] cnt_i2c_clk ; //clk_i2c时钟计数器,控制生成cnt_bit信号
reg [3:0] cnt_bit ; //sda比特计数器
reg cnt_finish ; //完成一个字节写入或者读取标志
reg ack ; //应答信号
reg i2c_sda_reg ; //sda数据缓存
reg [1:0] rd_data_cnt ; //对读出的数据进行计数
reg wr_en ; //输入写使能信号
reg rd_en ; //输入读使能信号
reg [23:0] rd_data ; //输出i2c设备读取数据
reg i2c_clk ; //i2c驱动时钟
reg [7:0] wr_data ;
//reg define
reg [12:0] baud_cnt ;
reg bit_flag ;
reg [5:0] bit_cnt ;
reg work_en ;
reg pi_flag ;
reg [15:0] send_cnt ;
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//work_en:接收数据工作使能信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
work_en <= 1'b0;
else if(pi_flag == 1'b1)
work_en <= 1'b1;
else if((bit_flag == 1'b1) && (bit_cnt == 6'd39))
work_en <= 1'b0;
//baud_cnt:波特率计数器计数,从0计数到BAUD_CNT_MAX - 1
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
baud_cnt <= 13'b0;
else if((baud_cnt == BAUD_CNT_MAX - 1) || (work_en == 1'b0))
baud_cnt <= 13'b0;
else if(work_en == 1'b1)
baud_cnt <= baud_cnt + 1'b1;
//bit_flag:当baud_cnt计数器计数到1时让bit_flag拉高一个时钟的高电平
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
bit_flag <= 1'b0;
else if(baud_cnt == 13'd1)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
//bit_cnt:数据位数个数计数,10个有效数据(含起始位和停止位)到来后计数器清零
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
bit_cnt <= 4'b0;
else if((bit_flag == 1'b1) && (bit_cnt == 6'd39)) begin
bit_cnt <= 4'b0;
end
else if((bit_flag == 1'b1) && (work_en == 1'b1))
bit_cnt <= bit_cnt + 1'b1;
//tx:输出数据在满足rs232协议(起始位为0,停止位为1)的情况下一位一位输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
tx <= 1'b1; //空闲状态时为高电平
else if(bit_flag == 1'b1)
case(bit_cnt)
0 : tx <= 1'b0;
1 : tx <= 1'b0;
2 : tx <= 1'b1;
3 : tx <= 1'b1;
4 : tx <= 1'b1;
5 : tx <= 1'b1;
6 : tx <= 1'b1;
7 : tx <= 1'b1;
8 : tx <= 1'b0;
9 : tx <= 1'b1;
10 : tx <= 1'b0;
11 : tx <= rd_data[16];
12 : tx <= rd_data[17];
13 : tx <= rd_data[18];
14 : tx <= rd_data[19];
15 : tx <= rd_data[20];
16 : tx <= rd_data[21];
17 : tx <= rd_data[22];
18 : tx <= rd_data[23];
19 : tx <= 1'b1;
20 : tx <= 1'b0;
21 : tx <= rd_data[8];
22 : tx <= rd_data[9];
23 : tx <= rd_data[10];
24 : tx <= rd_data[11];
25 : tx <= rd_data[12];
26 : tx <= rd_data[13];
27 : tx <= rd_data[14];
28 : tx <= rd_data[15];
29 : tx <= 1'b1;
30 : tx <= 1'b0;
31 : tx <= rd_data[0];
32 : tx <= rd_data[1];
33 : tx <= rd_data[2];
34 : tx <= rd_data[3];
35 : tx <= rd_data[4];
36 : tx <= rd_data[5];
37 : tx <= rd_data[6];
38 : tx <= rd_data[7];
39 : tx <= 1'b1;
default : tx <= 1'b1;
endcase
//************************************************************************//
//******************************* Main Code ******************************//
//************************************************************************//
// cnt_clk:系统时钟计数器,控制生成clk_i2c时钟信号
always@(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
cnt_clk <= 8'd0;
else if(cnt_clk == CNT_CLK_MAX - 1'b1)
cnt_clk <= 8'd0;
else
cnt_clk <= cnt_clk + 1'b1;
end
// i2c_clk:i2c驱动时钟
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
i2c_clk <= 1'b1;
else if(cnt_clk == CNT_CLK_MAX - 1'b1)
i2c_clk <= ~i2c_clk;
// cnt_i2c_clk:i2c_clk时钟计数器,控制生成cnt_bit信号
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_i2c_clk = 2'd00;
else if(cnt_i2c_clk < 2'b11)
cnt_i2c_clk = cnt_i2c_clk + 2'b01;
else
cnt_i2c_clk = 2'b00;
// sda_in:sda输入数据寄存
assign sda_in = i2c_sda;
// sda_en:sda数据写入使能信号
assign sda_en = ((state == RD_DATA) ||
(state == ACK_WADDR) ||
(state == ACK_RADDR) ||
(state == ACK_WD)) ? 1'b0 : 1'b1;
// i2c_sda:输出至i2c设备的串行数据信号sda
assign i2c_sda = (sda_en == 1'b1) ? i2c_sda_reg : 1'bz;
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0) begin
i2c_scl <= 1'b1;
i2c_sda_reg <= 1'b1;
state <= START_WR;
cnt_bit <= 4'b0000;
cnt_finish <= 1'b0;
rd_data_cnt <= 1'b0;
rd_data = 24'b0;
rd_en <= 1'b0;
wr_en <= 1'b1;
wr_data <= 8'b1000_1100; //8'b10001100; // CONFIGURATION REGISTER
send_cnt <= 0;
end
else case(state)
IDLE: begin
if(cnt_i2c_clk == 2'b00) begin
if(pi_flag == 1'b1) begin
if(work_en == 1'b1) begin
pi_flag <= 1'b0;
rd_en <= 1'b0;
wr_en <= 1'b0;
end
end
else if(pi_flag == 1'b0) begin
if(work_en == 1'b0) begin
if(send_cnt >= 1000) begin
send_cnt <= 0;
rd_en <= 1'b1;
wr_en <= 1'b0;
end
else
send_cnt <= send_cnt + 1;
end
end
end
if(cnt_i2c_clk == 2'b01) begin
end
if(cnt_i2c_clk == 2'b10) begin
end
if(cnt_i2c_clk == 2'b11) begin
i2c_scl <= 1'b1;
i2c_sda_reg <= 1'b1;
if(wr_en == 1'b1) begin
wr_en <= 1'b0;
state <= START_WR;
rd_data = 24'b0;
end
else if(rd_en == 1'b1) begin
rd_en <= 1'b0;
state <= START_RD;
rd_data = 24'b0;
end
end
end
START_WR: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_sda_reg <= 1'b1;
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_sda_reg <= 1'b0;
end
else if(cnt_i2c_clk == 2'b10) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b11) begin
i2c_scl <= 1'b0;
state <= SEND_WR_ADDR;
end
end
SEND_WR_ADDR: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_scl <= 1'b0;
if(cnt_bit <= 4'd6) begin
i2c_sda_reg <= DEVICE_ADDR[6 - cnt_bit];
end
else begin
i2c_sda_reg <= 1'b0;
end
if(cnt_bit <= 4'd6) begin
cnt_bit <= cnt_bit + 1'b1;
end
else begin
cnt_bit <= 4'd0;
cnt_finish <= 1'b1;
end
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b11) begin
if(cnt_finish == 1'b1) begin
state <= ACK_WADDR;
cnt_finish <= 1'b0;
end
end
end
ACK_WADDR: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
ack <= sda_in;
end
else if(cnt_i2c_clk == 2'b11) begin
i2c_scl <= 1'b0;
if(ack == 1'b1) begin
state <= IDLE;
end
else begin
state <= WR_DATA;
end
end
end
WR_DATA: begin
if(cnt_i2c_clk == 2'b00) begin
if(cnt_bit <= 4'd7) begin
i2c_sda_reg <= wr_data[7 - cnt_bit];
cnt_bit <= cnt_bit + 1'b1;
end
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_scl <= 1'b1;
if(cnt_bit == 4'd8) begin
cnt_bit <= 4'd0;
cnt_finish <= 1'b1;
end
end
else if(cnt_i2c_clk == 2'b10) begin
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b11) begin
if(cnt_finish == 1'b1) begin
state <= ACK_WD;
cnt_finish <= 1'b0;
end
end
end
ACK_WD: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
ack <= sda_in;
end
else if(cnt_i2c_clk == 2'b11) begin
i2c_scl <= 1'b0;
if(ack == 1'b1) begin
state <= IDLE;
end
else begin
state <= STOP_WR;
end
end
end
STOP_WR: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_sda_reg <= 1'b0;
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_sda_reg <= 1'b0;
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
i2c_sda_reg <= 1'b1;
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b11) begin
state <= START_RD;
end
end
START_RD: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_sda_reg <= 1'b1;
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_sda_reg <= 1'b0;
end
else if(cnt_i2c_clk == 2'b10) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b11) begin
i2c_scl <= 1'b0;
state <= SEND_RD_ADDR;
end
end
SEND_RD_ADDR: begin
if(cnt_i2c_clk == 2'b00) begin
if(cnt_bit <= 4'd6) begin
i2c_sda_reg <= DEVICE_ADDR[6 - cnt_bit];
end
else begin
i2c_sda_reg <= 1'b1;
end
if(cnt_bit <= 4'd6) begin
cnt_bit <= cnt_bit + 1'b1;
end
else begin
cnt_bit <= 4'd0;
cnt_finish <= 1'b1;
end
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b11) begin
if(cnt_finish == 1'b1) begin
state <= ACK_RADDR;
cnt_finish <= 1'b0;
end
end
end
ACK_RADDR: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
ack <= sda_in;
end
else if(cnt_i2c_clk == 2'b11) begin
i2c_scl <= 1'b0;
if(ack == 1'b1) begin
state <= IDLE;
end
else begin
state <= RD_DATA;
end
end
end
RD_DATA: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
rd_data = (rd_data << 1);
rd_data = (rd_data | sda_in);
cnt_bit <= (cnt_bit + 1'b1);
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b11) begin
if(cnt_bit >= 4'd8) begin
cnt_bit <= 4'd0;
rd_data_cnt <= rd_data_cnt + 2'd1;
state <= ACK_MRD;
end
end
end
ACK_MRD: begin
if(cnt_i2c_clk == 2'b00) begin
// i2c_scl <= 1'b0;
i2c_sda_reg <= 1'b0;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b11) begin
if(rd_data_cnt === 3) begin
state <= STOP_RD;
rd_data_cnt <= 0;
end
else begin
state <= RD_DATA;
end
end
end
STOP_RD: begin
if(cnt_i2c_clk == 2'b00) begin
i2c_sda_reg <= 1'b0;
i2c_scl <= 1'b0;
end
else if(cnt_i2c_clk == 2'b01) begin
i2c_sda_reg <= 1'b0;
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b10) begin
i2c_sda_reg <= 1'b1;
i2c_scl <= 1'b1;
end
else if(cnt_i2c_clk == 2'b11) begin
state <= IDLE;
pi_flag <= 1'b1;
end
end
default: begin
i2c_sda_reg <= 1'b1;
i2c_scl <= 1'b1;
end
endcase
endmodule


更多推荐



所有评论(0)