1、功能图
M0发送数据给M1,M1存取数据并赋给串行的sda,传给M0。
2、时序图
由时序图可以看出:说重点就是,这句最重点,理解哈,如果scl=1,那么sda由高变低时刻串行数据流开始;如果scl=1,那么sda由低变高时刻串行数据流结束,如果scl=0,那么我们的sda数据就可以变化了。
3、状态图
这是描述的时序状态图,我们可以看出,状态图就只是状态,这是时序的状态,注意clk的行为。从状态转换的条件来看,转换成功的关键在于看懂时序图,即:什么条件是代表开始,什么条件代表存数据??
4、M1程序
1 //M1程序 2 module ptosda(rst,sclk,ack,scl,sda,data); 3 4 input sclk,rst;//外部时钟和复位 5 input[3:0] data;//外部数据 6 output ack;//请求 7 output scl;//m1的时钟 8 output sda;//M1数据线 9 10 reg scl,link_sda,ack,sdabuf;//总线开光,数据串行寄存变量 11 reg[3:0]databuf;//M1内部数据寄存 12 reg[7:0]state;//状态变量 13 14 //九种状态,怎么想的呢??? 15 parameter ready=8'b0000_0000,//等待 16 start=8'b0000_0001,//开始 17 bit1=8'b0000_0010,//数据1 18 bit2=8'b0000_0100,//数据2 19 bit3=8'b0000_1000,//数据3 20 bit4=8'b0001_0000,//数据4 21 bit5=8'b0010_0000,//数据5 22 stop=8'b0100_0000,//结束 23 idle=8'b1000_0000;//空闲 24 25 always@(posedge sclk or negedge rst)//先把时钟设置好,就是这样设置的 26 begin 27 if(!rst) 28 scl<=1;//m1的scl时钟需要先是高位 29 else 30 scl<=~scl;//这里的数据是sclk的周期的二倍,把sclk的时钟信号传递给了scl,一种方法,5rf你懂的 31 end 32 33 always@(posedge ack)//再把数据接受好 34 databuf<=data;//只要请求到来,就会把数据传给databuf 35 36 //------主状态机:产生控制信号,根据databuf中的保存数据,按照协议产生sda串行信号 37 always@(negedge sclk or negedge rst)//这里是sclk 没有用scl用低电平触发 38 if(!rst) 39 begin 40 link_sda<=0;//断开总线 41 state<=ready;//进入准备状态 42 sdabuf<=1;//m1传输数据总线打开 43 ack<=0;//请求置0 44 end 45 else 46 begin 47 case(state) 48 ready: 49 if(ack)// 50 begin 51 link_sda<=1;//sda的总线打开 52 state<=start;//进入另外的开始阶段 53 end 54 else 55 begin 56 link_sda<=0;//sda 总线关闭 57 state<=ready; 58 ack<=1;//请求数据 59 end 60 start: 61 if(scl&&ack)//scl是高电平传状态,低电平传数据 62 begin 63 sdabuf<=0;//sdabuf寄存0 64 state<=bit1;//进入bit1状态 65 end 66 else 67 state<=start;//等待scl高电平到来 68 bit1: 69 if(!scl) 70 begin 71 sdabuf<=databuf[3];//sdabuf寄存高位数据 72 state<=bit2;//进入bit2状态 73 ack<=0;//关闭请求 74 end 75 else 76 state<=bit1;//等待scl变低电平,似乎是 77 bit2: 78 if(!scl) 79 begin 80 sdabuf<=databuf[2]; 81 state<=bit3; 82 end 83 else 84 state<=bit2; 85 bit3: 86 if(!scl) 87 begin 88 sdabuf<=databuf[1]; 89 state<=bit4; 90 end 91 else 92 state<=bit3; 93 bit4: 94 if(!scl) 95 begin 96 sdabuf<=databuf[0]; 97 state<=bit5; 98 end 99 else 100 state<=bit4; 101 102 bit5: 103 if(!scl) 104 begin 105 sdabuf<=0; 106 state<=stop; 107 end 108 else 109 state<=bit5; 110 stop: 111 if(scl) 112 begin 113 sdabuf<=1; 114 state<=idle; 115 end 116 else 117 state<=stop; 118 idle: 119 begin 120 link_sda<=0; 121 state<=ready; 122 end 123 default: 124 begin 125 link_sda<=0; 126 state<=1; 127 state<=ready; 128 end 129 endcase 130 131 end 132 133 endmodule
5、M2程序
1 //描述M2模块的verilog程序 2 //按照协议接受串行数据,进行处理并按照数据值在相应位输出高电平。 3 module out16hi(scl,sda,outhigh); 4 5 inout scl,sda;//串行数据输入 6 output [15:0] outhigh;//根据输入的串行数据和设置高电平位 7 8 reg[5:0] mstate/*synthesis preserve*/;//本模块的主状态 9 reg[3:0] pdata,pdatabuf; 10 reg[15:0] outhigh;//输出寄存器 11 reg startflag,endflag;//数据开始和结束标志 12 13 always@(negedge sda)//当数据是高电平 14 begin 15 if(scl)//如果时钟也是高 16 begin 17 startflag<=1;//开始标志位置1 18 end 19 else if(endflag)//如果结束标志位是1 20 startflag<=0;//那么开始标志位是0 21 end 22 23 always@(posedge sda)//如果数据线是上升沿 24 if(scl)//如果时钟是高 25 begin 26 endflag<=1; 27 pdatabuf<=pdata; 28 end 29 else 30 endflag<=0; 31 32 parameter ready=6'b00_0000, 33 sbit0=6'b00_0001, 34 sbit1=6'b00_0010, 35 sbit2=6'b00_0100, 36 sbit3=6'b00_1000, 37 sbit4=6'b01_0000; 38 39 always@(pdatabuf) 40 begin 41 case(pdatabuf) 42 4'b0001: 43 outhigh=16'b0000_0000_0000_0001; 44 4'b0010: 45 outhigh=16'b0000_0000_0000_0010; 46 4'b0011: 47 outhigh=16'b0000_0000_0000_0100; 48 4'b0100: 49 outhigh=16'b0000_0000_0000_1000; 50 4'b0101: 51 outhigh=16'b0000_0000_0001_0000; 52 4'b0110: 53 outhigh=16'b0000_0000_0010_0000; 54 4'b0111: 55 outhigh=16'b0000_0000_0100_0000; 56 4'b1000: 57 outhigh=16'b0000_0000_1000_0000; 58 4'b1001: 59 outhigh=16'b0000_0001_0000_0000; 60 4'b1010: 61 outhigh=16'b0000_0010_0000_0000; 62 4'b1011: 63 outhigh=16'b0000_0100_0000_0000; 64 4'b1100: 65 outhigh=16'b0000_1000_0000_0000; 66 4'b1101: 67 outhigh=16'b0001_0000_0000_0000; 68 4'b1110: 69 outhigh=16'b0010_0000_0000_0000; 70 4'b1111: 71 outhigh=16'b0100_0000_0000_0000; 72 4'b0000: 73 outhigh=16'b1000_0000_0000_0000; 74 endcase 75 76 end 77 78 always@(posedge scl) 79 if(startflag) 80 case(mstate) 81 sbit0: 82 begin 83 mstate<=sbit1; 84 pdata[3]<=sda; 85 $display("I am in sdabit0"); 86 end 87 sbit1: 88 begin 89 mstate<=sbit2; 90 pdata[2]<=sda; 91 $display("I am in sdabit1"); 92 end 93 sbit2: 94 begin 95 mstate<=sbit3; 96 pdata[1]<=sda; 97 $display("I am in sdabit2"); 98 end 99 sbit3: 100 begin 101 mstate<=sbit4; 102 pdata[0]<=sda; 103 $display("I am in sdabit3"); 104 end 105 sbit4: 106 begin 107 mstate<=sbit0; 108 $display("I am in sdastop"); 109 end 110 default: 111 mstate<=sbit0; 112 endcase 113 else 114 mstate<=sbit0; 115 endmodule 116 117 118
6、M0程序
1 //M0模块的verilog代码 2 //本模块产生测试信号对设计中的模块进行测试 3 `timescale 1ns/1ns 4 `define halfperiod 50 5 module sigdata(rst,sclk,data,ask_for_data); 6 output rst; 7 output[3:0] data; 8 output sclk; 9 input ask_for_data; 10 reg rst,sclk; 11 reg[3:0] data; 12 13 initial 14 begin 15 rst=1; 16 #10 rst=0; 17 #(`halfperiod*2+3) rst=1; 18 end 19 20 initial 21 begin 22 sclk=0; 23 data=0; 24 #(`halfperiod*1000) 25 $stop; 26 end 27 28 always #(`halfperiod) sclk=~sclk; 29 30 always@(posedge ask_for_data) 31 begin 32 #(`halfperiod/2+3) 33 data=data+1; 34 end 35 36 endmodule
7、top.v程序
1 //描述顶层模块 2 //对所涉及的两个综合模块ptosda和out16hi进行联合测试 3 `timescale 1ns/1ns 4 `include "sigdata.v" 5 `include "ptosda.v" 6 `include "out16hi.v" 7 8 module top; 9 wire[3:0] data; 10 wire sclk; 11 wire scl; 12 wire sda; 13 wire rst; 14 wire[15:0] outhigh; 15 16 sigdata m0 (.rst(rst),.sclk(sclk),.data(data),.ask_for_data(ack)); 17 ptosda m1 (.rst(rst),.sclk(sclk),.ack(ack),.scl(scl),.sda(sda),.data(data)); 18 out16hi m2 (.scl(scl),.sda(sda),.outhigh(outhigh)); 19 20 endmodule