清霜一梦

用Verilog实现IIC通讯

0
阅读(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