cyclone4驱动LM75A温湿度传感器学习

1. LM75A第一次使用,I2C接口,8脚

2. 打开quartus工程,下面只要是看看代码结构,问题在于多个always语句,逻辑上不太好分清楚,主要看状态机

  1 module I2C_READ(
  2        clk,
  3 rst_n,
  4 scl,sda,data
  5               );
  6  
  7 input clk;//总线时钟 50MHz  
  8 input rst_n;//异步复位,低电平有效  
  9   
 10 output scl;//SCL 时钟  
 11 inout  sda;// SDA 数据总线  
 12 output [15:0] data;//温度数据  
 13   
 14 reg [15:0]data_r;//温度数据寄存器  
 15 reg scl;//SCL 总线寄存器  
 16 reg sda_r;//SDA 总线寄存器  
 17 reg sda_link;//SDA 总线数据方向标志  
 18 reg [7:0]scl_cnt;//SCL 时钟产生计数器  
 19 reg [2:0]cnt;//用来标记SCL时钟计数器  
 20 reg [25:0]timer_cnt;//定时器,每隔2s 读取一次温度数据  
 21 reg [3:0]data_cnt;//数据串并转换寄存器  
 22 reg [7:0]address_reg;//器件地址寄存器  
 23 reg [8:0]state;//状态寄存器  
 24 //////////////////////////////////////////////////////////////////////////////////  
 25 //进程1、2、3:产生SCL 总线时钟  
 26 always@(posedge clk or negedge rst_n)  
 27     begin  
 28         if(!rst_n)  
 29             scl_cnt <= 8'd0;  
 30         else if(scl_cnt == 8'd199)  
 31             scl_cnt <= 8'd0;  
 32         else  
 33             scl_cnt <= scl_cnt + 1'b1;  
 34     end  
 35 always@(posedge clk or negedge rst_n)  
 36     begin  
 37         if(!rst_n)  
 38             cnt <= 3'd5;  
 39         else   
 40             case(scl_cnt)  
 41                 8'd49: cnt <= 3'd1;//高电平中间  
 42                 8'd99: cnt <= 3'd2;//下降沿  
 43                 8'd149:cnt <= 3'd3;//低电平中间  
 44                 8'd199:cnt <= 3'd0;//上升沿  
 45                default: cnt <= 3'd5;  
 46             endcase  
 47     end  
 48 `define SCL_HIG (cnt == 3'd1)  
 49 `define SCL_NEG (cnt == 3'd2)  
 50 `define SCL_LOW (cnt == 3'd3)  
 51 `define SCL_POS (cnt == 3'd0)  
 52 always@(posedge clk or negedge rst_n)  
 53     begin  
 54         if(!rst_n)  
 55             scl <= 1'b0;  
 56         else if(`SCL_POS)  
 57             scl <= 1'b1;  
 58         else if(`SCL_NEG)  
 59             scl <= 1'b0;  
 60     end  
 61 //////////////////////////////////////////////////////////////////////////////////  
 62 //进程4:定时器,每隔1s 读取一次温度数据  
 63 always@(posedge clk or negedge rst_n)  
 64     begin  
 65         if(!rst_n)  
 66             timer_cnt <= 26'd0;  
 67         else if(timer_cnt == 26'd49999999)  
 68             timer_cnt <= 26'd0;  
 69         else   
 70             timer_cnt <= timer_cnt + 1'b1;  
 71     end  
 72 //////////////////////////////////////////////////////////////////////////////////  
 73 //状态机定义  
 74 parameter IDLE  = 9'b0_0000_0000,  
 75              START  = 9'b0_0000_0010,  
 76              ADDRESS    = 9'b0_0000_0100,  
 77              ACK1       = 9'b0_0000_1000,  
 78              READ1  = 9'b0_0001_0000,  
 79              ACK2       = 9'b0_0010_0000,  
 80              READ2  = 9'b0_0100_0000,  
 81              NACK       = 9'b0_1000_0000,  
 82              STOP       = 9'b1_0000_0000;  
 83 `define DEVICE_ADDRESS 8'b1001_0001//器件地址,读操作  
 84 //////////////////////////////////////////////////////////////////////////////////  
 85 //进程5:状态机描述  
 86 always@(posedge clk or negedge rst_n)  
 87     begin  
 88         if(!rst_n)  
 89             begin  
 90                 data_r  <= 16'd0;  
 91                 sda_r       <= 1'b1;  
 92                 sda_link    <= 1'b1;  
 93                 state       <= IDLE;  
 94                 address_reg <= 15'd0;  
 95                 data_cnt    <= 4'd0;  
 96             end  
 97         else   
 98             case(state)  
 99                 IDLE:  
100                     begin  
101                         sda_r   <= 1'b1;  
102                         sda_link <= 1'b1;  
103                         if(timer_cnt == 26'd49999999)  
104                             state <= START;  
105                         else  
106                             state <= IDLE;  
107                     end  
108                 START://产生起始信号  
109                     begin  
110                         if(`SCL_HIG)  
111                             begin  
112                                 sda_r       <= 1'b0;  
113                                 sda_link    <= 1'b1;  
114                                 address_reg <= `DEVICE_ADDRESS;  
115                                 state           <= ADDRESS;  
116                                 data_cnt        <= 4'd0;  
117                             end  
118                         else  
119                             state <= START;  
120                     end  
121                 ADDRESS://主机对器件进行寻址  
122                     begin  
123                         if(`SCL_LOW)  
124                             begin  
125                                 if(data_cnt == 4'd8)//寻址完成,SDA改变方向,器件准备输出应答讯号  
126                                     begin  
127                                         state   <= ACK1;  
128                                         data_cnt <=  4'd0;  
129                                         sda_r       <= 1'b1;  
130                                         sda_link    <= 1'b0;  
131                                     end  
132                                 else//寻址过程中,SDA对器件作为输入  
133                                     begin  
134                                         state   <= ADDRESS;  
135                                         data_cnt <= data_cnt + 1'b1;  
136                                         case(data_cnt)  
137                                             4'd0: sda_r <= address_reg[7];  
138                                             4'd0: sda_r <= address_reg[7];  
139                                             4'd1: sda_r <= address_reg[6];  
140                                             4'd2: sda_r <= address_reg[5];  
141                                             4'd3: sda_r <= address_reg[4];  
142                                             4'd4: sda_r <= address_reg[3];  
143                                             4'd5: sda_r <= address_reg[2];  
144                                             4'd6: sda_r <= address_reg[1];  
145                                             4'd7: sda_r <= address_reg[0];  
146                                             default: ;  
147                                         endcase  
148                                     end  
149                             end  
150                         else  
151                             state <= ADDRESS;  
152                     end  
153                 ACK1://器件输出应答信号  
154                     begin  
155                         if(!sda && (`SCL_HIG))  
156                             state <= READ1;  
157                         else if(`SCL_NEG)  
158                             state <= READ1;  
159                         else  
160                             state <= ACK1;  
161                     end  
162                 READ1://读器件数据,高字节  
163                     begin  
164                         if((`SCL_LOW) && (data_cnt == 4'd8))//读高字节数据完成,SDA改变方向,主机准备输出应答讯号  
165                             begin  
166                                 state   <= ACK2;  
167                                 data_cnt <= 4'd0;  
168                                 sda_r       <= 1'b1;  
169                                 sda_link    <= 1'b1;  
170                             end  
171                         else if(`SCL_HIG)//读数据过程中,器件作为输出,这里有疑问,不是应该的等SCL一个时钟吗?SCL_HIG
172                             begin  
173                                 data_cnt <= data_cnt + 1'b1;  
174                                 case(data_cnt)  
175                                     4'd0: data_r[15] <= sda;  
176                                     4'd1: data_r[14] <= sda;  
177                                     4'd2: data_r[13] <= sda;  
178                                     4'd3: data_r[12] <= sda;  
179                                     4'd4: data_r[11] <= sda;  
180                                     4'd5: data_r[10] <= sda;  
181                                     4'd6: data_r[9]  <= sda;  
182                                     4'd7: data_r[8]  <= sda;  
183                                     default: ;  
184                                 endcase  
185                             end  
186                         else  
187                             state <= READ1;  
188                     end  
189                 ACK2://主机输出应答讯号  
190                     begin     
191                         if(`SCL_LOW)  
192                             sda_r <= 1'b0;  
193                         else if(`SCL_NEG)  
194                             begin  
195                                 sda_r   <= 1'b1;  
196                                 sda_link    <= 1'b0;  
197                                 state       <= READ2;  
198                             end  
199                         else  
200                             state <= ACK2;  
201                     end  
202                 READ2://读低字节数据  
203                     begin  
204                         if((`SCL_LOW) && (data_cnt == 4'd8))  
205                             begin  
206                                 state   <= NACK;  
207                                 data_cnt <= 4'd0;  
208                                 sda_r       <= 1'b1;  
209                                 sda_link    <= 1'b1;  
210                             end  
211                         else if(`SCL_HIG)  
212                             begin  
213                                 data_cnt <= data_cnt + 1'b1;  
214                                 case(data_cnt)  
215                                     4'd0: data_r[7] <= sda;  
216                                     4'd1: data_r[6] <= sda;  
217                                     4'd2: data_r[5] <= sda;  
218                                     4'd3: data_r[4] <= sda;  
219                                     4'd4: data_r[3] <= sda;  
220                                     4'd5: data_r[2] <= sda;  
221                                     4'd6: data_r[1]  <= sda;  
222                                     4'd7: data_r[0]  <= sda;  
223                                     default: ;  
224                                 endcase  
225                             end  
226                         else  
227                             state <= READ2;  
228                     end  
229                 NACK://主机非应答  
230                     begin  
231                         if(`SCL_LOW)  
232                             begin  
233                                 state <= STOP;  
234                                 sda_r   <= 1'b0;  
235                             end  
236                         else  
237                             state <= NACK;  
238                     end  
239                 STOP:  
240                     begin  
241                         if(`SCL_HIG)  
242                             begin  
243                                 state <= IDLE;  
244                                 sda_r <= 1'b1;  
245                             end  
246                         else  
247                             state <= STOP;  
248                     end  
249                 default: state <= IDLE;  
250             endcase  
251     end  
252 assign sda   = sda_link ? sda_r: 1'bz;  
253 assign data  = data_r;  
254 endmodule

3. 这个代码需要好好研究下,有疑问的地方,data_cnt <= data_cnt + 1'b1;每次读一位的时候,SCL应该有一个时钟,按照这个时钟去读的,为啥代码使用data_cnt这个变量,感觉不对啊?这里不是很明白

 1  begin  
 2 134                                         state   <= ADDRESS;  
 3 135                                         data_cnt <= data_cnt + 1'b1;  
 4 136                                         case(data_cnt)  
 5 137                                             4'd0: sda_r <= address_reg[7];  
 6 138                                             4'd0: sda_r <= address_reg[7];  
 7 139                                             4'd1: sda_r <= address_reg[6];  
 8 140                                             4'd2: sda_r <= address_reg[5];  
 9 141                                             4'd3: sda_r <= address_reg[4];  
10 142                                             4'd4: sda_r <= address_reg[3];  
11 143                                             4'd5: sda_r <= address_reg[2];  
12 144                                             4'd6: sda_r <= address_reg[1];  
13 145                                             4'd7: sda_r <= address_reg[0];  
14 146                                             default: ;  
15 147                                         endcase  
16 148                                     end  
原文地址:https://www.cnblogs.com/429512065qhq/p/8093270.html