verilog iic 求助,程序中的scl示波器上看是没有反应的...
`timescale 1ns / 1psmodule iic_top(clk,rst_n,sw1,sw2,scl,sda,led_d2,led_d3,led_d4,led_d5);
input clk; // 4m
input rst_n; //复位信号,低有效
input sw1,sw2;
output scl; // 24C02的时钟端口
inout sda; // 24C02的数据端口
output led_d2,led_d3,led_d4,led_d5; //四个LED灯
//--------------------------------------------
//按键检测
reg sw1_r,sw2_r; //每20ms检测一次键值
reg cnt_20ms;
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt_20ms <= 20'd0;
else cnt_20ms <= cnt_20ms+1'b1;
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
sw1_r <= 1'b1;
sw2_r <= 1'b1;
end
else if(cnt_20ms == 20'h0000f) begin
sw1_r <= sw1;
sw2_r <= sw2;
end
//---------------------------------------------
//分频部分
reg cnt; //cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl低电平中间
reg cnt_delay; //
reg scl_r; //时钟脉冲寄存器
always @ (posedge clk)
if(!rst_n) cnt_delay <= 13'd0;
else if(cnt_delay==13'd400) cnt_delay <= 13'd0; //产生iic所需要的时钟
else cnt_delay <= cnt_delay+1'b1;
always @ (posedge clk ) begin
if(!rst_n) cnt <= 2'd0;
else begin
case (cnt_delay)
13'd99: cnt <= 3'd1;
13'd199: cnt <= 3'd2;
13'd299: cnt <= 3'd3;
13'd399: cnt <= 3'd0;
default: cnt <= 3'd5;
endcase
end
end
always @ (posedge clk) begin //posedge clk or negedge rst_n
if(!rst_n) scl_r <= 1'b0;
else if(cnt==3'd0) scl_r <= 1'b1;
else if(cnt==3'd2) scl_r <= 1'b0;
else scl_r <= scl_r;
end
//assign scl = scl_r ? 1'b1:1'b0; //产生iic所需要的时钟
assign scl=scl_r;
//---------------------------------------------
//需要写入24C02的地址和数据
reg device_add; //最低bit:1--读,0--写
parameter device_read = 8'b1010_0001;
parameter device_write = 8'b1010_0000;
reg byte_add; // 写入地址
reg byte_data1; //写入的数据
reg byte_data2; //读出的数据
//---------------------------------------------
//读、写时序
parameter IDLE = 12'b000000000001;
parameter START1 = 12'b000000000010;
parameter ADD1 = 12'b000000000100;
parameter ACK1 = 12'b000000001000;
parameter ADD2 = 12'b000000010000;
parameter ACK2 = 12'b000000100000;
parameter START2 = 12'b000001000000;
parameter ADD3 = 12'b000010000000;
parameter ACK3 = 12'b000100000000;
parameter DATA = 12'b001000000000;
parameter ACK4 = 12'b010000000000;
parameter STOP = 12'b100000000000;
reg current_state,next_state;
reg sda_r,sda_link; //输出数据寄存器
reg num;
reg ack_bit; //响应位寄存器
always @ (next_state or rst_n)//posedge clk or negedge rst_n
if(!rst_n) current_state <= IDLE;
else current_state <= next_state;
always @ (posedge clk or negedge rst_n) begin ////rst_n or current_state or sw1_r or sw2_r or cnt
if(!rst_n) begin
next_state <= IDLE;
sda_r <= 1'b1;
sda_link <= 1'b0;
num <= 4'd0;
byte_data2 <= 8'b0000_0000;
ack_bit <= 1'b1;
byte_add <= 8'b0000_0001; // 0地址
byte_data1 <= 8'b0001_1101; //写入的数据,低四位1001
device_add <= 8'b0000_0000;
end
else
case (current_state)
IDLE: begin
sda_link <= 1'b0;
if((!sw1_r || !sw2_r) && cnt==3'd1) begin
device_add <= device_write;
next_state <= START1;
sda_link <= 1'b1;
sda_r <= 1'b1;
end
else next_state <= IDLE;
end
START1: begin
if(cnt==3'd1) begin
sda_r <= 1'b0;
next_state <= ADD1;
num <= 4'd0;
end
else next_state <= START1;
end
ADD1: begin
if(num<=4'd7) begin
next_state <= ADD1;
if(cnt==3'd3) begin
num <= num+1'b1;
sda_r <= device_add;
end
else if(cnt==3'd0) begin
device_add <= {device_add,device_add};
end
end
else if((num==4'd8) && (cnt==3'd3)) begin
device_add <= {device_add,device_add};//
num <= 4'd0;
sda_link <= 1'b0; //sda置为高阻态
next_state <= ACK1;
end
else next_state <= ADD1;
end
ACK1: begin
if(cnt==3'd2) begin
next_state <= ADD2;
end
else next_state <= ACK1;
end
ADD2: begin
if(num<=4'd7) begin
next_state <= ADD2;
if(cnt==3'd3) begin
sda_link <= 1'b1;
num <= num+1'b1;
sda_r <= byte_add;
end
else if(cnt==3'd0) begin
byte_add <= {byte_add,byte_add};
end
end
else if((num==4'd8) && (cnt==3'd3)) begin
byte_add <= {byte_add,byte_add};//
num <= 4'd0;
sda_link <= 1'b0; //sda置为高阻态
next_state <= ACK2;
if(!sw1_r) device_add <= device_write;
else if(!sw2_r) device_add <= device_read;
end
else next_state <= ADD2;
end
ACK2: begin
if(cnt==3'd2) begin
case (device_add)
1'b1: next_state <= START2; //读操作
1'b0: next_state <= DATA; //写操作
default: ;
endcase
end
else next_state <= ACK2;
end
START2: begin
if(cnt==3'd3) begin
sda_link <= 1'b1;
sda_r <= 1'b1;
end
else if(cnt==3'd1) begin
sda_r <= 1'b0;
next_state <= ADD3;
end
end
ADD3: begin
if(num<=4'd7) begin
next_state <= ADD3;
if(cnt==3'd3) begin
num <= num+1'b1;
sda_r <= device_add;
end
else if(cnt==3'd0) begin
device_add <= {device_add,device_add};
end
end
else if((num==4'd8) && (cnt==3'd3)) begin
device_add <= {device_add,device_add};
num <= 4'd0;
sda_link <= 1'b0; //sda_r置为高阻态
next_state <= ACK3;
end
else next_state <= ADD3;
end
ACK3: begin
if(cnt==3'd3) begin
next_state <= DATA;
end
else next_state <= ACK3;
end
DATA: begin
if(!sw2_r) begin //读
if(num<=4'd7) begin
next_state<= DATA;
if(cnt==3'd1) begin
num <= num+1'b1;
byte_data2 <= sda;
end
else if(cnt==3'd2) begin
byte_data2 <= {byte_data2,byte_data2};
end
end
else if((cnt==3'd3) && (num==4'd8)) begin
byte_data2 <= {byte_data2,byte_data2};
num <= 4'd0;
next_state <= ACK4;
end
else next_state <= DATA;
end
else begin //写
if(num<=4'd7) begin
next_state <= DATA;
if(cnt==3'd3) begin
sda_link <= 1'b1;
num <= num+1'b1;
sda_r <= byte_data1;
end
else if(cnt==3'd0) begin
byte_data1 <= {byte_data1,byte_data1};
end
end
else if((cnt==3'd3) && (num==4'd8)) begin
byte_data1 <= {byte_data1,byte_data1};
num <= 4'd0;
sda_link <= 1'b0; //sda置为高阻态
next_state <= ACK4;
end
else next_state <= DATA;
end
end
ACK4: begin
if(cnt==3'd3) begin
sda_r <= 1'b0;
sda_link <= 1'b1;
next_state <= STOP;
end
else next_state <= ACK4;
end
STOP: begin
if(cnt==3'd1) begin
sda_r <= 1'b1;
end
else if((cnt==3'd3) && sda_link) sda_link <= 1'b0;
if(cnt_20ms==20'hffff0) next_state <= IDLE;
else next_state <= STOP;
end
default: ;
endcase
end
assign sda = sda_link ? sda_r:1'bz;
assign {led_d2,led_d3,led_d4,led_d5} = byte_data2;
//---------------------------------------------
//任务
task write_add1 //写地址1任务
case (num)
4'd0: sda_r <= device_write;
4'd1: sda_r <= device_write;
4'd2: sda_r <= device_write;
4'd3: sda_r <= device_write;
4'd4: sda_r <= device_write;
4'd5: sda_r <= device_write;
4'd6: sda_r <= device_write;
4'd7: sda_r <= device_write;
default: ;
endcase
endtask
task write_add2 begin //写地址2任务
case (num)
4'd0: sda_r <= byte_add;
4'd1: sda_r <= byte_add;
4'd2: sda_r <= byte_add;
4'd3: sda_r <= byte_add;
4'd4: sda_r <= byte_add;
4'd5: sda_r <= byte_add;
4'd6: sda_r <= byte_add;
4'd7: sda_r <= byte_add;
default: ;
endcase
end
endtask
task write_add3 begin //写地址3任务
case (num)
4'd0: sda_r <= device_read;
4'd1: sda_r <= device_read;
4'd2: sda_r <= device_read;
4'd3: sda_r <= device_read;
4'd4: sda_r <= device_read;
4'd5: sda_r <= device_read;
4'd6: sda_r <= device_read;
4'd7: sda_r <= device_read;
default: ;
endcase
end
endtask
task write_data begin //写数据任务
case (num)
4'd0: sda_r <= byte_data1;
4'd1: sda_r <= byte_data1;
4'd2: sda_r <= byte_data1;
4'd3: sda_r <= byte_data1;
4'd4: sda_r <= byte_data1;
4'd5: sda_r <= byte_data1;
4'd6: sda_r <= byte_data1;
4'd7: sda_r <= byte_data1;
default: ;
endcase
end
endtask
task read_data begin //写数据任务
case (num)
4'd0: byte_data2 <= sda;
4'd1: byte_data2 <= sda;
4'd2: byte_data2 <= sda;
4'd3: byte_data2 <= sda;
4'd4: byte_data2 <= sda;
4'd5: byte_data2 <= sda;
4'd6: byte_data2 <= sda;
4'd7: byte_data2 <= sda;
default: ;
endcase
end
endtask
endmodule 呃,示波器上看只有sda在动,但是scl根本就没有反应,这是怎么回事呢?
开发环境:ise8.2
页:
[1]