您的位置:首页 > 其它

Verilog实现IIC通讯第二版

2013-08-14 23:31 190 查看
HMC5883三轴磁力传感器IIC通讯模块的VerilogHDL的实现

上一版并没有实现我想要的功能

0.0.1版 正在修订中 2013/9/2

//date :2013/7/7
//designer :pengxiaoen
//synthesizer:QuartusII 12.1
//function : IIC实现HMC5883的通讯  50M /(400k × 4)= 32

`define WriteAddress  8'h3c
`define ReadAddress   8'h3d

`define RegAAddress   8'h00  //配置寄存器A
`define RegBAddress   8'h01  //配置寄存器B
`define ModelAddress  8'h02  //模式寄存器
`define X_MSBAddress  8'h03  //X MSB寄存器
`define X_LSBAddress  8'h04
`define Z_MSBAddress  8'h05
`define Z_LSBAddress  8'h06
`define Y_MSBAddress  8'h07
`define Y_LSBAddress  8'h08
`define STATEAddress  8'h09  //状态寄存器
`define IdentifyAAddress  8'h10  //识别寄存器A
`define IdentifyBAddress  8'h10
`define IdentifyCAddress  8'h10

`define INITIAL  0
`define DELAY    1
`define MEASURE  2

`define START  3
`define Re     4
`define Se     5
`define STOP   6

//`default_nettype none

module HMC5883_2 (
clock,reset,
sda,scl,
out_seg,

sel_seg,
IIC_result
);

input clock,reset;
inout sda,scl;
output reg [7:0]out_seg;
output reg IIC_result;

output reg [5:0]sel_seg;

reg [7:0] SEND_buffer;
reg [7:0] Re_buffer ;
reg sda_reg;
reg scl_reg;
reg ack_reg;
reg sda_enable;
reg scl_enable;

reg IC_state;
reg n_IC_state;
reg [2:0]state;           //当前状态寄存器
reg state_finish_flag ;   //

reg [5:0] scl_4;
reg [3:0] step_counter;
reg [3:0] clk_temp ;

