//sccb接口
//计数器
//明德扬定义计数器
//计数器规则1:计数器逐一考虑3要素:初值、加一条件、结束值
//计数器规则2:计数器初值必须为零
//计数器规则3:使用某一计数器值,必须同时满足加一条件
//计数器规则4:结束条件必须同时满足加一条件
//计数器规则5:当取某个数时,assign的形式必须为:(加一条件)&&(cnt==计数值-1);
//计数器规则6:结束后必须回到0;
//计数器规则7:若要限定范围,则推荐使用">=“和”<"两种符号;
//计数器规则8:设计步骤是,先写计数器的always段,条件用名字代替,然后用assign写出加1条件;最后用assign写出结束条件;
//计数器规则9:加1条件必须与计数器严格对齐,其他信号一律向计数器对齐;
//计数器规则10:命名规则必须符合规范,比如:add_cnt表示加1条件;end_cnt表示结束条件;
//计数器规则11:减1计数器暂时不用。
//计数器八步法
// 第一步:功能明确
// 第二步:功能波形
// 第三步:计数结构 ------根据波形找出实现时序需要的计数器数量和结构
// 第四步:加1和结束条件
// 第五步:定义特殊点
// 第六步:完整性检查
// 第七步:计数器代码
// 第八步:功能代码
用硬件思想去描绘电路 ,找出每个信号变高变低的条件(条件要对齐计数器)
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
cnt_sclk <= 0;
end
else if(add_cnt_sclk) //加一条件
begin
if(end_cnt_sclk) //结束条件
cnt_sclk <= 0;
else
cnt_sclk <= cnt_sclk + 1'b1;
end
end
assign add_cnt_sclk = work_flag;
assign end_cnt_sclk = add_cnt_sclk && cnt_sclk == SCLK_TIME - 1;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
cnt_byte <= 0;
end
else if(add_cnt_byte) //加一条件
begin
if(end_cnt_byte) //结束条件
cnt_byte <= 0;
else
cnt_byte <= cnt_byte + 1'b1;
end
end
assign add_cnt_byte = end_cnt_sclk;
assign end_cnt_byte = add_cnt_byte && cnt_byte == byte_num - 1;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
cnt_step <= 0;
end
else if(add_cnt_step) //加一条件
begin
if(end_cnt_step) //结束条件
cnt_step <= 0;
else
cnt_step <= cnt_step + 1'b1;
end
end
assign add_cnt_step = end_cnt_byte;
assign end_cnt_step = add_cnt_step && cnt_byte == step_num - 1;
//功能代码
parameter IDWADD = 8'h42;
parameter IDRADD = 8'h43;
parameter SCLK_TIME = 400;
parameter SCLK_HALF_TIME = SCLK_TIME/2;
parameter SCLK_W_TIME = SlCK_TIME/4;
parameter SCLK_R_TIME = (SCLK_TIME/4)*3;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
work_flag =1'b0;
end
else if(en)
begin
work_flag <= 1;
end
else if(end_cnt_step)
begin
work_flag <= 0;
end
end
assign en = work_flag == 1'b0 && (wr_en || rd_en);
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
rd_flag =1'b0;
end
else if(rd_en)
begin
rd_flag <= 1;
end
else if(wr_en)
begin
rd_flag <= 0;
end
end
assign wr_state = work_flag && rd_flag == 1'b0;
assign rd_state = work_flag && rd_flag == 1'b1;
assign rd_0_state = rd_state && cnt_step == 1'b0;
assign rd_1_state = rd_state && cnt_step == 1'b1;
assign rd_get_state = rd_1_state && cnt_byte >= 10 && cnt_byte < 18;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
subaad <= 0;
wdata_ff0 <= 0;
end
else if(en)
begin
subaad <= addr;
wdata_ff0 <= wdata;
end
end
always @(*)
begin
if(wr_state)
begin
wdata_temp = {1'b0,IDWADD,1'b1,subaad,1'b1,wdata_ff0,1'b1,1'b0,1'b1};
byte_num = 30;
step_num = 1;
end
else if(rd_0_state)
begin
wdata_temp = {1'b0,IDWADD,1'b1,subaad,1'b1,1'b0,1'b1,9'b0};
byte_num = 21;
step_num = 2;
end
else if(rd_1_state)
begin
wdata_temp = {1'b0,IDRADD,1'b1,8'b0,1'b1,1'b0,1'b1,9'b0};
byte_num = 21;
step_num = 2;
end
end
assign start_area = add_cnt_sclk && cnt_byte == 0;
assign stop_area = add_cnt_sclk && cnt_byte == byte_num - 1;
assign sclk_h2l = add_cnt_sclk && cnt_sclk == 0 && ((!start_area) && (!stop_area));
assign sclk_l2h = add_cnt_sclk && cnt_sclk == SCLK_HALF_TIME - 1;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
sclk =1'b1;
end
else if(sclk_l2h)
begin
sclk <= 1;
end
else if(sclk_l2h)
begin
sclk <= 0;
end
end
assign sio_send = add_cnt_sclk && cnt_sclk == SCLK_W_TIME - 1 && rd_get_state == 1'b0;
assign sio_get = add_cnt_sclk && cnt_sclk == SCLK_R_TIME - 1 && rd_get_state;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
sio_out <=1'b1;
end
else if(sio_send)
begin
sio_out <= wdata_temp[29 - cnt_byte];
end
end
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
sio_out_en =1'b0;
end
else if(work_flag && rd_get_state == 1'b0)
begin
sio_out_en <= 1;
end
else
begin
sio_out_en <= 0;
end
end
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
rdata =1'b0;
end
else if(rd_get_state && sio_get)
begin
rdata <= {rdata[6:0],sio_in};
end
end
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
rdata_vld =1'b0;
end
else if(end_cnt_step && rd_1_state)
begin
rdata_vld <= 1;
end
else
begin
rdata_vld <= 0;
end
end
always @(*)
begin
if(work_flag || rd_en || wr_en)
rdy = 1'b0;
else
rdy = 1'b1;
end