前言:终于到了测试篇,不过悲剧了一下。按照之前《二》里面的思路,在顶层用一个复用器驱动读写独立模块的I2C总线确实失败。虽然综合过去了,不过警告里已经说明:底层的2个原本是inout三态口的数据线在顶层复用时候被综合成wire,这样在默认情况下顶层的inout总是输出有效,失去了三态口的作用。囧,看来为了测试I2C的写还是得把读模块并进去可避免这一尴尬……
测试:DE2+Questasim10.0c+Q2_9.1;
日期:2013七夕夜
结果:以下2张图为仿真波形图与逻辑分析仪采样的时序波形图。之前还踩不到ACK信号,因为宏定义里读写器件的地址弄饭了。(若这里程序与之前的《一》《二》有出路须以此篇修改之后为准)。对比可知基本上二者相同,也踩到从器件的相应。不过有个问题,在响应的一个完整时钟周期里的后四分之一变成高电平,也就是说一个ACK仅仅保持了四分之三的低电平,这个是不是应该算正常?如果从数据有效来看,时钟高电平保持了ACK一直为低电平,似乎是对的。
解决:出现这样目前只好等读模块嵌入,如果能读出正确写入的数据,那么说明是正常的。
last update:因为其他时间耽搁了,断断续续终于今天整理完毕。仿真和硬件均测试通过。最后附出仿真文件、建模源码以及tcl脚本。
总结:IIC中从机响应脉冲宽度并未填满一整个周期,这也是之前图里的疑问。如何分辨正确:仅记ack和nack在时钟上升沿改变在时钟下降沿即可改变;不同器件数据变化时间时刻不一样,如果移植到不同器件测试得到不用stp2也无需惊讶,抓住根本的就行;
源码1:iic读写控制器
1 `timescale 1 ns / 1 ps 2 `define SIM 3 `define SYS_CLK 50000000 4 `define IIC_CLK 100000 5 `define IIC_CLK_DIV `SYS_CLK/`IIC_CLK 6 `define ADV7181B 7 `define SCLK_CNT_WIDTH 9 8 //VERSION:V0.0 9 module iic_ctrl( 10 //common 11 sys_clk, 12 sys_rst_n, 13 iic_sclk, 14 iic_sdat, 15 //read 16 rreq_i, 17 iic_rd_addr_i, 18 rd_en_i, 19 iic_rd_ack_o, 20 sys_byte_o, 21 //write 22 wreq_i, 23 wr_en_i, 24 iic_wr_addr_i, 25 sys_byte_i, 26 iic_wr_ack_o 27 ); 28 //common port 29 input sys_clk; //global clk in 30 input sys_rst_n; //global rst_n in 31 output iic_sclk; //iic sclk 32 inout iic_sdat; //iic sdat 33 //read port 34 input rreq_i; //read requast in 35 input [7:0] iic_rd_addr_i; //read register address in 36 input rd_en_i; //read enable in 37 output iic_rd_ack_o; //module read ack 38 output [7:0] sys_byte_o; //read byte out 39 //write port 40 input wreq_i; //write request in 41 input wr_en_i; //write enable in 42 input [7:0] iic_wr_addr_i; //write register address in 43 input [7:0] sys_byte_i; //byte to be written 44 output iic_wr_ack_o; //module write ack 45 //macro 46 `ifdef ADV7181B 47 parameter DEVICE_READ = 8'h41; //器件读操作地址 48 parameter DEVICE_WRITE = 8'h40; //器件写操作地址 49 `endif 50 //marcro 51 `ifdef SIM 52 parameter ST_WIDTH = 56; 53 parameter IDLE = "IDLE...", 54 START1 = "START1.", 55 WR_SLAVE = "WR_SLAV", 56 ACK1 = "ACK1...", 57 SET_REG = "SET_REG", 58 ACK2 = "ACK2...", 59 WR_DATA = "WR_DATA", 60 ACK3 = "ACK3...", 61 STOP = "STOP..."; 62 parameter START2 = "START2.", 63 RD_SLAVE = "RD_SLAV", 64 ACK4 = "ACK4...", 65 RD_DATA = "RD_DATA", 66 NACK = "NACK..."; 67 68 `else 69 `define FSM 14 70 parameter ST_WIDTH = 14; 71 parameter IDLE = `FSM'b00_0000_0000_0001, 72 START1 = `FSM'b00_0000_0000_0010, //写操作一共有1个start,读操作一共2个start 73 WR_SLAVE = `FSM'b00_0000_0000_0100, 74 ACK1 = `FSM'b00_0000_0000_1000, 75 SET_REG = `FSM'b00_0000_0001_0000, 76 ACK2 = `FSM'b00_0000_0010_0000, 77 WR_DATA = `FSM'b00_0000_0100_0000, 78 ACK3 = `FSM'b00_0000_1000_0000, 79 STOP = `FSM'b00_0001_0000_0000; 80 parameter START2 = `FSM'b00_0010_0000_0000, 81 RD_SLAVE = `FSM'b00_0100_0000_0000, 82 ACK4 = `FSM'b00_1000_0000_0000, 83 RD_DATA = `FSM'b01_0000_0000_0001, 84 NACK = `FSM'b10_0000_0000_0001; 85 `endif 86 //caputre the posedge of rreq_i; 87 reg rreq_r0 = 0; 88 always @ (posedge sys_clk) begin 89 if(sys_rst_n == 1'b0) rreq_r0 <= 0; 90 else rreq_r0 <= rreq_i; 91 end 92 wire do_rreq = rreq_i & ~rreq_r0 & rd_en_i; 93 //generate the rd_start; 94 reg rd_start = 0; 95 always @ (posedge sys_clk) begin 96 if(sys_rst_n == 1'b0) rd_start <= 0; 97 else if(iic_rd_ack_o == 1'b1) rd_start <= 0; 98 else if(do_rreq) rd_start <= 1; 99 else rd_start <= rd_start; 100 end 101 //caputre the posedge of wreq_i; 102 reg wreq_r0 = 0; 103 always @ (posedge sys_clk) begin 104 if(sys_rst_n == 1'b0) wreq_r0 <= 0; 105 else wreq_r0 <= wreq_i; 106 end 107 wire do_wreq = wreq_i & ~wreq_r0 & wr_en_i; 108 //generate the wr_start; 109 reg wr_start = 0; 110 always @ (posedge sys_clk) begin 111 if(sys_rst_n == 1'b0) wr_start <= 0; 112 else if(iic_wr_ack_o == 1'b1) wr_start <= 0; 113 else if(do_wreq) wr_start <= 1; 114 else wr_start <= wr_start; 115 end 116 //GENERATE SCLK 117 reg [`SCLK_CNT_WIDTH-1:0] sclk_cnt = 0; 118 wire sclk_cnt_en1 = ((sclk_cnt < `IIC_CLK_DIV-1)&&(wr_en_i == 1'b1)&&(wr_start == 1'b1))?1'b1:1'b0; 119 wire sclk_cnt_en2 = ((sclk_cnt < `IIC_CLK_DIV-1)&&(rd_en_i == 1'b1)&&(rd_start == 1'b1))?1'b1:1'b0; 120 always @ (posedge sys_clk) begin 121 if(1'b0 == sys_rst_n) sclk_cnt <= 0; 122 else if(sclk_cnt_en1 | sclk_cnt_en2) sclk_cnt <= sclk_cnt + 1'd1; 123 else sclk_cnt <= 0; 124 end 125 //时间片 126 `define SCLK_POS (sclk_cnt == `SCLK_CNT_WIDTH'd499) 127 `define SCLK_HIGH (sclk_cnt == `SCLK_CNT_WIDTH'd124) 128 `define SCLK_NEG (sclk_cnt == `SCLK_CNT_WIDTH'd249) 129 `define SCLK_LOW (sclk_cnt == `SCLK_CNT_WIDTH'd374) 130 //内部i2c串行时钟 131 wire iic_sclk_w = ((sclk_cnt <= `SCLK_CNT_WIDTH'd249)&&(rd_en_i | wr_en_i))?1'b1:1'b0; 132 //fsm registers 133 reg [7:0] iic_byte = 0; 134 reg [7:0] sys_byte_o = 0; 135 reg sdat_r = 1; 136 reg link = 0; //read:0 137 reg [3:0] bit_cnt = 0; 138 reg [ST_WIDTH-1:0] c_st = IDLE; 139 reg [ST_WIDTH-1:0] n_st = IDLE; 140 //FSM-1 141 always @ (posedge sys_clk) begin 142 if(1'b0 == sys_rst_n) c_st <= IDLE; 143 else c_st <= n_st; 144 end 145 //FSM-2,实际的状态转移中ack[2:0]比物理等待的ack少四分之一 146 always @ (*) begin 147 n_st = IDLE; 148 case(c_st) 149 IDLE:begin 150 n_st = ((wr_start == 1'b1)||(rd_start == 1'b1))?START1:IDLE;end 151 START1:begin 152 n_st = (`SCLK_LOW)?WR_SLAVE:START1;end //sclk为高电平中心时转移 153 WR_SLAVE:begin 154 n_st = ((`SCLK_LOW)&&(bit_cnt == 4'd8))?ACK1:WR_SLAVE;end//数据在低电平是更新 155 ACK1:begin 156 n_st = (`SCLK_NEG)?SET_REG:ACK1;end//为保证下一步设置寄存器,提前1/4进入下一个状态 157 SET_REG:begin 158 n_st = ((`SCLK_LOW)&&(bit_cnt == 4'd8))?ACK2:SET_REG;end//数据在低电平是更新 159 ACK2:begin 160 if(`SCLK_NEG) begin 161 n_st = (wr_start == 1'b1)?WR_DATA:START2;end 162 else begin 163 n_st = ACK2;end 164 end//为保证下一步设置寄存器,提前1/4进入下一个状态 165 WR_DATA:begin 166 n_st = ((`SCLK_LOW)&&(bit_cnt == 4'd8))?ACK3:WR_DATA;end 167 ACK3:begin 168 n_st = (`SCLK_NEG)?STOP:ACK3;end 169 STOP:begin 170 n_st = (`SCLK_NEG)?IDLE:STOP;end 171 START2:begin 172 n_st = (`SCLK_NEG)?RD_SLAVE:START2;end 173 RD_SLAVE:begin 174 n_st = ((`SCLK_LOW)&&(bit_cnt == 4'd8))?ACK4:RD_SLAVE;end 175 ACK4:begin 176 n_st = (`SCLK_NEG)?RD_DATA:ACK4;end 177 RD_DATA:begin 178 n_st = ((`SCLK_LOW)&&(bit_cnt == 4'd8))?NACK:RD_DATA;end 179 NACK:begin 180 n_st = (`SCLK_NEG)?STOP:NACK;end 181 default:begin 182 n_st = IDLE;end 183 endcase 184 end 185 //FSM-3 186 always @ (posedge sys_clk) begin 187 if(sys_rst_n == 1'b0) begin 188 link <= 1'd0; 189 iic_byte <= 0; 190 sys_byte_o <= sys_byte_o; //保持 191 bit_cnt <= 4'd0; 192 sdat_r <= 1'd1; 193 end 194 else begin 195 case(c_st) 196 IDLE:begin 197 link <= 1'd0; 198 sys_byte_o <= sys_byte_o; 199 iic_byte <= DEVICE_WRITE; 200 bit_cnt <= 4'd0; 201 sdat_r <= 1'd1; 202 end 203 START1:begin 204 link <= 1'd1; 205 bit_cnt <= 4'd1; 206 sys_byte_o <= sys_byte_o; 207 iic_byte <= (`SCLK_LOW)?iic_byte<<1:iic_byte; 208 if(`SCLK_HIGH) begin 209 sdat_r <= 1'b0;end 210 else if(`SCLK_LOW) begin 211 sdat_r <= iic_byte[7];end //pull down,由于i2c_byte缓存一级的缘故,需要提前在START里输出第MSB位 212 else begin 213 sdat_r <= sdat_r;end 214 end 215 WR_SLAVE:begin 216 sys_byte_o <= sys_byte_o; 217 if(`SCLK_LOW) begin 218 link <= (bit_cnt == 4'd8)?1'b0:1'b1; //释放数据总线 219 bit_cnt <= (bit_cnt == 4'd8)?4'd0:bit_cnt+1'd1; 220 iic_byte <= {iic_byte[6:0],1'd0};//左移一位 221 sdat_r <= (bit_cnt == 4'd8)?1'd1:iic_byte[7];end 222 else begin 223 link <= link; 224 bit_cnt <= bit_cnt; 225 iic_byte <= iic_byte; 226 sdat_r <= sdat_r;end 227 end 228 ACK1:begin 229 link <= 1'd0; 230 sys_byte_o <= sys_byte_o; 231 if(`SCLK_POS) begin 232 iic_byte <= (wr_start==1'b1)?iic_wr_addr_i:iic_rd_addr_i;end 233 else begin 234 iic_byte <= iic_byte;end //读入待写的寄存器地址 235 bit_cnt <= 4'd0; 236 sdat_r <= 1'd1; 237 end 238 SET_REG:begin 239 sys_byte_o <= sys_byte_o; 240 if(`SCLK_LOW) begin 241 link <= (bit_cnt == 4'd8)?1'b0:1'b1; //释放数据总线 242 bit_cnt <= (bit_cnt == 4'd8)?4'd0:bit_cnt+1'd1; 243 iic_byte <= {iic_byte[6:0],1'd0};//左移一位 244 sdat_r <= (bit_cnt == 4'd8)?1'd1:iic_byte[7];end 245 else begin 246 link <= link; 247 bit_cnt <= bit_cnt; 248 iic_byte <= iic_byte; 249 sdat_r <= sdat_r;end 250 end 251 ACK2:begin 252 link <= 1'd0; 253 bit_cnt <= 4'd0; 254 sdat_r <= 1'd1; 255 sys_byte_o <= sys_byte_o; 256 if(`SCLK_POS) begin 257 iic_byte <= (wr_start)?sys_byte_i:DEVICE_READ;end //读入待写的寄存器地址 258 else begin 259 iic_byte <= iic_byte;end 260 end 261 WR_DATA:begin 262 sys_byte_o <= sys_byte_o; 263 if(`SCLK_LOW) begin 264 link <= (bit_cnt == 4'd8)?1'b0:1'b1; //释放数据总线 265 bit_cnt <= (bit_cnt == 4'd8)?4'd0:bit_cnt+1'd1; 266 iic_byte <= {iic_byte[6:0],1'd0};//左移一位 267 sdat_r <= iic_byte[7];end 268 else begin 269 link <= link; 270 bit_cnt <= bit_cnt; 271 iic_byte <= iic_byte; 272 sdat_r <= sdat_r;end 273 end 274 ACK3:begin 275 sys_byte_o <= sys_byte_o; 276 link <= 1'd0; 277 sdat_r <= 1'd0;//预先拉低 278 bit_cnt <= bit_cnt; 279 iic_byte <= iic_byte;end 280 STOP:begin 281 sys_byte_o <= sys_byte_o; 282 link <= (`SCLK_LOW)?1'b1:link; 283 bit_cnt <= bit_cnt; 284 iic_byte <= iic_byte; 285 if(`SCLK_LOW) begin 286 sdat_r <= 1'b0;end 287 else if(`SCLK_HIGH) begin 288 sdat_r <= 1'b1;end 289 else begin 290 sdat_r <= sdat_r;end 291 end 292 START2:begin 293 link <= (`SCLK_LOW)?1'b1:link; 294 sys_byte_o <= sys_byte_o; 295 iic_byte <= iic_byte; 296 bit_cnt <= bit_cnt; 297 sdat_r <= (`SCLK_HIGH)?1'b0:sdat_r; 298 end 299 RD_SLAVE:begin 300 sys_byte_o <= sys_byte_o; 301 if(`SCLK_LOW) begin 302 link <= (bit_cnt == 4'd8)?1'b0:1'b1; 303 bit_cnt <= (bit_cnt == 4'd8)?4'd0:bit_cnt+1'd1; 304 iic_byte <= {iic_byte[6:0],1'd0};//左移一位 305 sdat_r <= (bit_cnt == 4'd8)?1'd1:iic_byte[7];end 306 else begin 307 link <= link; 308 bit_cnt <= bit_cnt; 309 iic_byte <= iic_byte; 310 sdat_r <= sdat_r;end 311 end 312 ACK4:begin 313 link <= 1'b0; 314 bit_cnt <= 4'd0; 315 sys_byte_o <= sys_byte_o; 316 iic_byte <= 0; 317 sdat_r <= 1'd1;end 318 RD_DATA:begin 319 sys_byte_o <= sys_byte_o; 320 if(`SCLK_POS) begin 321 link <= (bit_cnt == 4'd8)?1'b1:1'b0; //为主设备产生NACK准备 322 bit_cnt <= (bit_cnt == 4'd8)?4'd0:bit_cnt+1'd1; 323 iic_byte[7:1] <= iic_byte[6:0];//左移一位 324 iic_byte[0] <= iic_sdat;end 325 else begin 326 link <= link; 327 bit_cnt <= bit_cnt; 328 iic_byte <= iic_byte; 329 sdat_r <= sdat_r;end 330 end 331 NACK:begin 332 link <= 1'd1; 333 sdat_r <= 1'd1;//预先拉低 334 bit_cnt <= bit_cnt; 335 iic_byte <= iic_byte; 336 sys_byte_o <= iic_byte;end 337 default:begin 338 link <= 1'd0; 339 iic_byte <= 8'd0; 340 bit_cnt <= 4'd0; 341 sdat_r <= 1'd1; 342 sys_byte_o <= sys_byte_o; 343 end 344 endcase 345 end 346 end 347 //assign 348 assign iic_rd_ack_o = ((c_st == STOP)&&(`SCLK_NEG)&&(rd_start))?1'b1:1'b0; 349 assign iic_sclk = (c_st != IDLE)?iic_sclk_w:1'b1; 350 assign iic_sdat = (link == 1'b1)?sdat_r:1'bz; 351 assign iic_wr_ack_o = ((c_st == STOP)&&(`SCLK_NEG)&&(wr_start))?1'b1:1'b0; 352 353 endmodule
源码2:写iic的寄存器地址和数据,移植不同器件更改这部分查找表内容
`timescale 1 ns / 1 ps `define LUT_WIDTH 6 module wr_config( sys_clk, sys_rst_n, iic_wr_ack_i, wreq_o, sys_byte_o, iic_wr_addr_o, wr_config_done_o ); input sys_clk; input sys_rst_n; input iic_wr_ack_i; output wreq_o; output [7:0] sys_byte_o; output [7:0] iic_wr_addr_o; output wr_config_done_o; //generate wreq_o reg wreq_o = 0; reg [`LUT_WIDTH-1:0] lut_index = 0; reg [15:0] lut_data = 0; always @ (posedge sys_clk) begin if(1'b0 == sys_rst_n) begin wreq_o <= 1; lut_index <= 0;end else if((iic_wr_ack_i == 1'b1)&&(wr_config_done_o == 1'b0)) begin wreq_o <= 1; lut_index <= lut_index + 1'd1;end else begin wreq_o <= 0; lut_index <= lut_index;end end //generate done reg wr_config_done_o = 0; always @ (posedge sys_clk) begin if(sys_rst_n == 1'b0) wr_config_done_o <= 0; else if((lut_index == 6'd34) && (iic_wr_ack_i == 1'b1)) wr_config_done_o <= 1; else wr_config_done_o <= wr_config_done_o; end //assign assign sys_byte_o = lut_data[7:0]; assign iic_wr_addr_o = lut_data[15:8]; //lut always @ (*) begin case(lut_index) `LUT_WIDTH'd0:lut_data <= 16'h0080; `LUT_WIDTH'd1:lut_data <= 16'h0701; `LUT_WIDTH'd2:lut_data <= 16'h1500; `LUT_WIDTH'd3:lut_data <= 16'h1741; `LUT_WIDTH'd4:lut_data <= 16'h19FA; `LUT_WIDTH'd5:lut_data <= 16'h1D40; `LUT_WIDTH'd6:lut_data <= 16'h0F40; `LUT_WIDTH'd7:lut_data <= 16'h3A16; `LUT_WIDTH'd8:lut_data <= 16'h3DC3; `LUT_WIDTH'd9:lut_data <= 16'h3FE4; `LUT_WIDTH'd10:lut_data <= 16'h500A; `LUT_WIDTH'd11:lut_data <= 16'hC309; `LUT_WIDTH'd12:lut_data <= 16'hC480; `LUT_WIDTH'd13:lut_data <= 16'h0E80; `LUT_WIDTH'd14:lut_data <= 16'h5020; `LUT_WIDTH'd15:lut_data <= 16'h5218; `LUT_WIDTH'd16:lut_data <= 16'h58ED; `LUT_WIDTH'd17:lut_data <= 16'h77C5; `LUT_WIDTH'd18:lut_data <= 16'h7C93; `LUT_WIDTH'd19:lut_data <= 16'h7D00; `LUT_WIDTH'd20:lut_data <= 16'h90C9; `LUT_WIDTH'd21:lut_data <= 16'h9140; `LUT_WIDTH'd22:lut_data <= 16'h923C; `LUT_WIDTH'd23:lut_data <= 16'h93CA; `LUT_WIDTH'd24:lut_data <= 16'h94D5; `LUT_WIDTH'd25:lut_data <= 16'hCF50; `LUT_WIDTH'd26:lut_data <= 16'hD04E; `LUT_WIDTH'd27:lut_data <= 16'hD6DD; `LUT_WIDTH'd28:lut_data <= 16'hE551; `LUT_WIDTH'd29:lut_data <= 16'hD5A0; `LUT_WIDTH'd30:lut_data <= 16'hD7EA; `LUT_WIDTH'd31:lut_data <= 16'hE43E; `LUT_WIDTH'd32:lut_data <= 16'hE93E; `LUT_WIDTH'd33:lut_data <= 16'hEA0F; `LUT_WIDTH'd34:lut_data <= 16'h0E00; default:lut_data <= 16'h0080; endcase end endmodule
源码3:读回写入寄存器内容
1 `timescale 1 ns / 1 ps 2 `define LUT_WIDTH 6 3 module rd_check( 4 sys_clk, 5 sys_rst_n, 6 key_n, 7 rreq_o, 8 iic_rd_addr_o 9 ); 10 input sys_clk; 11 input sys_rst_n; 12 input key_n; 13 output rreq_o; 14 output [7:0] iic_rd_addr_o; 15 16 //capture the negedge of key_n; 17 reg key_n_r0 = 1; 18 always @ (posedge sys_clk) begin 19 if(1'b0 == sys_rst_n) key_n_r0 <= 1; 20 else key_n_r0 <= key_n; 21 end 22 wire key_neg = ~key_n & key_n_r0; 23 //generate the rreq_o 24 reg rreq_o = 0; 25 always @ (posedge sys_clk) begin 26 if(1'b0 == sys_rst_n) rreq_o <= 0; 27 else if(key_neg) rreq_o <= 1; 28 else rreq_o <= 0; 29 end 30 31 //generate the iic_rd_addr_o 32 reg [6:0] lut_index = 0; 33 reg [7:0] lut_data = 0; 34 always @ (posedge sys_clk) begin 35 if(1'b0 == sys_rst_n) lut_index <= 0; 36 else if(lut_index == `LUT_WIDTH'd35) lut_index <= 0; 37 else if(key_neg) lut_index <= lut_index + 1'd1; 38 else lut_index <= lut_index; 39 end 40 41 always @ (*) begin 42 case(lut_index) 43 `LUT_WIDTH'd0:lut_data <= 8'hFF; //offset no meaning 44 `LUT_WIDTH'd1:lut_data <= 8'h00; 45 `LUT_WIDTH'd2:lut_data <= 8'h07; 46 `LUT_WIDTH'd3:lut_data <= 8'h15; 47 `LUT_WIDTH'd4:lut_data <= 8'h17; 48 `LUT_WIDTH'd5:lut_data <= 8'h19; 49 `LUT_WIDTH'd6:lut_data <= 8'h1D; 50 `LUT_WIDTH'd7:lut_data <= 8'h0F; 51 `LUT_WIDTH'd8:lut_data <= 8'h3A; 52 `LUT_WIDTH'd9:lut_data <= 8'h3D; 53 `LUT_WIDTH'd10:lut_data <= 8'h3F; 54 `LUT_WIDTH'd11:lut_data <= 8'h50; 55 `LUT_WIDTH'd12:lut_data <= 8'hC3; 56 `LUT_WIDTH'd13:lut_data <= 8'hC4; 57 `LUT_WIDTH'd14:lut_data <= 8'h0E; 58 `LUT_WIDTH'd15:lut_data <= 8'h50; 59 `LUT_WIDTH'd16:lut_data <= 8'h52; 60 `LUT_WIDTH'd17:lut_data <= 8'h58; 61 `LUT_WIDTH'd18:lut_data <= 8'h77; 62 `LUT_WIDTH'd19:lut_data <= 8'h7C; 63 `LUT_WIDTH'd20:lut_data <= 8'h7D; 64 `LUT_WIDTH'd21:lut_data <= 8'h90; 65 `LUT_WIDTH'd22:lut_data <= 8'h91; 66 `LUT_WIDTH'd23:lut_data <= 8'h92; 67 `LUT_WIDTH'd24:lut_data <= 8'h93; 68 `LUT_WIDTH'd25:lut_data <= 8'h94; 69 `LUT_WIDTH'd26:lut_data <= 8'hCF; 70 `LUT_WIDTH'd27:lut_data <= 8'hD0; 71 `LUT_WIDTH'd28:lut_data <= 8'hD6; 72 `LUT_WIDTH'd29:lut_data <= 8'hE5; 73 `LUT_WIDTH'd30:lut_data <= 8'hD5; 74 `LUT_WIDTH'd31:lut_data <= 8'hD7; 75 `LUT_WIDTH'd32:lut_data <= 8'hE4; 76 `LUT_WIDTH'd33:lut_data <= 8'hE9; 77 `LUT_WIDTH'd34:lut_data <= 8'hEA; 78 `LUT_WIDTH'd35:lut_data <= 8'h0E; 79 default:lut_data <= 8'h00; 80 endcase 81 end 82 //assign 83 assign iic_rd_addr_o = lut_data; 84 85 endmodule
源码4:顶层例化文件
1 `timescale 1 ns / 1 ps 2 module iic_driver( 3 sys_clk, 4 sys_rst_n, 5 iic_sclk, 6 iic_sdat, 7 //for test 8 key_n 9 ); 10 input sys_clk; 11 input sys_rst_n; 12 input key_n; 13 output iic_sclk; 14 inout iic_sdat; 15 16 wire wreq; 17 wire rreq; 18 19 wire iic_wr_ack; 20 wire iic_rd_ack; 21 22 wire [7:0] sys_data_o; 23 wire [7:0] sys_data_i; 24 25 wire [7:0] iic_wr_addr; 26 wire [7:0] iic_rd_addr; 27 28 wire wr_config_done; 29 30 wr_config inst_wr_config( 31 .sys_clk(sys_clk), 32 .sys_rst_n(sys_rst_n), 33 .iic_wr_ack_i(iic_wr_ack), 34 .wreq_o(wreq), 35 .sys_byte_o(sys_data_i), 36 .iic_wr_addr_o(iic_wr_addr), 37 .wr_config_done_o(wr_config_done) 38 ); 39 40 rd_check inst_rd_check( 41 .sys_clk(sys_clk), 42 .sys_rst_n(sys_rst_n), 43 .key_n(key_n), 44 .rreq_o(rreq), 45 .iic_rd_addr_o(iic_rd_addr) 46 ); 47 48 iic_ctrl inst_iic_ctrl( 49 //common 50 .sys_clk(sys_clk), 51 .sys_rst_n(sys_rst_n), 52 .iic_sclk(iic_sclk), 53 .iic_sdat(iic_sdat), 54 //read 55 .rreq_i(rreq), 56 .iic_rd_addr_i(iic_rd_addr), 57 .rd_en_i(wr_config_done), 58 .iic_rd_ack_o(iic_rd_ack), 59 .sys_byte_o(sys_data_o), 60 //write 61 .wreq_i(wreq), 62 .wr_en_i(~wr_config_done), 63 .iic_wr_addr_i(iic_wr_addr), 64 .sys_byte_i(sys_data_i), 65 .iic_wr_ack_o(iic_wr_ack) 66 ); 67 68 69 endmodule
源码5:仿真文件
1 `timescale 1 ns / 1 ps 2 `define T1 10000000 3 `define T20 20 4 `define T500 500000 5 module iic_tsb; 6 7 reg sys_clk; 8 reg sys_rst_n; 9 reg key_n; 10 11 initial begin 12 sys_clk=1; 13 sys_rst_n=0; 14 key_n=1; 15 #100 sys_rst_n=1; 16 #`T1 key_n=0; 17 #`T20 key_n=1; 18 #`T500 key_n=0; 19 #`T20 key_n=1; 20 #`T500 key_n=0; 21 #`T20 key_n=1; 22 end 23 24 always begin 25 #10 sys_clk=~sys_clk; 26 end 27 28 wire iic_sclk; 29 wire iic_sdat; 30 31 iic_driver inst_iic_driver( 32 .sys_clk(sys_clk), 33 .sys_rst_n(sys_rst_n), 34 .iic_sclk(iic_sclk), 35 .iic_sdat(iic_sdat), 36 .key_n(key_n) 37 ); 38 39 endmodule
脚本文件1:windows .bat
1 rd work /s /q 2 del *.wlf 3 del modelsim.ini 4 del transcript 5 6 vsim -do iic_tsb.do
脚本文件2:仿真tcl脚本
1 # creat lib 2 vlib work 3 vmap work work 4 5 # compile 6 vlog -work work iic_ctrl.v 7 vlog -work work rd_check.v 8 vlog -work work wr_config.v 9 vlog -work work iic_driver.v 10 vlog -work work iic_tsb.v 11 12 # simulation 13 vsim -novopt -lib work iic_tsb 14 15 # wave 16 view wave 17 add wave sim:/iic_tsb/inst_iic_driver/sys_clk 18 add wave sim:/iic_tsb/inst_iic_driver/sys_rst_n 19 add wave -radix hex sim:/iic_tsb/inst_iic_driver/data2host 20 add wave -radix hex sim:/iic_tsb/inst_iic_driver/data2slave 21 add wave -radix hex sim:/iic_tsb/inst_iic_driver/iic_wr_addr 22 add wave -radix hex sim:/iic_tsb/inst_iic_driver/iic_rd_addr 23 add wave sim:/iic_tsb/inst_iic_driver/wreq 24 add wave sim:/iic_tsb/inst_iic_driver/rreq 25 add wave sim:/iic_tsb/inst_iic_driver/iic_wr_ack 26 add wave sim:/iic_tsb/inst_iic_driver/iic_rd_ack 27 add wave sim:/iic_tsb/inst_iic_driver/inst_iic_ctrl/iic_sclk 28 add wave sim:/iic_tsb/inst_iic_driver/inst_iic_ctrl/iic_sclk_w 29 add wave sim:/iic_tsb/inst_iic_driver/inst_iic_ctrl/iic_sdat 30 add wave sim:/iic_tsb/inst_iic_driver/inst_iic_ctrl/sdat_r 31 add wave sim:/iic_tsb/inst_iic_driver/inst_iic_ctrl/link 32 add wave -radix unsigned sim:/iic_tsb/inst_iic_driver/inst_iic_ctrl/bit_cnt 33 add wave sim:/iic_tsb/inst_iic_driver/inst_iic_ctrl/iic_byte 34 add wave -radix ascii sim:/iic_tsb/inst_iic_driver/inst_iic_ctrl/c_st 35 #write config cost 10ms 36 run 12ms