当前位置:   article > 正文

针对OV5640(16位寄存器位宽)的sccb接口

针对OV5640(16位寄存器位宽)的sccb接口

sccb不需要判断应答位

        

  1. /*qin*/
  2. module sccb_io
  3. (
  4. input clk,
  5. input rst_n,
  6. input sccb_write_req,
  7. input sccb_read_req,
  8. output sccb_ack,//数据发送完成
  9. output [7:0] sccb_read_data,
  10. input [6:0] lut_id,
  11. input [15:0] lut_addr,
  12. input [7:0] lut_data,
  13. inout sccb_sda,
  14. output reg sccb_scl
  15. );
  16. /*
  17. sccb_io u_sccb_io(
  18. .clk (clk ),
  19. .rst_n (rst_n ),
  20. .sccb_write_req (sccb_write_req ),
  21. .sccb_read_req (sccb_read_req ),
  22. .sccb_ack (sccb_ack ),
  23. .lut_id (lut_id ),
  24. .lut_addr (lut_addr ),
  25. .lut_data (lut_data ),
  26. .sccb_sda (sccb_sda ),
  27. .sccb_scl (sccb_scl )
  28. );
  29. */
  30. localparam cmoscnt_max = 'd2000;
  31. localparam cmoscnt_half = 'd1000;
  32. localparam comscnt_quater = 'd1500;
  33. localparam IDLE = 8'b00000000;
  34. localparam START = 8'b00000001;
  35. localparam ID_ADDR = 8'b00000010;
  36. localparam REG_ADDR = 8'b00000100;
  37. localparam WRITE = 8'b00001000;
  38. localparam READ = 8'b00010000;
  39. localparam STOP = 8'b00100000;
  40. wire sccb_en;
  41. wire scl_down;
  42. reg scl_frame;
  43. reg sdo;
  44. reg sdir;
  45. reg turnflag;
  46. reg [7:0] read_data;//
  47. reg [15:0] delay;//最大值必须是cmoscnt_max的两倍以上
  48. reg [7:0] ID_CNT; //发送从机地址
  49. reg [7:0] REG_CNT; //发送寄存器地址
  50. reg [7:0] DATA_CNT;//读写地址
  51. reg [15:0] sccb_cnt;
  52. reg [7:0] currentstate;
  53. reg [7:0] nextstate;
  54. assign sccb_en = (sccb_cnt == cmoscnt_max)?1'b1:1'b0;
  55. assign scl_down = (!sccb_scl && scl_frame)?1'b1:1'b0;
  56. assign sccb_sda = (sdir)?sdo:1'hz;
  57. assign sccb_ack = (delay == 16'd5000)?1'b1:1'b0;
  58. assign sccb_read_data = read_data;
  59. always @(posedge clk or negedge rst_n)
  60. begin
  61. if(!rst_n)
  62. sccb_cnt <= 'd0;
  63. else if(currentstate == IDLE)
  64. sccb_cnt <= 'd0;
  65. else if(currentstate == STOP)
  66. begin
  67. if(sccb_scl == 1'b1 && sdo == 1'b1)
  68. sccb_cnt <= sccb_cnt;
  69. else
  70. sccb_cnt <= (sccb_cnt < 2*cmoscnt_max)?sccb_cnt + 1'b1:sccb_cnt;
  71. end
  72. // else if(currentstate == START)
  73. // begin
  74. // if(turnflag)begin
  75. // sccb_cnt <= (sccb_cnt > cmoscnt_half)?'d0:(sccb_cnt + 1'b1);
  76. // turnflag <= 1'b0;
  77. // end
  78. // else
  79. // sccb_cnt <= sccb_cnt + 1'b1;
  80. // end
  81. else if(sccb_cnt == cmoscnt_max)
  82. sccb_cnt <= 'd0;
  83. else
  84. sccb_cnt <= sccb_cnt + 1'b1;
  85. end
  86. always @(posedge clk or negedge rst_n)
  87. begin
  88. if(!rst_n)
  89. scl_frame <= 1'b1;
  90. else
  91. scl_frame <= sccb_scl;
  92. end
  93. always @(posedge clk or negedge rst_n)
  94. begin
  95. if(!rst_n)
  96. sccb_scl <= 1'b1;
  97. else if(currentstate == IDLE)
  98. sccb_scl <= 1'b1;
  99. else if(currentstate == START)
  100. begin
  101. if(sccb_cnt == comscnt_quater)
  102. sccb_scl <= 1'b0;
  103. else
  104. sccb_scl <= sccb_scl;
  105. end
  106. else if(currentstate == STOP)
  107. begin
  108. if(sccb_en)
  109. sccb_scl <= 1'b1;
  110. else
  111. sccb_scl <= sccb_scl;
  112. end
  113. else if(sccb_en)
  114. sccb_scl <= ~sccb_scl;
  115. end
  116. always @(posedge clk or negedge rst_n)
  117. begin
  118. if(!rst_n)
  119. turnflag <= 1'b0;
  120. else if(currentstate == STOP && nextstate == START)
  121. turnflag <= 1'b1;
  122. end
  123. always @(posedge clk or negedge rst_n)
  124. begin
  125. if(!rst_n)begin
  126. ID_CNT <= 'd0;
  127. REG_CNT <= 'd0;
  128. DATA_CNT<= 'd0;
  129. end
  130. else begin
  131. ID_CNT <= (currentstate == ID_ADDR)?((sccb_en && sccb_scl)?(ID_CNT + 1'b1):ID_CNT):'d0;
  132. REG_CNT <= (currentstate == REG_ADDR)?((sccb_en && sccb_scl)?(REG_CNT + 1'b1):REG_CNT):'d0;
  133. DATA_CNT <= (currentstate == WRITE || currentstate == READ)?((sccb_en && sccb_scl)?(DATA_CNT + 1'b1):DATA_CNT):'d0;
  134. end
  135. end
  136. always @(posedge clk or negedge rst_n)
  137. begin
  138. if(!rst_n)
  139. sdir <= 1'b1;
  140. else if (sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)begin
  141. case(currentstate)
  142. IDLE: sdir <= 1'b1;
  143. START: sdir <= 1'b1;
  144. ID_ADDR: sdir <= (ID_CNT == 8'd8)?1'b0:1'b1;
  145. REG_ADDR: sdir <= (REG_CNT == 8'd8 || REG_CNT == 8'd17)?1'b0:1'b1;
  146. WRITE: sdir <= (DATA_CNT == 8'd8)?1'b0:1'b1;
  147. READ: sdir <= (DATA_CNT == 8'd8)?1'b1:1'b0;
  148. STOP: sdir <= 1'b1;//(bit_cnt == )?1'b0:1'b1;
  149. default: sdir <= 1'b1;
  150. endcase
  151. end
  152. end
  153. always @(posedge clk or negedge rst_n)
  154. begin
  155. end
  156. always @(posedge clk or negedge rst_n)
  157. begin
  158. if(!rst_n)
  159. delay <= 'd0;
  160. else if(currentstate == STOP)
  161. delay <= delay + 1'b1;
  162. else
  163. delay <= 'd0;
  164. end
  165. always @(posedge clk or negedge rst_n)
  166. begin
  167. if(!rst_n)
  168. currentstate <= IDLE;
  169. else
  170. currentstate <= nextstate;
  171. end
  172. always @(*)
  173. begin
  174. case(currentstate)
  175. IDLE:begin
  176. if(sccb_read_req || sccb_write_req)
  177. nextstate = START;
  178. else
  179. nextstate = IDLE;
  180. end
  181. START:begin
  182. if(sccb_read_req || sccb_write_req)begin
  183. if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_max)
  184. nextstate = ID_ADDR;
  185. else
  186. nextstate = START;
  187. end
  188. else
  189. nextstate = IDLE;
  190. end
  191. ID_ADDR:begin
  192. if(sccb_read_req || sccb_write_req)begin
  193. if(ID_CNT == 8'd9)
  194. nextstate = REG_ADDR;
  195. else
  196. nextstate = ID_ADDR;
  197. end
  198. else
  199. nextstate = IDLE;
  200. end
  201. REG_ADDR:begin
  202. if(sccb_read_req || sccb_write_req)begin
  203. if(REG_CNT == 8'd18)begin
  204. if(sccb_write_req)
  205. nextstate = WRITE;
  206. else
  207. nextstate = READ;
  208. end
  209. else
  210. nextstate = REG_ADDR;
  211. end
  212. else
  213. nextstate = IDLE;
  214. end
  215. WRITE:begin
  216. if(sccb_read_req || sccb_write_req)begin
  217. if(DATA_CNT == 8'd9)
  218. nextstate = STOP;
  219. else
  220. nextstate = WRITE;
  221. end
  222. else
  223. nextstate = IDLE;
  224. end
  225. READ:begin
  226. if(sccb_read_req || sccb_write_req)begin
  227. if(DATA_CNT == 8'd9)
  228. nextstate = STOP;
  229. else
  230. nextstate = READ;
  231. end
  232. else
  233. nextstate = IDLE;
  234. end
  235. STOP:begin
  236. // if(delay == 'd5000)begin
  237. // if(sccb_read_req || sccb_write_req)
  238. // nextstate = START;
  239. // else
  240. // end
  241. if(delay == 'd5000)
  242. nextstate = IDLE;
  243. else
  244. nextstate = STOP;
  245. end
  246. default:;
  247. endcase
  248. end
  249. always @(posedge clk or negedge rst_n)
  250. begin
  251. if(!rst_n)begin
  252. sdo <= 1'b1;
  253. read_data <= 'd0;
  254. end
  255. else begin
  256. case(currentstate)
  257. IDLE:begin
  258. sdo <= 1'b1;
  259. end
  260. START:begin
  261. if(sccb_cnt == cmoscnt_half)
  262. sdo <= 1'b0;
  263. else
  264. sdo <= sdo;
  265. end
  266. ID_ADDR:begin
  267. if(ID_CNT < 8'd7)begin
  268. if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
  269. sdo <= lut_id[8'd6 - ID_CNT];
  270. else
  271. sdo <= sdo;
  272. end
  273. else begin
  274. if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
  275. begin
  276. if(sccb_write_req)
  277. sdo <= 1'b0;
  278. else
  279. sdo <= 1'b1;
  280. end
  281. else
  282. sdo <= sdo;
  283. end
  284. end
  285. REG_ADDR:begin
  286. if(REG_CNT < 8'd8)begin
  287. if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
  288. sdo <= lut_addr[8'd15 - REG_CNT];//高8位
  289. else
  290. sdo <= sdo;
  291. end
  292. else if(REG_CNT < 8'd17 && REG_CNT > 8'd8)begin
  293. if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
  294. sdo <= lut_addr[8'd16 - REG_CNT];//低8位
  295. else
  296. sdo <= sdo;
  297. end
  298. else
  299. sdo <= 1'b1;
  300. end
  301. WRITE:begin
  302. if(DATA_CNT < 8'd8 )begin
  303. if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
  304. sdo <= lut_data[8'd7 - DATA_CNT];
  305. else
  306. sdo <= sdo;
  307. end
  308. else
  309. sdo <= 1'b1;
  310. end
  311. READ:begin
  312. if(DATA_CNT < 8'd8 )begin
  313. if(sccb_scl == 1'b1 && sccb_cnt == cmoscnt_half)
  314. read_data[8'd7 - DATA_CNT] <= sccb_sda;
  315. else
  316. read_data <= read_data;
  317. end
  318. else begin
  319. read_data <= read_data;
  320. if(DATA_CNT == 8'd8)
  321. sdo <= 1'b0;
  322. else
  323. sdo <= sdo;
  324. end
  325. end
  326. STOP:begin
  327. if(sccb_scl == 1'b1 && sccb_cnt == 2*cmoscnt_max)
  328. sdo <= 1'b1;
  329. else
  330. sdo <= 1'b0;
  331. end
  332. default:;
  333. endcase
  334. end
  335. end
  336. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/881538
推荐阅读
相关标签
  

闽ICP备14008679号