题目:
把时序画的具体点:
设计关键点:
(1)、需用到两个计数器,计数器cnt0 用于产生1M的soic时钟计数,系统100M,产生1M,需计数100次; 计数器cnt1用于对bit位数进行计数,需发送12bit。
(2)、增加flag_add,用于标出需要计数的阶段。
(3)、 soic 在cnt1=0和cnt1=11期间,需保持为高,不能拉低,用于产生起始位和停止位。
(4)、soid 是在soic低电平中间改变,soic高电平期间保持不变。
代码:
1 module sccb( 2 clk, 3 rst_n, 4 en, 5 6 soic, 7 soid 8 ); 9 parameter SOIC_1M = 100; 10 11 input clk; 12 input rst_n; 13 input en; 14 15 output soic; 16 output soid; 17 18 wire add_cnt0; 19 wire end_cnt0; 20 wire add_cnt1; 21 wire end_cnt1; 22 wire [12-1:0] data; 23 24 reg flag_add; 25 reg soic; 26 reg soid; 27 28 reg [8-1:0] cnt0; 29 reg [4-1:0] cnt1; 30 31 assign data = {1'b0,8'h5a,1'b1,1'b0,1'b1}; //将数据拼接好,起始位、8bit数据、ack位、停止位、还有最后将soid拉高 32 33 always @(posedge clk or negedge rst_n)begin 34 if(!rst_n)begin 35 cnt0 <= 0; 36 end 37 else if(add_cnt0)begin 38 if(end_cnt0)begin 39 cnt0 <= 0; 40 end 41 else begin 42 cnt0 <= cnt0 + 1; 43 end 44 end 45 end 46 47 assign add_cnt0 = flag_add; 48 assign end_cnt0 = add_cnt0 && cnt0 == SOIC_1M - 1; 49 50 always @(posedge clk or negedge rst_n)begin 51 if(!rst_n)begin 52 cnt1 <= 0; 53 end 54 else if(add_cnt1)begin 55 if(end_cnt1)begin 56 cnt1 <= 0; 57 end 58 else begin 59 cnt1 <= cnt1 + 1; 60 end 61 end 62 end 63 64 assign add_cnt1 = end_cnt0; 65 assign end_cnt1 = add_cnt1 && cnt1 == 12 - 1; 66 67 always @(posedge clk or negedge rst_n)begin 68 if(!rst_n) begin 69 flag_add <= 0; 70 end 71 else if(en)begin 72 flag_add <= 1; 73 end 74 else if(end_cnt1)begin 75 flag_add <= 0; 76 end 77 end 78 79 //soic 在cnt1=0和cnt1=11期间,需保持为高,不能拉低,产生起始位和停止位 80 always @(posedge clk or negedge rst_n)begin 81 if(!rst_n) begin 82 soic <= 1; 83 end 84 else if(add_cnt0 && cnt0 == SOIC_1M/2 && cnt1 != 0 && cnt1 != 11)begin 85 soic <= 0; 86 end 87 else if(end_cnt0)begin 88 soic <= 1; 89 end 90 end 91 92 //soid 是在soic低电平中间改变,soic高电平期间保持不变 93 always @(posedge clk or negedge rst_n)begin 94 if(!rst_n)begin 95 soid <= 1; 96 end 97 else if(add_cnt0 && cnt0 == 75-1)begin // && cnt1 >= 0 && cnt1 < 12 98 soid <= data[11-cnt1]; 99 end 100 end 101 102 endmodule
仿真代码:
1 module sccb_sim; 2 3 reg clk; 4 reg rst_n; 5 reg en; 6 7 wire soic; 8 wire soid; 9 10 parameter CLK_CYCLE = 10; //100M,时钟周期是10ns 11 12 initial begin 13 clk = 0; 14 forever #(CLK_CYCLE/2) clk = ~clk; 15 end 16 17 initial begin 18 #1; 19 rst_n = 0; 20 #(CLK_CYCLE*10); 21 rst_n = 1; 22 end 23 24 initial begin 25 #1; 26 en = 0; 27 #(CLK_CYCLE*15); 28 repeat(10)begin 29 en = 1; 30 #(CLK_CYCLE); 31 en = 0; 32 #(CLK_CYCLE*$urandom_range(1300,1500)); 33 end 34 end 35 36 sccb sccb_inist( 37 .clk(clk), 38 .rst_n(rst_n), 39 .en(en), 40 41 .soic(soic), 42 .soid(soid) 43 ); 44 45 46 endmodule
仿真波形: