Verilog实现IIC通讯第二版
0赞
发表于 8/14/2013 1:56:52 PM
阅读(1379)
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