菜鸟求助!modelsim仿真I2C过程出问题
时间:10-02
整理:3721RD
点击:
毕业设计要做一个I2C的时序仿真,用verilog语言编写的。因为我自己没这个基础做不来,求大神帮忙。这个是SCCB底层驱动程序:module I2C_Controller (
CLOCK,
I2C_SCLK,//I2C CLOCK
I2C_SDAT,//I2C DATA
I2C_DATA,//DATA:[SLAVE_ADDR,SUB_ADDR,DATA]
GO, //GO transfor
END, //END transfor
W_R, //W_R
ACK, //ACK
RESET,
//TEST
SD_COUNTER,
count,
SDO
);
output [7:0] count;
input CLOCK;
input [23:0]I2C_DATA;
input GO;
input RESET;
input W_R;
inout I2C_SDAT;
output I2C_SCLK;
output END;
output ACK;
//TEST
output [5:0] SD_COUNTER;
output SDO;
reg [7:0] count;
parameter tpd_RESET_to_count = 3;
parameter tpd_CLOCK_to_count = 2;
function [7:0] increment;
input [7:0] val;
reg [3:0] i;
reg carry;
begin
increment = val;
carry = 1'b1;
/*
Exit this loop when carry == zero, OR all bits processed
*/
for (i = 4'b0; ((carry == 4'b1) && (i <= 7)); i = i+ 4'b1)
begin
increment = val ^ carry;
carry = val & carry;
end
end
endfunction
/*
always @ (posedge CLOCK or posedge RESET)
if (RESET)
count = #tpd_RESET_to_count 8'h00;
else
count <= #tpd_CLOCK_to_count increment(count);
*/
always @ (posedge CLOCK or posedge RESET)
if (RESET)
count = 8'h00;
else
count <= count + 8'h01;
reg SDO;
reg SCLK;
reg END;
reg [23:0]SD;
reg [5:0]SD_COUNTER;
wire I2C_SCLK=SCLK | ( ((SD_COUNTER >= 4) & (SD_COUNTER <=30))? ~CLOCK :0 );
wire I2C_SDAT=SDO?1'bz:0 ;
reg ACK1,ACK2,ACK3;
wire ACK=ACK1 | ACK2 |ACK3;
//--I2C COUNTER
always @(negedge RESET or posedge CLOCK ) begin
if (!RESET) SD_COUNTER=6'b111111;
else begin
if (GO==0)
SD_COUNTER=0;
else
if (SD_COUNTER < 6'b111111) SD_COUNTER=SD_COUNTER+1;
end
end
//----
always @(negedge RESET or posedge CLOCK ) begin
if (!RESET) begin SCLK=1;SDO=1; ACK1=0;ACK2=0;ACK3=0; END=1; end
else
case (SD_COUNTER)
6'd0 : begin ACK1=0 ;ACK2=0 ;ACK3=0 ; END=0; SDO=1; SCLK=1;end
//start
6'd1 : begin SD=I2C_DATA;SDO=0;end
6'd2 : SCLK=0;
//SLAVE ADDR
6'd3 : SDO=SD[23];
6'd4 : SDO=SD[22];
6'd5 : SDO=SD[21];
6'd6 : SDO=SD[20];
6'd7 : SDO=SD[19];
6'd8 : SDO=SD[18];
6'd9 : SDO=SD[17];
6'd10 : SDO=SD[16];
6'd11 : SDO=1'b1;//ACK
//SUB ADDR
6'd12 : begin SDO=SD[15]; ACK1=I2C_SDAT; end
6'd13 : SDO=SD[14];
6'd14 : SDO=SD[13];
6'd15 : SDO=SD[12];
6'd16 : SDO=SD[11];
6'd17 : SDO=SD[10];
6'd18 : SDO=SD[9];
6'd19 : SDO=SD[8];
6'd20 : SDO=1'b1;//ACK
//DATA
6'd21 : begin SDO=SD[7]; ACK2=I2C_SDAT; end
6'd22 : SDO=SD[6];
6'd23 : SDO=SD[5];
6'd24 : SDO=SD[4];
6'd25 : SDO=SD[3];
6'd26 : SDO=SD[2];
6'd27 : SDO=SD[1];
6'd28 : SDO=SD[0];
6'd29 : SDO=1'b1;//ACK
//stop
6'd30 : begin SDO=1'b0;
SCLK=1'b0; ACK3=I2C_SDAT; end
6'd31 : SCLK=1'b1;
6'd32 : begin SDO=1'b1; END=1; end
endcase
end
endmodule
这个是已经编写的部分激励程序
`timescale 1 ps/ 1 ps
module I2C_Controller_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg CLOCK;
reg GO;
reg [23:0] I2C_DATA;
reg treg_I2C_SDAT;
reg RESET;
reg W_R;
// wires
wire ACK;
wire END;
wire I2C_SCLK;
wire I2C_SDAT;
wire SDO;
wire [5:0] SD_COUNTER;
wire [7:0] count;
// assign statements (if any)
assign I2C_SDAT = treg_I2C_SDAT;
I2C_Controller i1 (
// port map - connection between master ports and signals/registers
.ACK(ACK),
.CLOCK(CLOCK),
.\END (END),
.GO(GO),
.I2C_DATA(I2C_DATA),
.I2C_SCLK(I2C_SCLK),
.I2C_SDAT(I2C_SDAT),
.RESET(RESET),
.SDO(SDO),
.SD_COUNTER(SD_COUNTER),
.W_R(W_R),
.count(count)
);
initial
begin
CLOCK = 0;
forever #50 CLOCK = ~CLOCK;
end
initial
begin
RESET=0;
#50 RESET=1;
#40 RESET = 0;
#40 RESET = 1;
GO=1;
#500 GO=0;
#400 GO = 1;
end
initial
$monitor($stime,, RESET,, CLOCK,,, count,, SD_COUNTER);
endmodule 求助:要在源程序或者激励文件中怎样修改,才能使所有端口的波形都能正确仿真,尤其是I2C_DATA 跟I2C_SDAT。
CLOCK,
I2C_SCLK,//I2C CLOCK
I2C_SDAT,//I2C DATA
I2C_DATA,//DATA:[SLAVE_ADDR,SUB_ADDR,DATA]
GO, //GO transfor
END, //END transfor
W_R, //W_R
ACK, //ACK
RESET,
//TEST
SD_COUNTER,
count,
SDO
);
output [7:0] count;
input CLOCK;
input [23:0]I2C_DATA;
input GO;
input RESET;
input W_R;
inout I2C_SDAT;
output I2C_SCLK;
output END;
output ACK;
//TEST
output [5:0] SD_COUNTER;
output SDO;
reg [7:0] count;
parameter tpd_RESET_to_count = 3;
parameter tpd_CLOCK_to_count = 2;
function [7:0] increment;
input [7:0] val;
reg [3:0] i;
reg carry;
begin
increment = val;
carry = 1'b1;
/*
Exit this loop when carry == zero, OR all bits processed
*/
for (i = 4'b0; ((carry == 4'b1) && (i <= 7)); i = i+ 4'b1)
begin
increment = val ^ carry;
carry = val & carry;
end
end
endfunction
/*
always @ (posedge CLOCK or posedge RESET)
if (RESET)
count = #tpd_RESET_to_count 8'h00;
else
count <= #tpd_CLOCK_to_count increment(count);
*/
always @ (posedge CLOCK or posedge RESET)
if (RESET)
count = 8'h00;
else
count <= count + 8'h01;
reg SDO;
reg SCLK;
reg END;
reg [23:0]SD;
reg [5:0]SD_COUNTER;
wire I2C_SCLK=SCLK | ( ((SD_COUNTER >= 4) & (SD_COUNTER <=30))? ~CLOCK :0 );
wire I2C_SDAT=SDO?1'bz:0 ;
reg ACK1,ACK2,ACK3;
wire ACK=ACK1 | ACK2 |ACK3;
//--I2C COUNTER
always @(negedge RESET or posedge CLOCK ) begin
if (!RESET) SD_COUNTER=6'b111111;
else begin
if (GO==0)
SD_COUNTER=0;
else
if (SD_COUNTER < 6'b111111) SD_COUNTER=SD_COUNTER+1;
end
end
//----
always @(negedge RESET or posedge CLOCK ) begin
if (!RESET) begin SCLK=1;SDO=1; ACK1=0;ACK2=0;ACK3=0; END=1; end
else
case (SD_COUNTER)
6'd0 : begin ACK1=0 ;ACK2=0 ;ACK3=0 ; END=0; SDO=1; SCLK=1;end
//start
6'd1 : begin SD=I2C_DATA;SDO=0;end
6'd2 : SCLK=0;
//SLAVE ADDR
6'd3 : SDO=SD[23];
6'd4 : SDO=SD[22];
6'd5 : SDO=SD[21];
6'd6 : SDO=SD[20];
6'd7 : SDO=SD[19];
6'd8 : SDO=SD[18];
6'd9 : SDO=SD[17];
6'd10 : SDO=SD[16];
6'd11 : SDO=1'b1;//ACK
//SUB ADDR
6'd12 : begin SDO=SD[15]; ACK1=I2C_SDAT; end
6'd13 : SDO=SD[14];
6'd14 : SDO=SD[13];
6'd15 : SDO=SD[12];
6'd16 : SDO=SD[11];
6'd17 : SDO=SD[10];
6'd18 : SDO=SD[9];
6'd19 : SDO=SD[8];
6'd20 : SDO=1'b1;//ACK
//DATA
6'd21 : begin SDO=SD[7]; ACK2=I2C_SDAT; end
6'd22 : SDO=SD[6];
6'd23 : SDO=SD[5];
6'd24 : SDO=SD[4];
6'd25 : SDO=SD[3];
6'd26 : SDO=SD[2];
6'd27 : SDO=SD[1];
6'd28 : SDO=SD[0];
6'd29 : SDO=1'b1;//ACK
//stop
6'd30 : begin SDO=1'b0;
SCLK=1'b0; ACK3=I2C_SDAT; end
6'd31 : SCLK=1'b1;
6'd32 : begin SDO=1'b1; END=1; end
endcase
end
endmodule
这个是已经编写的部分激励程序
`timescale 1 ps/ 1 ps
module I2C_Controller_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg CLOCK;
reg GO;
reg [23:0] I2C_DATA;
reg treg_I2C_SDAT;
reg RESET;
reg W_R;
// wires
wire ACK;
wire END;
wire I2C_SCLK;
wire I2C_SDAT;
wire SDO;
wire [5:0] SD_COUNTER;
wire [7:0] count;
// assign statements (if any)
assign I2C_SDAT = treg_I2C_SDAT;
I2C_Controller i1 (
// port map - connection between master ports and signals/registers
.ACK(ACK),
.CLOCK(CLOCK),
.\END (END),
.GO(GO),
.I2C_DATA(I2C_DATA),
.I2C_SCLK(I2C_SCLK),
.I2C_SDAT(I2C_SDAT),
.RESET(RESET),
.SDO(SDO),
.SD_COUNTER(SD_COUNTER),
.W_R(W_R),
.count(count)
);
initial
begin
CLOCK = 0;
forever #50 CLOCK = ~CLOCK;
end
initial
begin
RESET=0;
#50 RESET=1;
#40 RESET = 0;
#40 RESET = 1;
GO=1;
#500 GO=0;
#400 GO = 1;
end
initial
$monitor($stime,, RESET,, CLOCK,,, count,, SD_COUNTER);
endmodule 求助:要在源程序或者激励文件中怎样修改,才能使所有端口的波形都能正确仿真,尤其是I2C_DATA 跟I2C_SDAT。
同学,你要说明你又哪些不明白的,不能让大家看你这么长的代码啊,说出来你不明白的地方大家帮你解答。可以贴部分代码然后提出问题,大家给你解答。
不好意思,没注意到这个。非常抱歉。就是这个例子里面的I2C_DATA要怎样写 才能在仿真的波形里面会有输出,我自己做的时候,一直都是一条红线。还有inout型的 I2C_SDAT 要怎样在激励文件里面写可以使仿真的波形里面使这个信号有输出。(我是新手,表述不太准确,不好意思)
inout型在testbench里作为wire声明,如wire data;在定义一个输出数据如reg data_out,在定义一个输出使能信号,如reg data_oe;然后需要输出data到线上时data_oe拉高,要输出的数据准备好赋值到data_out,用一个语句描述双向动作,assign data = data_oe ? data_out : 1'bz;就行了
虽然还是不知道具体要怎么做,还是谢谢你
我去尝试了一下,做不出来。如果小编有时间的话,能不能帮我看下,我贴出来的那个程序的那个inout要怎么写?非常感谢
在定义几个变量的时候 ,是在源文件里面定义还是要在testbench里面定义?搞不懂,求解
当然在源程序定义
opencores上面有代码,自己看一下就可以了。
data是inout的,可能在仿真环境中需要pullup。
testbench里也要这样写,只不过定义的时候要定义成wire。你的工程文件要定义为inout。
谢谢楼上各位
:):):):):):):):):):):):):):)
