模块M0
`timescale 1ns/100ps
`define clk_cyc 50
module sigdata(rst,data,sclk,ack);
input ack;
output rst;
output [3:0] data;
output sclk;
reg rst;
reg sclk;
reg [3:0] data;
initial
begin
rst <= 1;
#10rst=0;
#(`clk_cyc*2+3)rst=1;
end
initial
begin
sclk = 0;
data = 0;
#(`clk_cyc * 1000) $stop;
end
always #(`clk_cyc) sclk = ~sclk;
always @(posedge ack)
begin
#(`clk_cyc/2+3) data = data+1;
end
endmodule
模块M1
module ptosda(rst,sclk,data,ack,scl,sda);
input rst,sclk;
input [3:0] data; //并行口数据输入
output ack; //请求新的转换数据
output scl;
output sda; //定义SDA为单向的串行输出
reg ack;
reg scl;
reg link_sda;
reg sdabuf;
reg [3:0] databuf;
reg [7:0] state;
assign sda = link_sda?sdabuf:1'b0; //link_sda控制sdabuf输出到串行总线上
parameter ready = 8'b0000_0000,
start = 8'b0000_0001,
bit3 = 8'b0000_0010,
bit2 = 8'b0000_0100,
bit1 = 8'b0000_1000,
bit0 = 8'b0001_0000,
prestop = 8'b0010_0000,
stop = 8'b0100_0000,
idle = 8'b1000_0000;
always@(posedge sclk or negedge rst) //由输入的sclk产生串行输出时钟scl
begin
if(!rst)
scl <= 1;
else
scl <= ~scl;
end
always @(posedge ack) //请求新数据时存入并行总线上要转换的数据
databuf <= data;
/*主状态机:产生控制信号,根据databuf中保存的数据,按照协议产生sda串行信号*/
always @(negedge sclk or negedge rst)
if(!rst)
begin
link_sda <= 0; //把sdabuf与sda串行总线断开
state <= ready;
sdabuf <= 1;
ack <= 0;
end
else
begin
case(state)
ready:
if(ack)
begin
link_sda <= 1;
state <= start;
end
else
begin
link_sda <= 0;
state <= ready;
ack <= 1; //请求新数据信号置为1
end
start:
if(ack&&scl)
begin
sdabuf <= 0;
state <= bit3;
end
else
begin
state <= start;
end
bit3:
if(!scl)
begin
sdabuf <= data[3];
state <= bit2;
ack <= 0;
end
else
state <= bit3;
bit2:
if(!scl)
begin
sdabuf <= data[2];
state <= bit1;
end
else
state <= bit2;
bit1:
if(!scl)
begin
sdabuf <= data[1];
state <= bit0;
end
else
state <= bit1;
bit0:
if(!scl)
begin
sdabuf <= data[0];
state <= prestop;
end
else
state <= bit0;
prestop:
if(!scl)
begin
sdabuf <= 0;
state <= stop;
end
else
state <= prestop;
stop:
if(scl)
begin
sdabuf <= 1;
state <= idle;
end
else
state <=stop;
idle:
begin
link_sda<= 0;
state <= ready;
end
default:
begin
link_sda<= 0;
sdabuf <= 1;
state <= ready;
end
endcase
end
sigdata u0(.rst(rst),.data(data),.sclk(sclk),.ack(ack));
endmodule
模块M2
module out16hign(scl,sda,outhigh);
input scl;
input sda;
output [15:0] outhigh;
reg [5:0] mstate; //本模块的主状态
reg [3:0] pdata,pdatabuf; //用寄存器和最终数据寄存器记录串行数据位。
reg [15:0] outhigh; //输出位寄存器
reg Startflag,Endflag; //数据开始和结束标记
always@(negedge sda)
begin
if(scl)
Startflag <= 1;
else if(Endflag)
Startflag <= 0;
end
always@(posedge sda)
if (scl)
begin
Endflag <= 1;
pdatabuf<= pdata; //把收到的4位数据存入寄存器
end
else
Endflag <= 0;
parameter
ready = 6'b00_0000,
sbit0 = 6'b00_0001,
sbit1 = 6'b00_0010,
sbit2 = 6'b00_0100,
sbit3 = 6'b00_1000,
sbit4 = 6'b01_0000;
always@(pdatabuf)
begin
case(pdatabuf)
4'b0001: outhigh = 16'b0000_0000_0000_0001;
4'b0010: outhigh = 16'b0000_0000_0000_0010;
4'b0011: outhigh = 16'b0000_0000_0000_0100;
4'b0100: outhigh = 16'b0000_0000_0000_1000;
4'b0101: outhigh = 16'b0000_0000_0001_0000;
4'b0110: outhigh = 16'b0000_0000_0010_0000;
4'b0111: outhigh = 16'b0000_0000_0100_0000;
4'b1000: outhigh = 16'b0000_0000_1000_0000;
4'b1001: outhigh = 16'b0000_0001_0000_0000;
4'b1010: outhigh = 16'b0000_0010_0000_0000;
4'b1011: outhigh = 16'b0000_0100_0000_0000;
4'b1100: outhigh = 16'b0000_1000_0000_0000;
4'b1101: outhigh = 16'b0001_0000_0000_0000;
4'b1110: outhigh = 16'b0010_0000_0000_0000;
4'b1111: outhigh = 16'b0100_0000_0000_0000;
4'b0000: outhigh = 16'b1000_0000_0000_0000;
endcase
end
always@(posedge scl)
if(Startflag)
case(mstate)
sbit0:
begin
mstate <=sbit1;
pdata[3]<=sda;
$display("i am in sdabit0");
end
sbit1:
begin
mstate <= sbit2;
pdata[2]<= sda;
$display("i am in sdabit1");
end
sbit2:
begin
mstate <= sbit3;
pdata[1]<= sda;
$display("i am in sdabit2");
end
sbit3:
begin
mstate <= sbit4;
pdata[0]<= sda;
$display("i am in sdabit3");
end
sbit4:
begin
mstate <= sbit0;
$display("i am in sdastop");
end
default:
mstate <= sbit0;
endcase
else
mstate <= sbit0;
ptosda u1(.rst(rst),.sclk(sclk),.data(data),.ack(ack),.scl(scl),.sda(sda));
endmodule