赞
踩
配置文件:根据具体的IIC设备改一下时钟频率就可以产生正确的时钟波形
`define SYS_CLK 50_000_000
`define SCL_CLK 400_000
`define COUNT_MAX (`SYS_CLK/`SCL_CLK)
`define HALF (`COUNT_MAX/2 -1)
`define H_HALF (`HALF/2)
`define NEG (`HALF +1)
`define L_HALF (`H_HALF+NEG)
RTL代码:
`include "config.v" module I2C( clk, //system clk 50MHZ rstn, //active low data_in, data_out, sda, scl, wr, //wr=0 write; wr=1 read fail, req, address, wr_done, rd_done ); input clk; input rstn; input [7:0]data_in; input wr; input req; input [7:0] address; output [0:0]scl; output reg[7:0] data_out; inout sda; output fail; output rd_done; output wr_done; reg [7:0] clk_cnt; wire sda_in; reg sda_out; reg [29:0] state; reg [0:0] sda_mode; wire clk_en; parameter IN =0, OUT =1; parameter idle =30'b00_0000_0000_0000_0000_0000_0000_0001, start =30'b00_0000_0000_0000_0000_0000_0000_0010, mode0 =30'b00_0000_0000_0000_0000_0000_0000_0100, mode1 =30'b00_0000_0000_0000_0000_0000_0000_1000, mode2 =30'b00_0000_0000_0000_0000_0000_0001_0000, mode3 =30'b00_0000_0000_0000_0000_0000_0010_0000, mode4 =30'b00_0000_0000_0000_0000_0000_0100_0000, mode5 =30'b00_0000_0000_0000_0000_0000_1000_0000, mode6 =30'b00_0000_0000_0000_0000_0001_0000_0000, mode7 =30'b00_0000_0000_0000_0000_0010_0000_0000, ack_mode =30'b00_0000_0000_0000_0000_0100_0000_0000, addr0 =30'b00_0000_0000_0000_0000_1000_0000_0000, addr1 =30'b00_0000_0000_0000_0001_0000_0000_0000, addr2 =30'b00_0000_0000_0000_0010_0000_0000_0000, addr3 =30'b00_0000_0000_0000_0100_0000_0000_0000, addr4 =30'b00_0000_0000_0000_1000_0000_0000_0000, addr5 =30'b00_0000_0000_0001_0000_0000_0000_0000, addr6 =30'b00_0000_0000_0010_0000_0000_0000_0000, addr7 =30'b00_0000_0000_0100_0000_0000_0000_0000, ack_addr =30'b00_0000_0000_1000_0000_0000_0000_0000, bit0 =30'b00_0000_0001_0000_0000_0000_0000_0000, bit1 =30'b00_0000_0010_0000_0000_0000_0000_0000, bit2 =30'b00_0000_0100_0000_0000_0000_0000_0000, bit3 =30'b00_0000_1000_0000_0000_0000_0000_0000, bit4 =30'b00_0001_0000_0000_0000_0000_0000_0000, bit5 =30'b00_0010_0000_0000_0000_0000_0000_0000, bit6 =30'b00_0100_0000_0000_0000_0000_0000_0000, bit7 =30'b00_1000_0000_0000_0000_0000_0000_0000, ack_bit =30'b01_0000_0000_0000_0000_0000_0000_0000, stop =30'b10_0000_0000_0000_0000_0000_0000_0000; //generate clk 400khz always@(posedge clk) if(!rstn) clk_cnt <=8'd0; else if(clk_en) begin if(clk_cnt==`COUNT_MAX) clk_cnt <=8'd0; else clk_cnt <=clk_cnt + 1'b1; end else clk_cnt <=8'd0; //wire neg=(clk_cnt==`NEG)?1:0; //negedge of the scl_clk wire h_half =(clk_cnt==h_half); wire l_half =(clk_cnt==l_half); wire scl_clk =(clk_cnt <`HALF); assign scl =(clk_en&scl_clk)|(!clk_en); //control sda direction assign sda=(sda_mode==OUT)?sda_out:1'bz; assign sda_in=(sda_mode==IN)?sda:1'bz; wire full=(clk_cnt==`COUNT_MAX); //state control always@(posedge clk) if(!rstn) state <=idle; else case(state) idle: if(req) state <=start; else state <=state; start: //at the same time start clock generator if(full) state <=mode0; else state <=state; mode0: if(full) state <=mode1; else state <=state; mode1: if(full) state <=mode2; else state <=state; mode2: if(full) state <=mode3; else state <=state; mode3: if(full) state <=mode4; else state <=state; mode4: if(full) state <=mode5; else state <=state; mode5: if(full) state <=mode6; else state <=state; mode6: if(full) state <=mode7; else state <=state; mode7: if(full) state <=ack_mode; else state <=state; ack_mode: if(h_half) begin if(sda_in==1'b1) state <=addr0; else state <=stop; end else state <=state; addr0: if(full) state <=addr1; else state <=state; addr1: if(full) state <=addr2; else state <=state; addr2: if(full) state <=addr3; else state <=state; addr3: if(full) state <=addr4; else state <=state; addr4: if(full) state <=addr5; else state <=state; addr5: if(full) state <=addr6; else state <=state; addr6: if(full) state <=addr7; else state <=state; addr7: if(full) state <=ack_addr; else state <=state; ack_addr: if(h_half) begin if(sda_in==1'b0) state <=bit0; else state <=stop; end else state <=state; bit0: if(full) state <=bit1; else state <=bit2; bit1: if(full) state <=bit2; else state <=state; bit2: if(full) state <=bit3; else state <=state; bit3: if(full) state <=bit4; else state <=state; bit4: if(full) state <=bit5; else state <=state; bit5: if(full) state <=bit6; else state <=state; bit6: if(full) state <=bit7; else state <=state; bit7: if(full) state <=ack_bit; else state <=state; ack_bit: if((!wr)&h_half) begin if(sda_in==1'b0) state <=stop; else state <=stop; end else if(wr&l_half) state <=stop; else state <=state; stop: if(full) state <=idle; else state <=state; default: state <=stop; endcase always@(posedge clk) if(!rstn) begin sda_mode <=OUT; sda_out <=1'b1; data_out <=8'b0; end else case(state) idle: begin sda_mode <=OUT; sda_out <=1'b1; end start: begin sda_mode <=OUT; if(l_half) sda_out <=1'b0; else sda_out <=1'b1; end mode0: begin sda_mode <=OUT; if(l_half) sda_out <=1'b1; else sda_out <=sda_out; end mode1: begin sda_mode <=OUT; if(l_half) sda_out <=1'b0; else sda_out <=sda_out; end mode2: begin sda_mode <=OUT; if(l_half) sda_out <=1'b1; else sda_out <=sda_out; end mode3: begin sda_mode <=OUT; if(l_half) sda_out <=1'b0; else sda_out <=sda_out; end mode4: begin sda_mode <=OUT; if(l_half) sda_out <=1'b1; else sda_out <=sda_out; end mode5: begin sda_mode <=OUT; if(l_half) sda_out <=1'b0; else sda_out <=sda_out; end mode6: begin sda_mode <=OUT; if(l_half) sda_out <=1'b0; else sda_out <=sda_out; end mode7: begin sda_mode <=OUT; if(l_half) sda_out <=wr; else sda_out <=sda_out; end ack_mode: begin sda_mode <=IN; end addr0: begin sda_mode <=OUT; if(l_half) sda_out <=address[7]; else sda_out <=sda_out; end addr1: begin sda_mode <=OUT; if(l_half) sda_out <=address[6]; else sda_out <=sda_out; end addr2: begin sda_mode <=OUT; if(l_half) sda_out <=address[5]; else sda_out <=sda_out; end addr3: begin sda_mode <=OUT; if(l_half) sda_out <=address[4]; else sda_out <=sda_out; end addr4: begin sda_mode <=OUT; if(l_half) sda_out <=address[3]; else sda_out <=sda_out; end addr5: begin sda_mode <=OUT; if(l_half) sda_out <=address[2]; else sda_out <=sda_out; end addr6: begin sda_mode <=OUT; if(l_half) sda_out <=address[1]; else sda_out <=sda_out; end addr7: begin sda_mode <=OUT; if(l_half) sda_out <=address[0]; else sda_out <=sda_out; end ack_addr: begin sda_mode <=IN; end bit0: if(wr)//read begin sda_mode <=IN; if(h_half) data_out[7] <=sda_in; else data_out[7] <=data_out[7]; end else//write begin sda_mode <=OUT; if(l_half) sda_out <=data_in[7]; else sda_out <=sda_out; end bit1: if(wr)//read begin sda_mode <=IN; if(h_half) data_out[6] <=sda_in; else data_out[6] <=data_out[6]; end else//write begin sda_mode <=OUT; if(l_half) sda_out <=data_in[6]; else sda_out <=sda_out; end bit2: if(wr)//read begin sda_mode <=IN; if(h_half) data_out[5] <=sda_in; else data_out[5] <=data_out[5]; end else//write begin sda_mode <=OUT; if(l_half) sda_out <=data_in[5]; else sda_out <=sda_out; end bit3: if(wr)//read begin sda_mode <=IN; if(h_half) data_out[4] <=sda_in; else data_out[4] <=data_out[4]; end else//write begin sda_mode <=OUT; if(l_half) sda_out <=data_in[4]; else sda_out <=sda_out; end bit4: if(wr)//read begin sda_mode <=IN; if(h_half) data_out[3] <=sda_in; else data_out[3] <=data_out[3]; end else//write begin sda_mode <=OUT; if(l_half) sda_out <=data_in[3]; else sda_out <=sda_out; end bit5: if(wr)//read begin sda_mode <=IN; if(h_half) data_out[2] <=sda_in; else data_out[2] <=data_out[2]; end else//write begin sda_mode <=OUT; if(l_half) sda_out <=data_in[2]; else sda_out <=sda_out; end bit6: if(wr)//read begin sda_mode <=IN; if(h_half) data_out[1] <=sda_in; else data_out[1] <=data_out[1]; end else//write begin sda_mode <=OUT; if(l_half) sda_out <=data_in[1]; else sda_out <=sda_out; end bit7: if(wr)//read begin sda_mode <=IN; if(h_half) data_out[0] <=sda_in; else data_out[0] <=data_out[0]; end else//write begin sda_mode <=OUT; if(l_half) sda_out <=data_in[0]; else sda_out <=sda_out; end ack_bit: if(!wr) sda_mode <=IN; else begin sda_mode <=OUT; if(l_half) sda_out <=1'b1; else sda_out <=sda_out; end stop: if(h_half)//閹峰鐝 begin sda_mode <=OUT; sda_out <=1; end else if(!h_half)//閹峰缍 begin sda_mode <=OUT; sda_out <=0; end default:begin sda_out <=1'b1; sda_mode <=OUT; data_out <=8'd0; end endcase assign clk_en =(state==idle); assign wr_done =(state==ack_bit)&(h_half)&(sda_in==1'b0); assign fail =((state==ack_mode)&(h_half)&(sda_in!=1'b0))| ((state==ack_addr)&(h_half)&(sda_in!=1'b0))| ((state==ack_bit)&(h_half)&(sda_in!=1'b0)); assign rd_done =(state==stop); endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。