这个时序是通过状态机来实现的 case(sh_counter) 0: //time 0ns begin e1 <= 1'b1; sh <= 1'b0; sh_counter <= sh_counter + 12'h001; end ////////////////////////////////////////////////////////////////////////////////////// 1: //time 2t ns (refer to clk frequence) begin e1 <= 1'b1; sh <= 1'b1; sh_counter <= sh_counter + 12'h001; end 2: //time 3t ns begin e1 <= 1'b1; sh <= 1'b1; sh_counter <= sh_counter + 12'h001; end /////////////////////////////////////////////////////////////////////////////////////// 3: //time 3500ns begin e1 <= 1'b1; sh <= 1'b0; sh_counter <= sh_counter +12'h001; end 4: //time 4000ns begin e1 <= 1'b0; sh <= 1'b0; sh_counter <= sh_counter + 12'h001; end //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// default: begin e1 <= ~e1; sh <= 1'b0; sh_counter <= sh_counter + 12'h001; end endcase
end
end
对于如rs和cp这2个信号,脉冲比较小,而且要达到时序的要求,而且实在E1 E2的后面,所以我使用20m的时钟进行控制,在SH为高的是时候,着个信号是低电平,通过检测E1 E2的状态来完成控制,其实这里还是一个状态机 else if(sh) begin rs <= 1'b0; cp <= 1'b0; rs_cp_counter <= 3'b000; end else if(!e1 && inter_clk) //////////??? not good begin case(rs_cp_counter) 0: begin rs <= 1'b1; cp <= 1'b0; rs_cp_counter <= rs_cp_counter + 3'b001; end 1: begin rs <= 1'b1; cp <= 1'b0; rs_cp_counter <= rs_cp_counter + 3'b001; end 2: begin rs <= 1'b0; cp <= 1'b1; rs_cp_counter <= rs_cp_counter + 3'b001; end 3: begin rs <= 1'b0; cp <= 1'b1; rs_cp_counter <= rs_cp_counter + 3'b001; end default: begin rs <= 1'b0; cp <= 1'b0; rs_cp_counter <= 3'b000; end endcase end
最后说一个最要命的一点 就是复位的问题; 开始我写的时候是这样复位的: always@(negedge reset or posedge clkin or posedge sh) begin if(~reset) begin cp <= 1'b0; rs <= 1'b0; rs_cp_counter <= 4'b0000; end end 也就是说是通过检测复位信号的边沿来实现复位的,但是这种要求在外部有时候是很难打到要求的。 后来参考师兄的写法改为; always@(posedge clkin ) begin if(!reset) begin rs <= 1'b0; cp <= 1'b0; rs_cp_counter <= 3'b000; end end
用户1312638 2009-4-23 10:02