//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