自动例化报错
Closed this issue · 3 comments
i2c_byte_master.v
module i2c_byte_master #(parameter clk_div=100)(
input clk,
input rst,
input wr_req,rd_req,
input [7:0] data,
input i2c_addr_2byte,
inout sda,
output scl
);
reg [4:0] state;
reg i2c_clk;
reg [9:0] clk_cnt;
reg [4:0] clk_cnt_s;
reg [3:0] bit_cnt;
reg scl_o_en,sda_o_en;
reg wr_ack_y;
wire sda_i;
// assign scl=~scl_o_en?1'b0:1'bz;
assign sda=~sda_o_en?1'b0:1'bz;
assign sda_i=sda;
assign scl=scl_o_en;
// assign scl_i=scl;
// assign
parameter scl_low_div=31;//clk_div/4
parameter scl_high_div=93;//clk_div/(3/4)
parameter scl_change_div=15;//scl_low_div/2
parameter w_dev_address=9'b010101100;//LSB 0 W
parameter r_dev_address=9'b010101101;//LSB 1 R
parameter w_reg_address=8'b01010110;
parameter w_reg_address1=8'b01100100;
parameter s_idle=5'd0;
parameter s_wr_start=5'd1;
parameter s_wr_dev_addr=5'd2;
parameter s_wr_reg_addr=5'd3;
parameter s_wr_ack1=5'd4;
parameter s_wr_reg_addr1 = 5'd5;
parameter s_wr_data=5'd6;
parameter s_rd_start=5'd7;
parameter s_rd_dev_addr=5'd8;
parameter s_rd_reg_addr=5'd9;
parameter s_rd_start1=5'd10;
parameter s_rd_reg_addr1=5'd11;
parameter s_rd_dev_addr1=5'd12;
parameter s_rd_ack1=5'd13;
parameter s_rd_data=5'd14;
parameter s_stop=5'd15;
parameter s_wr_ack2=5'd16;
parameter s_wr_ack3=5'd17;
parameter s_wr_ack4=5'd18;
parameter s_rd_ack2=5'd19;
parameter s_rd_ack3=5'd20;
always@(posedge clk)
begin
if(rst)
begin
clk_cnt<=9'd0;
clk_cnt_s<=5'd0;
i2c_clk<=1'b0;
end
else if(clk_cnt==clk_div-1)
begin
clk_cnt<=9'd0;
i2c_clk=~i2c_clk;
end
else
clk_cnt<=clk_cnt+1'b1;
end
// always@(posedge clk)
// begin
// if(rst)
// begin
// clk_cnt_s<=9'd0;
// end
// else if(clk_cnt==clk_div-1)
// begin
// clk_cnt_s<=9'd0;
// end
// else
// clk_cnt_s<=clk_cnt_s+1'b1;
// end
always@(posedge clk)
begin
if(rst)
begin
scl_o_en<=1'b1;
sda_o_en<=1'b1;
state<=s_idle;
bit_cnt<=4'd0;
wr_ack_y<=1'b0;
end
else
begin
case (state)
s_idle:
begin
if(wr_req==1'b1)
begin
state<=s_wr_start;
scl_o_en<=1'b1;
sda_o_en<=1'b1;
end
else if(rd_req==1'b1)
begin
state<=s_rd_start;
scl_o_en<=1'b1;
sda_o_en<=1'b1;
end
else
begin
state<=s_idle;
end
end
s_wr_start://2.5us+5us
begin
if(clk_cnt_s==5'd2&&clk_cnt==clk_div-1)
begin
clk_cnt_s<=5'd0;
state<=s_wr_dev_addr;
sda_o_en<=1'b0;
scl_o_en<=1'b0;
end
else if(clk_cnt==clk_div-1)
begin
clk_cnt_s<=clk_cnt_s+1'b1;
sda_o_en<=1'b0;
scl_o_en<=1'b1;
end
end
s_wr_dev_addr:
begin
if(clk_cnt_s==5'd8&&clk_cnt==clk_div-1)
begin
clk_cnt_s<=5'd0;
state<=s_wr_ack1;
// scl_o_en<=1'b1;
sda_o_en<=1'b1;
end
else if(clk_cnt==clk_div-1)
begin
clk_cnt_s<=clk_cnt_s+1'b1;
end
else if(clk_cnt==scl_change_div)
begin
sda_o_en<=w_dev_address[8-clk_cnt_s];
end
else if(clk_cnt==scl_low_div)
begin
scl_o_en<=1'b1;
end
else if(clk_cnt==scl_high_div)
begin
scl_o_en<=1'b0;
end
// else if(clk_cnt==scl_high_div+scl_change_div)
// begin
// sda_o_en<=dev_address[7-clk_cnt_s];
// end
end
s_wr_ack1:
begin
if(clk_cnt==clk_div-1&&clk_cnt_s==5'd1&&wr_ack_y==1'b1)
begin
state<=s_wr_reg_addr;
wr_ack_y<=1'b0;
clk_cnt_s<=5'd0;
sda_o_en<=1'b1;
end
else if(clk_cnt==clk_div-1&&clk_cnt_s==5'd1)
begin
state<=s_stop;
end
else if(clk_cnt==clk_div-1)
begin
clk_cnt_s<=clk_cnt_s+1'b1;
end
else if(clk_cnt==scl_low_div)
begin
scl_o_en<=1'b1;
end
else if(clk_cnt==scl_high_div)
begin
scl_o_en<=1'b0;
end
else if(sda_i==1'b0)
begin
wr_ack_y<=1'b1;
end
end
s_wr_reg_addr:
begin
// if(clk_cnt==clk_div-1)
// begin
// state<=i2c_addr_2byte?s_wr_reg_addr1:s_wr_ack2;
// end
if(clk_cnt==clk_div-1&&clk_cnt_s==5'd7)
begin
state<=s_wr_ack2;
clk_cnt_s<=5'd0;
sda_o_en<=1'b1;
end
else if(clk_cnt==clk_div-1)
begin
clk_cnt_s<=clk_cnt_s+1'b1;
end
else if(clk_cnt==scl_change_div)
begin
sda_o_en<=w_reg_address[7-clk_cnt_s];
end
else if(clk_cnt==scl_low_div)
begin
scl_o_en<=1'b1;
end
else if(clk_cnt==scl_high_div)
begin
scl_o_en<=1'b0;
end
end
s_wr_reg_addr1:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_wr_ack2;
end
end
s_wr_ack2:
begin
if(clk_cnt==clk_div-1&&clk_cnt_s==5'd1&&wr_ack_y==1'b1)
begin
state<=i2c_addr_2byte?s_wr_reg_addr1:s_wr_data;
wr_ack_y<=1'b0;
clk_cnt_s<=5'd0;
sda_o_en<=1'b1;
end
else if(clk_cnt==clk_div-1&&clk_cnt_s==5'd1)
begin
state<=s_stop;
end
else if(clk_cnt==clk_div-1)
begin
clk_cnt_s<=clk_cnt_s+1'b1;
end
else if(clk_cnt==scl_low_div)
begin
scl_o_en<=1'b1;
end
else if(clk_cnt==scl_high_div)
begin
scl_o_en<=1'b0;
end
else if(sda_i==1'b0)
begin
wr_ack_y<=1'b1;
end
end
s_wr_data:
begin
if(clk_cnt==clk_div-1)
begin
if(bit_cnt==4'd7)
begin
state<=s_wr_ack3;
bit_cnt<=4'd0;
end
else
begin
bit_cnt<=bit_cnt+1'b1;
end
end
end
s_wr_ack3:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_stop;
end
end
s_rd_start:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_rd_dev_addr;
end
end
s_rd_ack1:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_rd_reg_addr;
end
end
s_rd_reg_addr:
begin
if(clk_cnt==clk_div-1)
begin
state<=i2c_addr_2byte?s_rd_reg_addr1:s_rd_start1;
end
end
s_rd_reg_addr1:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_rd_start1;
end
end
s_rd_start1:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_rd_dev_addr1;
end
end
s_rd_dev_addr1:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_rd_ack2;
end
end
s_rd_ack2:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_rd_data;
end
end
s_rd_data:
begin
if(clk_cnt==clk_div-1)
begin
if(bit_cnt==4'd7)
begin
state<=s_stop;
bit_cnt<=4'd0;
end
else
begin
bit_cnt<=bit_cnt+1'b1;
end
end
end
s_stop:
begin
if(clk_cnt==clk_div-1)
begin
state<=s_idle;
end
end
endcase
end
end
endmodule
timescale 1ns/100ps
include "../src/i2c_byte_master.v"
module i2c_byte_master_tb(
);
reg clk;
reg rst;
reg [7:0] data;
wire scl,sda;
wire sda1;
reg sda_reg;
always #20 clk=~clk;
assign sda=sda_reg;
initial
begin
$dumpfile("wave.vcd"); //生成的vcd文件名称
$dumpvars(0, i2c_byte_master_tb); //tb模块名称
end
initial
begin
clk=1'b1;
rst<=1'b0;
#100;
rst<=1'b1;
#40;
rst<=1'b0;
end
initial
begin
sda_reg<=1'bz;
#60000;
sda_reg<=1'b0;
#9800;
sda_reg<=1'bz;
#40100;
sda_reg<=1'b0;
#9500;
sda_reg<=1'bz;
end
i2c_byte_master#(125) i2c(
.clk(clk),
.rst(rst),
.wr_req(1'b1),
.rd_req(1'b0),
.data(data),
.i2c_addr_2byte(1'b1),
.scl(scl),
.sda(sda)
);
i2c_byte_master u_i2c_byte_master#(
.clk_div ( 99 )
)
(
.clk ( clk ),
.rst ( rst ),
.wr_req ( 1'b1 ),
.rd_req ( 1'b0 ),
.data ( data ),
.i2c_addr_2byte ( 1'b1 ),
.scl ( scl ),
.sda ( sda )
);
endmodule