//==============================================================================================
//-------------时钟控制模块------------------start---------------
always @ (posedge clock or negedge reset)
if (!reset)
begin
clk_temp <= 4'd0;
scl_4 <= 6'd0;
end
else if (clk_temp==4'd15)
begin
clk_temp <= 4'd0;
if (state_finish_flag) scl_4 <= 6'd0;
else if (scl_4 == 6'b111_111)   //这里是一个保护机制,可以设置一个flag
scl_4 <= 6'b111_111;
else  scl_4 <= scl_4 + 1;
end
else clk_temp <= clk_temp + 1;
//----------时钟控制模块----------end-----------

//--------一个检测的pin---------start-----------
always @(posedge clock or negedge reset)
if(!reset)
IIC_result <= 1'd0;
else if(scl_4 == 6'b111_111)
IIC_result <= 1'd1;
else ;
//-----------一个检测的pin-------end----------

//-------延时模块----5us------start--------
reg [7:0] delay_counter;
reg delay_enable;
always @(posedge clock )
if(!delay_enable)
begin
delay_counter <= 8'd0;
state_finish_flag <= 1'd0;
end
else  if(delay_counter == 8'd250)
begin
state_finish_flag <= 1'd1;
delay_counter <= 8'd0;
end
else  begin
delay_counter <= delay_counter + 1;
state_finish_flag <= 1'd0;
end
//--------------延时模块-------end---------------

//----------状态机控制模块---------start-------
always @ (posedge clock or negedge reset)
if(!reset)
IC_state <= `INITIAL;
else IC_state <= n_IC_state;

//------------------------------------------
always @ (posedge state_finish_flag or negedge reset)
if (!reset)
begin
SEND_buffer  <= 8'd0;
n_IC_state   <= 1'd0;
end
else if(IC_state == `INITIAL)
case (step_counter)
0: begin  state <= `START;end
1: begin  state <= `Se;  SEND_buffer <= `WriteAddress;   end
2: begin  state <= `Se;  SEND_buffer <= `ModelAddress;   end
3: begin  state <= `Se;  SEND_buffer <= `RegAAddress;   end
4: begin  state <= `STOP;   end

5: begin  n_IC_state <= `MEASURE;   end
default state <= `START;
endcase
else if (IC_state == `MEASURE)
case (step_counter)
0: begin  state <= `START; end
1: begin  state <= `Se;   SEND_buffer <= `WriteAddress; end
2: begin  state <= `Se;   SEND_buffer <= `X_MSBAddress; end
3: begin  state <= `START; end
4: begin  state <= `Se;   SEND_buffer <= `ReadAddress;end
5: begin  state <= `Re;   end
6: begin  state <= `Re;   end
7: begin  state <= `Re;   end
8: begin  state <= `Re;   end
9: begin  state <= `Re;   end
10: begin  state <= `Re;   end
11: begin  state <= `STOP; end

12:begin  n_IC_state <= `INITIAL;  end
default state <= `START;
endcase
else ;
//----------状态机控制模块----------end--- ---

//----------执行步骤计数--------start------------
always @ (posedge clock  or negedge reset)
if (!reset) begin
step_counter <= 4'd0;  end
else  if((IC_state == `INITIAL)&& (state_finish_flag))   begin
if(step_counter == 4'd5)  step_counter <= 4'd0;
else step_counter <= step_counter + 1; end
else if((IC_state == `MEASURE) && (state_finish_flag))   begin
if(step_counter == 4'd12 ) step_counter <= 4'd0;
else step_counter <= step_counter + 1;     end
else ;
//----------执行步骤计数--------end------------

//-----------外部数据线 控制模块----start------
always @ (posedge clock or negedge reset)
if(!reset)
begin
Re_buffer <= 8'd0;
sda_enable <= 1'd0;
scl_enable <= 1'd0;
delay_enable <= 1'd0;
end
else case (state)
`START : case (scl_4)
0: begin sda_enable <= 1'd1; scl_enable <= 1'd1; delay_enable <= 1'd0;
sda_reg <= 1'd1;  scl_reg <= 1'd0;  end
1: begin sda_reg <= 1'd1;  scl_reg <= 1'd0;  end
2: begin sda_reg <= 1'd1;  scl_reg <= 1'd1;  end
3: begin sda_reg <= 1'd0;  scl_reg <= 1'd1;  end
4: delay_enable <= 1'd1;
default  begin sda_reg <= 1'dz;  scl_reg <= 1'dz;  end
endcase
`STOP  : case (scl_4)
0: begin sda_enable <= 1'd1; scl_enable <= 1'd1; delay_enable <= 1'd0;
sda_reg <= 1'd0;  scl_reg <= 1'd0; end
1: begin sda_reg <= 1'd0;  scl_reg <= 1'd0; end
2: begin sda_reg <= 1'd0;  scl_reg <= 1'd1; end
3: begin sda_reg <= 1'd1;  scl_reg <= 1'd1; end
4: delay_enable <= 1'd1;
default  begin sda_reg <= 1'dz;  scl_reg <= 1'dz; end
endcase
`Se    : case (scl_4)
0: begin sda_enable <= 1'd1; scl_enable <= 1'd1; delay_enable <= 1'd0;
sda_reg <= 1'd0;            scl_reg <= 1'd0;  end
1: begin sda_reg <= SEND_buffer[7];  scl_reg <= 1'd0;  end
2: begin sda_reg <= SEND_buffer[7];  scl_reg <= 1'd1;  end
3: begin sda_reg <= SEND_buffer[7];  scl_reg <= 1'd1;  end
4: begin                             scl_reg <= 1'd0;  end
5: begin sda_reg <= SEND_buffer[6];  scl_reg <= 1'd0;  end
6: begin sda_reg <= SEND_buffer[6];  scl_reg <= 1'd1;  end
7: begin sda_reg <= SEND_buffer[6];  scl_reg <= 1'd1;  end
8: begin                             scl_reg <= 1'd0;  end
9: begin sda_reg <= SEND_buffer[5];  scl_reg <= 1'd0;  end
10: begin sda_reg <= SEND_buffer[5];  scl_reg <= 1'd1;  end
11: begin sda_reg <= SEND_buffer[5];  scl_reg <= 1'd1;  end
12: begin                             scl_reg <= 1'd0;  end
13: begin sda_reg <= SEND_buffer[4];  scl_reg <= 1'd0;  end
14: begin sda_reg <= SEND_buffer[4];  scl_reg <= 1'd1;  end
15: begin sda_reg <= SEND_buffer[4];  scl_reg <= 1'd1;  end
16: begin                             scl_reg <= 1'd0;  end
17: begin sda_reg <= SEND_buffer[3];  scl_reg <= 1'd0;  end
18: begin sda_reg <= SEND_buffer[3];  scl_reg <= 1'd1;  end
19: begin sda_reg <= SEND_buffer[3];  scl_reg <= 1'd1;  end
20: begin                             scl_reg <= 1'd0;  end
21: begin sda_reg <= SEND_buffer[2];  scl_reg <= 1'd0;  end
22: begin sda_reg <= SEND_buffer[2];  scl_reg <= 1'd1;  end
23: begin sda_reg <= SEND_buffer[2];  scl_reg <= 1'd1;  end
24: begin                             scl_reg <= 1'd0;  end
25: begin sda_reg <= SEND_buffer[1];  scl_reg <= 1'd0;  end
26: begin sda_reg <= SEND_buffer[1];  scl_reg <= 1'd1;  end
27: begin sda_reg <= SEND_buffer[1];  scl_reg <= 1'd1;  end
28: begin                             scl_reg <= 1'd0;  end
29: begin sda_reg <= SEND_buffer[0];  scl_reg <= 1'd0;  end
30: begin sda_reg <= SEND_buffer[0];  scl_reg <= 1'd1;  end
31: begin sda_reg <= SEND_buffer[0];  scl_reg <= 1'd1;  end
//此时序之后必须释放掉sda控制权  等待响应
32: begin  sda_enable <= 1'd0; scl_enable <= 1'd0; delay_enable <= 1'd1;
ack_reg <= 1'd0;           scl_reg <= 1'd0;  end //这里出现了一个警告,因为ack_reg没有利用到
33: begin  ack_reg <= sda;            scl_reg <= 1'd0;  end
34: begin  ack_reg <= sda;            scl_reg <= 1'd1;  end
35: begin  ack_reg <= sda;            scl_reg <= 1'd1;  end
//此时IC有可能在一个时钟下来不及响应,从而导致主机没有接收到响应信号
default  begin                        scl_reg <= 1'dz;      end
endcase

`Re  : case (scl_4)
0: begin  sda_enable <= 1'd0; scl_enable <= 1'd1; delay_enable <= 1'd0;
scl_reg <= 1'd0;  end
1: begin                        scl_reg <= 1'd0;  end
2: begin                        scl_reg <= 1'd1;  end
3: begin Re_buffer[7] <= sda;   scl_reg <= 1'd1;  end
4: begin                        scl_reg <= 1'd0;  end
5: begin                        scl_reg <= 1'd0;  end
6: begin                        scl_reg <= 1'd1;  end
7: begin Re_buffer[6] <= sda;   scl_reg <= 1'd1;  end
8: begin                        scl_reg <= 1'd0;  end
9: begin                        scl_reg <= 1'd0;  end
10: begin                        scl_reg <= 1'd1;  end
11: begin Re_buffer[5] <= sda;   scl_reg <= 1'd1;  end
12: begin                        scl_reg <= 1'd0;  end
13: begin                        scl_reg <= 1'd0;  end
14: begin                        scl_reg <= 1'd1;  end
15: begin Re_buffer[4] <= sda;   scl_reg <= 1'd1;  end
16: begin                        scl_reg <= 1'd0;  end
17: begin                        scl_reg <= 1'd0;  end
18: begin                        scl_reg <= 1'd1;  end
19: begin Re_buffer[3] <= sda;   scl_reg <= 1'd1;  end
20: begin                        scl_reg <= 1'd0;  end
21: begin                        scl_reg <= 1'd0;  end
22: begin                        scl_reg <= 1'd1;  end
23: begin Re_buffer[2] <= sda;   scl_reg <= 1'd1;  end
24: begin                        scl_reg <= 1'd0;  end
25: begin                        scl_reg <= 1'd0;  end
26: begin                        scl_reg <= 1'd1;  end
27: begin Re_buffer[1] <= sda;   scl_reg <= 1'd1;  end
28: begin                        scl_reg <= 1'd0;  end
29: begin                        scl_reg <= 1'd0;  end
30: begin                        scl_reg <= 1'd1;  end
31: begin Re_buffer[0] <= sda;   scl_reg <= 1'd1;  end
//此时序之后主机夺回sda控制权,延时开始
32: begin sda_enable <= 1'd1; delay_enable <= 1'd1;
sda_reg <= 0; scl_reg <= 1'd0;  end
33: begin  sda_reg <= 0; scl_reg <= 1'd0;  end
34: begin  sda_reg <= 0; scl_reg <= 1'd1;  end
35: begin  sda_reg <= 0; scl_reg <= 1'd1;  end
default  begin sda_reg <= 1'dz;    scl_reg <= 1'dz;end
endcase
endcase
//-------外部数据线 控制模块----------end---------------

assign sda = sda_enable ? sda_reg : 1'dz ;
assign scl = scl_enable ? scl_reg : 1'dz ;
//====================================================================================

//--------------数码管显示部分=======只显示了一部分,有待优化============================
always @ ( posedge clock or negedge reset)
if (!reset)
begin
sel_seg <= 6'b111110;
end
else if(state_finish_flag)
begin
sel_seg <= {sel_seg[4:0],sel_seg[5]};
end
//------------------------------------------------
always @(posedge clock or negedge reset)
if (!reset) out_seg <= 8'd0;
else
begin
case (Re_buffer[3:0])  //刚开始这里没有[3:0] 居然没有报错,连个警告都没有,这是为什么呢
4'b0000  :  out_seg<=8'b1100_0000;//0000_0011
4'b0001  :  out_seg<=8'b1111_1001;//1001_1111
4'b0010  :  out_seg<=8'b1010_0100;//0010_0101
4'b0011  :  out_seg<=8'b1011_0000;//0000_1101
4'b0100  :  out_seg<=8'b1001_1001;//1001_1001
4'b0101  :  out_seg<=8'b1001_0010;//0100_1001
4'b0110  :  out_seg<=8'b1000_0010;//0100_0001
4'b0111  :  out_seg<=8'b1111_1000;//0001_1111
4'b1000  :  out_seg<=8'b1000_0000;//0000_0001
4'b1001  :  out_seg<=8'b1001_1000;//0001_1001
4'b1010  :  out_seg<=8'b1000_1000;//0001_0001
4'b1011  :  out_seg<=8'b1000_0011;//1100_0001
4'b1100  :  out_seg<=8'b1100_0110;//0110_0011
4'b1101  :  out_seg<=8'b1010_0001;//1000_0101
4'b1110  :  out_seg<=8'b1000_0110;//0110_0001
4'b1111  :  out_seg<=8'b1000_1110;//0111_0001
endcase
end
//-------------------------------=================================

endmodule
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: