用Verilog实现IIC通讯
0赞
发表于 7/9/2013 1:54:58 PM
阅读(1690)
注意,此代码是错误代码,并不能实现想要的结果。
之所以留着,因为里面的enable 是独立开来的思想值得借鉴。就是控制单元和运算单元分开(我也是借鉴别人的实现思想)。具体用verilogHDL实现IIC通讯在http://www.cnblogs.com/sepeng/p/3258705.html 里会做到。
//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 MEASURE 1
`define START 2
`define Re 3
`define Se 4
`define STOP 5
//`default_nettype none
module HMC5883_IIC (
clock,reset,
sda,scl,
out_seg,
sel_seg
);
input clock,reset;
inout sda,scl;
output reg [7:0]out_seg;
output reg [5:0]sel_seg;
reg [7:0] SEND_buffer;
reg [7:0] Re_buffer ;
reg sda_reg;
reg scl_reg;
reg sda_enable;
reg scl_enable;
reg IC_state;
reg [2:0]state; //当前状态寄存器
reg state_finish_flag ; //
reg [5:0] clk_counter;
reg [3:0] step_counter;
reg [5:0] clk_temp ;
//-------------------------时钟控制模块-------------------------------start------------------
always @ (posedge clock or negedge reset)
if (!reset)
begin
clk_temp <= 6'd0;
clk_counter <= 6'd0;
end
else if (clk_temp[5])
begin
clk_temp <= 6'd0;
if (state_finish_flag) clk_counter <= 6'd0;
else if (clk_counter == 6'b111_111) //这里是一个保护机制,可以设置一个flag
begin
clk_counter <= 6'b111_111;
end
else clk_counter <= clk_counter + 1;
end
else clk_temp <= clk_temp + 1;
//-------------------------时钟控制模块-----------------------------------end------------------
//-----------------状态机控制模块------------------------------------------start-------------------
always @ (posedge clock or negedge reset)
if(!reset)
IC_state <= `INITIAL;
else IC_state <= `MEASURE;
always @ (posedge clock or negedge reset)
if (!reset)
begin
step_counter <= 4'd0;
SEND_buffer <= 8'd0;
end
else if(IC_state == `INITIAL)
case (step_counter)
0: begin state <= `START; step_counter <= step_counter + 1;end
1: begin SEND_buffer <= 8'h3c;state <= `Se; step_counter <= step_counter + 1; end
2: begin SEND_buffer <= 8'h02;state <= `Se; step_counter <= step_counter + 1; end
3: begin SEND_buffer <= 8'h00;state <= `Se; step_counter <= step_counter + 1; end
4: begin SEND_buffer <= 8'h00;state <= `Se; step_counter <= step_counter + 1; end
default step_counter <= 4'd0;
endcase
else if (IC_state == `MEASURE)
case (step_counter)
0: begin state <= `START; step_counter <= step_counter + 1;end
1: begin SEND_buffer <= 8'h3c;state <= `Se; step_counter <= step_counter + 1; end
2: begin SEND_buffer <= 8'h03;state <= `Se; step_counter <= step_counter + 1; end
3: begin state <= `START; step_counter <= step_counter + 1;end
4: begin SEND_buffer <= 8'h3d;state <= `Se; step_counter <= step_counter + 1; end
5: begin state <= `Re; step_counter <= step_counter + 1; end
6: begin state <= `Re; step_counter <= step_counter + 1; end
7: begin state <= `Re; step_counter <= step_counter + 1; end
8: begin state <= `Re; step_counter <= step_counter + 1; end
9: begin state <= `Re; step_counter <= step_counter + 1; end
10: begin state <= `Re; step_counter <= step_counter + 1; end
11: begin state <= `Re; step_counter <= step_counter + 1; end
12: begin state <= `Re; step_counter <= step_counter + 1; end
13: begin state <= `STOP; step_counter <= 4'd0; end
default step_counter <= 4'd0;
endcase
//-----------------状态机控制模块-------------------------------------------end---------------------
//------------------------------------------使能控制模块--------------------------start---------------
always @ (posedge clk_counter or negedge reset)
if (!reset)
begin
sda_enable <= 1'd0;
scl_enable <= 1'd0;
end
else case (state)
`START : begin
if(clk_counter >= 6'd4)
begin
sda_enable <= 1'd0;
scl_enable <= 1'd0;
end
else
begin
sda_enable <= 1'd1;
scl_enable <= 1'd1;
end
end
`STOP : begin
if(clk_counter >= 6'd4)
begin
sda_enable <= 1'd0;
scl_enable <= 1'd0;
end
else
begin
sda_enable <= 1'd1;
scl_enable <= 1'd1;
end
end
`Se : begin
if(clk_counter >= 6'd36) //send 完成之后释放掉使能
begin
sda_enable <= 1'd0;
scl_enable <= 1'd0;
end
else
begin
sda_enable <= 1'd1;
scl_enable <= 1'd1;
end
end
`Re : begin
if(clk_counter >= 6'd32) //receive 完成之后释放掉使能
begin
sda_enable <= 1'd0;
scl_enable <= 1'd0;
end
else
begin
sda_enable <= 1'd1;
scl_enable <= 1'd1;
end
end
endcase
//------------------------------------------使能控制模块--------------------------end---------------
//------------------------------------------------外部数据线 控制模块-----------------start---------------
always @ (posedge clk_counter or negedge reset)
if(!reset)
begin
sda_reg <= 1'd0;
scl_reg <= 1'd0;
state_finish_flag <= 1'd0;
Re_buffer <= 8'd0;
end
else case (state)
`START : begin
case (clk_counter)
0: begin sda_reg <= 1'd1; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
1: begin sda_reg <= 1'd1; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
2: begin sda_reg <= 1'd1; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
3: begin sda_reg <= 1'd0; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
default begin sda_reg <= 1'dz; scl_reg <= 1'dz; state_finish_flag <= 1'd1; end
endcase
end
`STOP : begin
case (clk_counter)
0: begin sda_reg <= 1'd0; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
1: begin sda_reg <= 1'd0; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
2: begin sda_reg <= 1'd0; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
3: begin sda_reg <= 1'd1; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
default begin sda_reg <= 1'dz; scl_reg <= 1'dz; state_finish_flag <= 1'd1; end
endcase
end
`Se : begin
case (clk_counter)
0: begin sda_reg <= 1'd0; scl_reg <= 1'd0; end
1: begin sda_reg <= SEND_buffer[7]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
2: begin sda_reg <= SEND_buffer[7]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
3: begin sda_reg <= SEND_buffer[7]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
4: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
5: begin sda_reg <= SEND_buffer[6]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
6: begin sda_reg <= SEND_buffer[6]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
7: begin sda_reg <= SEND_buffer[6]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
8: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
9: begin sda_reg <= SEND_buffer[5]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
10: begin sda_reg <= SEND_buffer[5]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
11: begin sda_reg <= SEND_buffer[5]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
12: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
13: begin sda_reg <= SEND_buffer[4]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
14: begin sda_reg <= SEND_buffer[4]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
15: begin sda_reg <= SEND_buffer[4]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
16: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
17: begin sda_reg <= SEND_buffer[3]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
18: begin sda_reg <= SEND_buffer[3]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
19: begin sda_reg <= SEND_buffer[3]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
20: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
21: begin sda_reg <= SEND_buffer[2]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
22: begin sda_reg <= SEND_buffer[2]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
23: begin sda_reg <= SEND_buffer[2]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
24: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
25: begin sda_reg <= SEND_buffer[1]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
26: begin sda_reg <= SEND_buffer[1]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
27: begin sda_reg <= SEND_buffer[1]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
28: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
29: begin sda_reg <= SEND_buffer[0]; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
30: begin sda_reg <= SEND_buffer[0]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
31: begin sda_reg <= SEND_buffer[0]; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
32: begin /*state_finish_flag <= sda;*/ scl_reg <= 1'd0; /*state_finish_flag <= 1'd0; */ end
33: begin /*state_finish_flag <= sda;*/ scl_reg <= 1'd0; /*state_finish_flag <= 1'd0; */ end
34: begin /*state_finish_flag <= sda;*/ scl_reg <= 1'd1; /*state_finish_flag <= 1'd0; */ end
35: begin state_finish_flag <= sda; scl_reg <= 1'd1; /*state_finish_flag <= 1'd0; */ end
default begin scl_reg <= 1'dz; state_finish_flag <= sda; end //等待响应
endcase
end
`Re : begin
case (clk_counter)
0: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
1: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
2: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
3: begin Re_buffer[7] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
4: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
5: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
6: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
7: begin Re_buffer[6] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
8: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
9: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
10: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
11: begin Re_buffer[5] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
12: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
13: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
14: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
15: begin Re_buffer[4] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
16: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
17: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
18: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
19: begin Re_buffer[3] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
20: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
21: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
22: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
23: begin Re_buffer[3] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
24: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
25: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
26: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
27: begin Re_buffer[3] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
28: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
29: begin scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
30: begin scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
31: begin Re_buffer[3] <= sda; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
// 32:begin sda_reg <= 1'd0; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end //NA
// 33:begin sda_reg <= 1'd0; scl_reg <= 1'd0; state_finish_flag <= 1'd0; end
// 34:begin sda_reg <= 1'd0; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
// 35:begin sda_reg <= 1'd0; scl_reg <= 1'd1; state_finish_flag <= 1'd0; end
default begin sda_reg <= 1'dz; scl_reg <= 1'dz; state_finish_flag <= 1'd1; end
endcase
end
endcase
//------------------------------------------------外部数据线 控制模块-----------------end---------------
assign sda = sda_enable ? sda_reg : 1'dz ;
assign scl = scl_enable ? scl_reg : 1'dz ;
always @ (posedge clk_counter 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)
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
