module test(
input wire sys_clk,
input wire sys_rst,
input wire [3:0]key_in,
output reg [7:0]led,
output wire scl,
inout wire sda,//i2c的信号
output wire [7:0]sel,
output wire [7:0]seg//数码管的驱动
);
wire [23:0] data ;
reg [31:0] dsp_data;
reg [23:0] bcd;
wire S1_debounce,S1_debounce_reg;
wire S2_debounce,S2_debounce_reg;
wire S3_debounce,S3_debounce_reg;
localparam KEY1_STATE1=2'b00;//停止状态
localparam KEY1_STATE2=2'b01;//启动状态
localparam KEY2_STATE1=2'b00;
localparam KEY2_STATE2=2'b01;
reg [1:0] key1_state;//当前状态
reg [1:0] key2_state;//当前状态
//显示eeprom读取的数据
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)begin
dsp_data <={4'd11,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10};//初始值,表示没有效数字时钟的显示
led <=8'b11111111;
end else begin
if(S1_debounce_reg&&!S1_debounce)begin
led[0]<=~led[0];
end
bcd[7:4]<=data[7:0]/10;
bcd[3:0]<=data[7:0]%10;
bcd[11:8]<=data[15:8]%10;
bcd[15:12]<=data[15:8]/10;
bcd[19:16]<=data[23:16]%10;
bcd[23:20]<=data[23:16]/10;
dsp_data<={4'd11,bcd[23:16],4'd10,bcd[15:8],4'd10,bcd[7:4]};
end
end
//按键一的状态
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)begin
key1_state<=KEY1_STATE1;
end else begin
if(S1_debounce_reg&&!S1_debounce) begin
key1_state <= (key1_state ==KEY1_STATE1) ? KEY1_STATE2:KEY1_STATE1;
end
end
end
//检测按键二的状态
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)begin
key2_state<=KEY2_STATE1;
end else begin
if(S2_debounce_reg&&!S2_debounce) begin
key2_state <= (key2_state ==KEY2_STATE1) ? KEY2_STATE2:KEY2_STATE1;
end
end
end
wire [23:0] rd_data;
wire rd_data_vld;
//reg define
reg [23:0] wr_data;
reg wr_req;
reg rd_req=0;
//检测写入EEPROM的条件
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)begin
wr_req<=1'b0;
end
else if({key1_state==KEY1_STATE2&&(S1_debounce_reg&&!S1_debounce)}||{key1_state==KEY1_STATE1&&(S2_debounce_reg && !S2_debounce)})begin
wr_data <=data;
wr_req <=1'b1;
end
else
wr_req<=1'b0;
end
reg [3:0] state=0;
reg [15:0] debounce_couter=0;//去抖计数器
reg [15:0] debounce_couter2=0;//去抖计数器
//上电读取eeprom的数据
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst) begin
state <=0;
rd_req<=0;
debounce_couter <=16'b0;
end else begin
case(state)
0:begin
//状态0:等待读取开始
state<=1;
end
1:begin
//状态1;从EEprom读取数据
rd_req<=1;
if(debounce_couter<=16'hFFFF)
debounce_couter <=debounce_couter+1;
else
state <=2;
end
2:begin
//状态2:数据加载完毕
//进一步处理逻辑
rd_req<=0;
debounce_couter<=16'b0;
end
default:state <=0;
endcase
end
end
//eeprom module
eeprom inst_eeprom(
.clk(sys_clk),
.rst(sys_rst),
.wr_req(wr_req),
.rd_req((~key_in[2])||rd_req),//read data from EEProm
.device_id(),
.reg_addr(8'h03),
.reg_addr_vld(1'b1),
.wr_data(wr_data),
.wr_data_vld(wr_req),
.rd_data(rd_data),
.rd_data_vld(rd_data_vld),
.ready(),
.scl(scl),
.sda(sda)
);
//按键模块
key debounce_L1(
.sys_clk(sys_clk),
.rst(sys_rst),
.key_in(key_in[0]),
.S_debounce(S1_debounce),
.S_debounce_reg(S1_debounce_reg)
);
key debounce_L2(
.sys_clk(sys_clk),
.rst(sys_rst),
.key_in(key_in[1]),
.S_debounce(S2_debounce),
.S_debounce_reg(S2_debounce_reg)
);
key debounce_L3(
.sys_clk(sys_clk),
.rst(sys_rst),
.key_in(key_in[2]),
.S_debounce(S3_debounce),
.S_debounce_reg(S3_debounce_reg)
);
//时间计数模块
counter_time u_couter_time(
.clk(sys_clk),
.rst_n(sys_rst),
.key_in1(S1_debounce_reg &&!S1_debounce),
.key_in2(S2_debounce_reg &&!S2_debounce),
.key_in3(S3_debounce_reg &&!S3_debounce),
.rd_req(rd_req),
.rd_data(rd_data),
.din_out(data)
);
//数码管显示模块
segdisplay segdisplay_inst(
.clk(sys_clk),
.rst(sys_rst),
.dsp_data(dsp_data),
.seg(seg),
.sel(sel)
);
endmodule
二、数码管驱动
复制代码
module segdisplay
(
input wire clk ,
input wire rst ,
input wire [31:0] dsp_data ,
output reg [7:0] seg ,//段选端
output reg [7:0] sel //位选段
);
localparam [7:0] DIGIT0 =8'b1100_0000 ;//16精制C0
localparam [7:0] DIGIT1 =8'b1111_1001 ;//F9
localparam [7:0] DIGIT2 =8'b1010_0100;//A4
localparam [7:0] DIGIT3 =8'b1011_0000;//B0
localparam [7:0] DIGIT4 =8'b1001_1001;//99
localparam [7:0] DIGIT5 =8'b1001_0010;//92
localparam [7:0] DIGIT6 =8'b1000_0010;//82
localparam [7:0] DIGIT7 =8'b1111_1000;//F8
localparam [7:0] DIGIT8 =8'b1000_0000;//80
localparam [7:0] DIGIT9 =8'b1001_0000 ;//90
localparam [7:0] DIGITX =8'b1011_1111 ;//
localparam [7:0] DIGOFF =8'b1111_1111 ;//FF
localparam [7:0] DIGITC =8'hC6 ;
localparam DSP_COUNT = 20'd50000; //
reg [19:0] dsp_count ;
reg [3:0] bits ;
reg [3:0] bcd ;
//1ms的计数器
always @(posedge clk or negedge rst)begin
if(!rst)
dsp_count <= 20'd0;
else begin
if (dsp_count == DSP_COUNT-1) begin
dsp_count <= 20'd0;
end else
dsp_count <= dsp_count + 20'd1;
end
end
//位选端
always @(posedge clk or negedge rst) begin
if(!rst)begin
sel <= 8'b1111_1111;
bits <=4'd0;
end else begin
if(dsp_count==DSP_COUNT-1)begin//每一毫秒更新一次
if(bits==4'd8)
bits <=4'd0;
else
bits<=bits+4'd1;
case(bits)
4'd0: begin sel<=8'b1111_1110;bcd<=dsp_data[31:28] ;end
4'd1: begin sel<=8'b1111_1101;bcd<=dsp_data[27:24] ;end
4'd2: begin sel<=8'b1111_1011;bcd<=dsp_data[23:20] ;end
4'd3: begin sel<=8'b1111_0111;bcd<=dsp_data[19:16] ;end
4'd4: begin sel<=8'b1110_1111;bcd<=dsp_data[15:12] ;end
4'd5: begin sel<=8'b1101_1111;bcd<=dsp_data[11:8] ;end
4'd6: begin sel<=8'b1011_1111;bcd<=dsp_data[7:4] ;end
4'd7: begin sel<=8'b0111_1111;bcd<=dsp_data[3:0] ;end
default:sel<=8'b1111_1111;
endcase
end
end
end
//段选端
always @(posedge clk or negedge rst)begin
if(!rst)
seg<=DIGOFF;
else begin
case(bcd)
4'd0: seg<=DIGIT0;
4'd1: seg<=DIGIT1;
4'd2: seg<=DIGIT2;
4'd3: seg<=DIGIT3;
4'd4: seg<=DIGIT4;
4'd5: seg<=DIGIT5;
4'd6: seg<=DIGIT6;
4'd7: seg<=DIGIT7;
4'd8: seg<=DIGIT8;
4'd9: seg<=DIGIT9;
4'd10:seg<=8'b1011_1111;//-
4'd11:seg<=8'b1000_1100;//p
default: seg<=DIGOFF;
endcase
end
end
endmodule
三、按键驱动
复制代码
module key(
input wire sys_clk,
input wire rst,
input wire [0:0] key_in,//按键输入信号,假设最多支持4个按键
output reg [0:0] S_debounce,//去抖后的按键输出
output reg [0:0] S_debounce_reg //去抖的寄存器输出
);
reg [15:0] debounce_counter;//去抖计数器
//按键去抖模块
always @(posedge sys_clk or negedge rst)begin
if(!rst)begin
S_debounce<=0;
S_debounce_reg<=0;
debounce_counter<=16'b0;
end else begin
//针对每个按键经行去抖
if(key_in==1'b0)begin//按键按下
if(debounce_counter< 16'hFFFF)
debounce_counter<=debounce_counter+1;
else
S_debounce_reg<=1'b1;//该按键去抖确认按下
end else begin
debounce_counter<=16'b0;
S_debounce_reg<=1'b0;//按键松开
end
end
//更新去抖后的按键输出
S_debounce <=S_debounce_reg;
end
endmodule
四、计数器模块
复制代码
module counter_time(
input wire clk,
input wire rst_n,
input wire key_in1,//消抖后的脉冲信号,高有效
input wire key_in2,//消抖后的脉冲信号,高有效
input wire key_in3,//消抖后的脉冲信号,高有效
input wire [23:0]rd_data,
input wire rd_req,
output wire [23:0]din_out//输出当前计数值
);
parameter MAX_1MS=16'd49_999;//1ms
parameter MAX_1S=10'd999;//1ms*1000=1s
parameter MAX_1MIN=6'd59;//1s*60=1min
parameter MAX_1H=6'd59;//1min*60=1h
reg flag;//开始、暂停结束信号
reg [15:0]cnt_1ms;
wire add_cnt_1ms;
wire end_cnt_1ms;
reg [9:0]cnt_1s;
wire add_cnt_1s;
wire end_cnt_1s;
reg [5:0]cnt_1min;
wire add_cnt_1min;
wire end_cnt_1min;
reg [5:0]cnt_1h;
wire add_cnt_1h;
wire end_cnt_1h;
reg [7:0] data_min;//保存此时有多少分钟
reg [7:0] data_s;//保存此时有多少秒
reg [7:0] data_ms;//保存此时有多少毫秒,只取高两位
//flag
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
flag<=1'b0;
end
else if(key_in1) begin
flag<=~flag;
end
else begin
flag<=flag;
end
end
//1ms计数器
always @(posedge clk or negedge rst_n or posedge key_in2) begin
if(!rst_n||key_in2)begin
cnt_1ms<=16'd0;
end
else if(add_cnt_1ms)begin
if(end_cnt_1ms)begin
cnt_1ms<=16'd0;
end
else begin
cnt_1ms<=cnt_1ms+1'b1;
end
end
end
assign add_cnt_1ms=flag;
assign end_cnt_1ms=add_cnt_1ms&&{cnt_1ms==MAX_1MS};
//1S计数器
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)begin
cnt_1s<=10'd0;
end
else if(key_in3||rd_req)begin
cnt_1s<=rd_data[7:0]*10;
end
else if(key_in2)begin
cnt_1s<=0;
end
else if(add_cnt_1s)begin
if(end_cnt_1s)begin
cnt_1s<=10'd0;
end
else begin
cnt_1s<=cnt_1s+1'b1;
end
end
end
assign add_cnt_1s=end_cnt_1ms;
assign end_cnt_1s=add_cnt_1s&&cnt_1s==MAX_1S;
//1min计数器
always @(posedge clk or negedge rst_n or posedge key_in2) begin
if(!rst_n||key_in2)begin
cnt_1min<=6'd0;
end
else if(key_in3||rd_req)begin
cnt_1min<=rd_data[23:16];
end
else if(add_cnt_1min)begin
if(end_cnt_1min)begin
cnt_1min<=6'd0;
end
else begin
cnt_1min<=cnt_1min+1'b1;
end
end
end
assign add_cnt_1min=end_cnt_1s;
assign end_cnt_1min=add_cnt_1min&&cnt_1s==MAX_1MIN;
//1H计数器
always @(posedge clk or negedge rst_n or posedge key_in2) begin
if(!rst_n||key_in2)begin
cnt_1h<=6'd0;
end
else if(key_in3||rd_req)begin
cnt_1h<=rd_data[15:8];
end
else if(add_cnt_1h)begin
if(end_cnt_1h)begin
cnt_1h<=6'd0;
end
else begin
cnt_1h<=cnt_1h+1'b1;
end
end
end
assign add_cnt_1h=end_cnt_1min;
assign end_cnt_1h=add_cnt_1h&&cnt_1h==MAX_1H;
//数据输出
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
begin
data_min<=8'd3;
data_s<=8'd7;
data_ms<=8'd2;
end
else
begin
data_min<=cnt_1h;
data_s<=cnt_1min;
data_ms<=cnt_1s/10;
end
end
assign din_out={data_min,data_s,data_ms};
endmodule
五、I2C驱动
复制代码
module i2c(
input clk ,
input rst ,
input [7:0] wr_data ,
input [4:0] cmd ,
input cmd_vld ,
output [7:0] rd_data ,
output rd_data_vld ,
output reg rev_ack ,
output done ,
output reg scl ,
inout sda
);
//para define
localparam IDLE = 7'b0000001,
START = 7'b0000010,
WR_DATA = 7'b0000100,
RD_DATA = 7'b0001000,
R_ACK = 7'b0010000,
T_ACK = 7'b0100000,
STOP = 7'b1000000;
parameter T = 100_000,
SCL_MAX = 50_000_000 / T;
parameter SCL_LOW_HALF = (SCL_MAX * 1 / 4) - 1,
SCL_HIGH_HALF = (SCL_MAX * 3 / 4) - 1;
`define START_BIT 5'b00001
`define WRITE_BIT 5'b00010
`define READ_BIT 5'b00100
`define STOP_BIT 5'b01000
`define ACK_BIT 5'b10000
`define ACK 0
`define NO_ACK 1
//reg define
reg [6:0] cstate ;
reg [6:0] nstate ;
reg [4:0] cmd_r ;
reg [7:0] wr_data_r ;
reg [7:0] rd_data_r ;
reg sda_out ;
reg OE ;
reg [8:0] cnt_bit ;
reg [3:0] num ;
reg [3:0] cnt_num ;
//wire define
wire sda_in ;
wire add_cnt_bit ;
wire end_cnt_bit ;
wire add_cnt_num ;
wire end_cnt_num ;
wire IDLE_START ;
wire START_WR_DATA ;
wire WR_DATA_R_ACK ;
wire R_ACK_IDLE ;
wire IDLE_WR_DATA ;
wire R_ACK_STOP ;
wire STOP_IDLE ;
wire IDLE_RD_DATA ;
wire RD_DATA_T_ACK ;
wire T_ACK_IDLE ;
wire T_ACK_STOP ;
assign add_cnt_bit = cstate != IDLE;
assign end_cnt_bit = add_cnt_bit && cnt_bit == SCL_MAX - 1'd1;
assign add_cnt_num = end_cnt_bit;
assign end_cnt_num = add_cnt_num && cnt_num == num - 1;
assign IDLE_START = (cstate == IDLE) && cmd_vld && (cmd & `START_BIT) ;
assign START_WR_DATA = (cstate == START) && end_cnt_num && (cmd_r & `WRITE_BIT) ;
assign WR_DATA_R_ACK = (cstate == WR_DATA) && end_cnt_num ;
assign R_ACK_IDLE = (cstate == R_ACK) && end_cnt_num && !(cmd_r & `STOP_BIT) ;
assign IDLE_WR_DATA = (cstate == IDLE) && cmd_vld && (cmd & `WRITE_BIT) ;
assign R_ACK_STOP = (cstate == R_ACK) && end_cnt_num && (cmd_r & `STOP_BIT) ;
assign STOP_IDLE = (cstate == STOP) && end_cnt_num ;
assign IDLE_RD_DATA = (cstate == IDLE) && cmd_vld && (cmd & `READ_BIT) ;
assign RD_DATA_T_ACK = (cstate == RD_DATA) && end_cnt_num ;
assign T_ACK_IDLE = (cstate == T_ACK) && end_cnt_num && !(cmd_r & `STOP_BIT) ;
assign T_ACK_STOP = (cstate == T_ACK) && end_cnt_num && (cmd_r & `STOP_BIT) ;
assign sda = OE ? sda_out : 1'bz;
assign sda_in = sda;
assign done = R_ACK_IDLE || T_ACK_IDLE || STOP_IDLE;
assign rd_data = rd_data_r;
assign rd_data_vld = T_ACK_IDLE || T_ACK_STOP;
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
wr_data_r <= 'd0;
cmd_r <= 'd0;
end
else if (cmd_vld) begin
wr_data_r <= wr_data;
cmd_r <= cmd;
end
end
//
always @(posedge clk or negedge rst) begin
if(!rst)begin
cnt_bit <= 'd0;
end
else if(add_cnt_bit)begin
if(end_cnt_bit)begin
cnt_bit <= 'd0;
end
else begin
cnt_bit <= cnt_bit + 1'd1;
end
end
end
//IIC_SCL
always @(posedge clk or negedge rst) begin
if (!rst) begin
scl <= 'd1;
end
else if (cnt_bit == (SCL_MAX - 1 ) >> 1 || STOP_IDLE) begin
scl <= 'd1;
end
else if (end_cnt_bit) begin
scl <= 'd0;
end
end
//
always @(posedge clk or negedge rst)begin
if(!rst)begin
cnt_num <= 'd0;
end
else if(add_cnt_num)begin
if(end_cnt_num)begin
cnt_num <= 'd0;
end
else begin
cnt_num <= cnt_num + 1'd1;
end
end
end
//
always @(*) begin
case (cstate)
IDLE : num = 1;
START : num = 1;
WR_DATA : num = 8;
RD_DATA : num = 8;
R_ACK : num = 1;
T_ACK : num = 1;
STOP : num = 1;
default : num = 1;
endcase
end
//
always @(posedge clk or negedge rst)begin
if(!rst)begin
cstate <= IDLE;
end
else begin
cstate <= nstate;
end
end
//
always @(*) begin
case(cstate)
IDLE : begin
if (IDLE_START) begin
nstate = START;
end
else if (IDLE_WR_DATA) begin
nstate = WR_DATA;
end
else if (IDLE_RD_DATA) begin
nstate = RD_DATA;
end
else begin
nstate = cstate;
end
end
START : begin
if (START_WR_DATA) begin
nstate = WR_DATA;
end
else begin
nstate = cstate;
end
end
WR_DATA : begin
if (WR_DATA_R_ACK) begin
nstate = R_ACK;
end
else begin
nstate = cstate;
end
end
RD_DATA : begin
if (RD_DATA_T_ACK) begin
nstate = T_ACK;
end
else begin
nstate = cstate;
end
end
R_ACK : begin
if (R_ACK_STOP) begin
nstate = STOP;
end
else if (R_ACK_IDLE) begin
nstate = IDLE;
end
else begin
nstate = cstate;
end
end
T_ACK : begin
if (T_ACK_STOP) begin
nstate = STOP;
end
else if (T_ACK_IDLE) begin
nstate = IDLE;
end
else begin
nstate = cstate;
end
end
STOP : begin
if (STOP_IDLE) begin
nstate = IDLE;
end
else begin
nstate = cstate;
end
end
default : nstate = cstate;
endcase
end
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
OE <= 'b0;
end else if (IDLE_START || START_WR_DATA || IDLE_WR_DATA || R_ACK_STOP || RD_DATA_T_ACK) begin
OE <= 'b1;
end else if (IDLE_RD_DATA || WR_DATA_R_ACK || STOP_IDLE) begin
OE <= 'b0;
end
end
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
sda_out <= 1;
end
else begin
case (cstate)
IDLE :sda_out <= 1;
START :begin
if (cnt_bit == SCL_LOW_HALF) begin
sda_out <= 'b1;
end
else if (cnt_bit == SCL_HIGH_HALF) begin
sda_out <= 'b0;
end
end
WR_DATA :begin
if (cnt_bit == SCL_LOW_HALF) begin
sda_out <= wr_data_r[7 - cnt_num];
end
end
T_ACK :begin
if (cnt_bit == SCL_LOW_HALF) begin
if (cmd & `ACK_BIT) begin
sda_out <= `NO_ACK;
end
else begin
sda_out <= `ACK;
end
end
end
STOP :begin
if (cnt_bit == SCL_LOW_HALF) begin
sda_out <= 'b0;
end
else if (cnt_bit == SCL_HIGH_HALF) begin
sda_out <= 'b1;
end
end
default: sda_out <= 'b1;
endcase
end
end
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
rev_ack <= 0;
rd_data_r <= 8'b0;
end
else begin
case (cstate)
RD_DATA:begin
if (cnt_bit == SCL_HIGH_HALF) begin
rd_data_r[7-cnt_num] <= sda_in;
end
end
R_ACK :begin
if (cnt_bit == SCL_HIGH_HALF) begin
rev_ack <= sda_in;
end
end
default:;
endcase
end
end
endmodule
六、eeprom模块
复制代码
module eeprom (
input wire clk ,
input wire rst ,
input wire wr_req ,
input wire rd_req ,
input wire [6:0] device_id ,
input wire [7:0] reg_addr ,
input wire reg_addr_vld,
input wire [7:0] wr_data ,
input wire wr_data_vld ,
output wire [7:0] rd_data ,
output wire rd_data_vld ,
output wire ready ,
output wire scl ,
inout wire sda
);
//para define
`define START_BIT 5'b00001
`define WRITE_BIT 5'b00010
`define READ_BIT 5'b00100
`define STOP_BIT 5'b01000
`define ACK_BIT 5'b10000
localparam IDLE = 6'b000001,
WR_REQ = 6'b000010,
WR_WAIT = 6'b000100,
RD_REQ = 6'b001000,
RD_WAIT = 6'b010000,
DONE = 6'b100000;
localparam WR_CTRL_BYTE = 8'b1010_0000;
localparam RD_CTRL_BYTE = 8'b1010_0001;
//wire define
wire IDLE_WR_REQ ;
wire IDLE_RD_REQ ;
wire WR_REQ_WR_WAIT ;
wire RD_REQ_RD_WAIT ;
wire WR_WAIT_WR_REQ ;
wire WR_WAIT_DONE ;
wire RD_WAIT_RD_REQ ;
wire RD_WAIT_DONE ;
wire DONE_IDLE ;
wire done ;
wire add_cnt_byte ;
wire end_cnt_byte ;
//reg define
reg [5:0] cstate ;
reg [5:0] nstate ;
reg [2:0] num ;
reg [4:0] cmd ;
reg cmd_vld ;
reg [7:0] op_wr_data ;
reg [15:0] addr_r ;
reg [7:0] wr_data_r ;
reg [2:0] cnt_byte ;
reg wr_req_r ;
reg rd_req_r ;
assign add_cnt_byte = done;
assign end_cnt_byte = add_cnt_byte && cnt_byte == num - 1;
assign IDLE_WR_REQ = (cstate == IDLE) && wr_req_r;
assign IDLE_RD_REQ = (cstate == IDLE) && rd_req_r;
assign WR_REQ_WR_WAIT = (cstate == WR_REQ) && 1;
assign RD_REQ_RD_WAIT = (cstate == RD_REQ) && 1;
assign WR_WAIT_WR_REQ = (cstate == WR_WAIT) && done;
assign WR_WAIT_DONE = (cstate == WR_WAIT) && end_cnt_byte;
assign RD_WAIT_RD_REQ = (cstate == RD_WAIT) && done;
assign RD_WAIT_DONE = (cstate == RD_WAIT) && end_cnt_byte;
assign DONE_IDLE = (cstate == DONE) && 1;
assign ready = cstate == IDLE;
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
wr_req_r <=0;
rd_req_r <= 0;
end
else begin
wr_req_r <= wr_req;
rd_req_r <= rd_req;
end
end
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
addr_r <= 'd0;
end
else if (reg_addr_vld) begin
addr_r <= reg_addr;
end
end
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
wr_data_r <= 'd0;
end
else if (wr_req) begin
wr_data_r <= wr_data;
end
end
//
always @(posedge clk or negedge rst)begin
if(!rst)begin
cnt_byte <= 'd0;
end
else if(add_cnt_byte)begin
if(end_cnt_byte)begin
cnt_byte <= 'd0;
end
else begin
cnt_byte <= cnt_byte + 1'd1;
end
end
end
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
num <= 1;
end
else if (wr_req) begin
num <= 4;
end
else if (rd_req) begin
num <= 5;
end
else if (end_cnt_byte) begin
num <= 1;
end
end
//
always @(posedge clk or negedge rst)begin
if(!rst)begin
cstate <= IDLE;
end
else begin
cstate <= nstate;
end
end
//
always @(*) begin
case(cstate)
IDLE :begin
if (IDLE_WR_REQ) begin
nstate = WR_REQ;
end
else if (IDLE_RD_REQ) begin
nstate = RD_REQ;
end
else begin
nstate = cstate;
end
end
WR_REQ :begin
if (WR_REQ_WR_WAIT) begin
nstate = WR_WAIT;
end
else begin
nstate = cstate;
end
end
WR_WAIT :begin
if (WR_WAIT_DONE) begin
nstate = DONE;
end
else if (WR_WAIT_WR_REQ) begin
nstate = WR_REQ;
end
else begin
nstate = cstate;
end
end
RD_REQ :begin
if (RD_REQ_RD_WAIT) begin
nstate = RD_WAIT;
end
else begin
nstate = cstate;
end
end
RD_WAIT :begin
if (RD_WAIT_DONE) begin
nstate = DONE;
end
else if (RD_WAIT_RD_REQ) begin
nstate = RD_REQ;
end
else begin
nstate = cstate;
end
end
DONE :begin
if (DONE_IDLE) begin
nstate = IDLE;
end
else begin
nstate = cstate;
end
end
default : nstate = cstate;
endcase
end
//
always @(posedge clk or negedge rst) begin
if (!rst) begin
TX(0,4'h0,8'h00);
end
else begin
case (cstate)
RD_REQ:begin
case (cnt_byte)
0 : TX(1,(`START_BIT | `WRITE_BIT),WR_CTRL_BYTE);
1 : TX(1,(`WRITE_BIT ),addr_r[15:8]);
2 : TX(1,(`WRITE_BIT ),addr_r[7:0] );
3 : TX(1,(`START_BIT | `WRITE_BIT),RD_CTRL_BYTE);
4 : TX(1,(`READ_BIT | `STOP_BIT ),8'h00 );
default: TX(0,cmd,op_wr_data);
endcase
end
WR_REQ:begin
case (cnt_byte)
0 : TX(1,(`START_BIT | `WRITE_BIT),WR_CTRL_BYTE);
1 : TX(1,(`WRITE_BIT ),addr_r[15:8]);
2 : TX(1,(`WRITE_BIT ),addr_r[7:0] );
3 : TX(1,(`WRITE_BIT | `STOP_BIT ),wr_data_r );
default: TX(0,cmd,op_wr_data);
endcase
end
default: TX(0,cmd,op_wr_data);
endcase
end
end
i2c inst_i2c(
.clk (clk),
.rst (rst),
.wr_data (op_wr_data),
.cmd (cmd),
.cmd_vld (cmd_vld),
.rd_data (rd_data),
.rd_data_vld (rd_data_vld),
.done (done),
.scl (scl),
.sda (sda)
);
task TX;
input task_cmd_vld ;
input [3:0] task_cmd ;
input [7:0] task_wr_data ;
begin
cmd_vld = task_cmd_vld ;
cmd = task_cmd ;
op_wr_data = task_wr_data ;
end
endtask
endmodule