当前位置:   article > 正文

基于intel(altera)FPGA OV5640摄像头 图像采集系统(完整代码)_pll root divider

pll root divider

 此项目一共分为摄像头配置模块,图像采集模块,异步FIFO控制模块,SDRAM控制模块,SDRAM端口模块,VGA显示模块。

摄像头配置模块

        直接采用IIC接口对摄像头进行配置:模块分化:IIC端口模块,IIC控制模块,和LUT查找表模块;配置图像像素输出为1280*720

摄像头配置参数

  1. //涉嫌头参数配置-LUT模块
  2. module lut_da(
  3. input clk ,
  4. input rst_n ,
  5. input redy , //反馈信号,1可以发数据,0 不能读写
  6. output reg data_en ,
  7. output [24:0] data_out ,
  8. output config_done //1代表配置完成
  9. );
  10. parameter RW_CTRL=1'b0; //1代表写模式+读模式 ;0代表只写
  11. localparam WAIT_TIME =1000_000,//上电等待时间
  12. MAX =253-2 ,
  13. WAIT =3'b001,
  14. WRITE =3'b010,
  15. IDLE =3'b100;
  16. reg [19:0] cnt ;
  17. wire add_cnt ;
  18. wire end_cnt ;
  19. reg [24:0] lut_data;
  20. reg cnt_flag;
  21. reg [2:0] state;
  22. reg [2:0] state_next;
  23. wire wait_write ;
  24. wire write_idle ;
  25. always@(posedge clk or negedge rst_n) begin
  26. if(!rst_n) begin
  27. state<=WAIT;
  28. end
  29. else begin
  30. state<=state_next;
  31. end
  32. end
  33. always @(*)begin
  34. case(state)
  35. WAIT :begin
  36. if(wait_write) begin
  37. state_next=WRITE;
  38. end
  39. else begin
  40. state_next=WAIT;
  41. end
  42. end
  43. WRITE:begin
  44. if(write_idle) begin
  45. state_next=IDLE;
  46. end
  47. else begin
  48. state_next=WRITE;
  49. end
  50. end
  51. IDLE :begin
  52. state_next=IDLE;
  53. end
  54. default:state=WAIT;
  55. endcase
  56. end
  57. assign wait_write=state==WAIT && end_cnt;
  58. assign write_idle=state==WRITE&& end_cnt;
  59. always @(posedge clk or negedge rst_n)begin
  60. if(!rst_n)begin
  61. cnt <= 0;
  62. end
  63. else if(add_cnt)begin
  64. if(end_cnt)begin
  65. cnt <= 0;
  66. end
  67. else begin
  68. cnt <= cnt + 1'b1;
  69. end
  70. end
  71. end
  72. assign add_cnt = state==WAIT|| (state==WRITE&&cnt_flag);
  73. assign end_cnt = add_cnt && cnt==( (state==WAIT) ? (WAIT_TIME-1 ): (MAX+1) ) ;
  74. //data_en
  75. always @(posedge clk or negedge rst_n)begin
  76. if(!rst_n)begin
  77. data_en <= 0;
  78. end
  79. else if( data_en==1 && state==WRITE ) begin
  80. data_en <= 0;
  81. end
  82. else if( state==WRITE && redy==1 )begin //redy==1模块空闲中,可以读写操作
  83. data_en<=1;
  84. end
  85. end
  86. assign config_done= state==IDLE;
  87. assign data_out= (state==WRITE) ? lut_data : 1'b0;
  88. always @(posedge clk or negedge rst_n)begin
  89. if(!rst_n)begin
  90. cnt_flag <= 0;
  91. end
  92. else if(data_en)begin
  93. cnt_flag<=1'b1;
  94. end
  95. else begin
  96. cnt_flag<=0;
  97. end
  98. end
  99. //lut_data
  100. always@(*)begin
  101. case( cnt ) //2个字节地址,一个字节数据
  102. //15fps VGA YUV output
  103. // 24MHz input clock, 24MHz PCLK
  104. 0 : lut_data = {RW_CTRL,24'h3103_11}; // system clock from pad, bit[1]
  105. 1 : lut_data = {RW_CTRL,24'h3008_82}; // software reset, bit[7]
  106. 2 : lut_data = {RW_CTRL,24'h3008_42}; // software power down, bit[6]
  107. 3 : lut_data = {RW_CTRL,24'h3103_03}; // system clock from PLL, bit[1]
  108. 4 : lut_data = {RW_CTRL,24'h3017_ff}; // FREX, Vsync, HREF, PCLK, D[9:6] output enable
  109. 5 : lut_data = {RW_CTRL,24'h3018_ff}; // D[5:0], GPIO[1:0] output enable
  110. 6 : lut_data = {RW_CTRL,24'h3034_1a}; // MIPI 10-bit
  111. 7 : lut_data = {RW_CTRL,24'h3037_13}; // PLL root divider, bit[4], PLL pre-divider, bit[3:0]
  112. 8 : lut_data = {RW_CTRL,24'h3108_01}; // PCLK root divider, bit[5:4], SCLK2x root divider, bit[3:2]
  113. 9 : lut_data = {RW_CTRL,24'h3630_36};// SCLK root divider, bit[1:0]
  114. 10 : lut_data = {RW_CTRL,24'h3631_0e};
  115. 11 : lut_data = {RW_CTRL,24'h3632_e2};
  116. 12 : lut_data = {RW_CTRL,24'h3633_12};
  117. 13 : lut_data = {RW_CTRL,24'h3621_e0};
  118. 14 : lut_data = {RW_CTRL,24'h3704_a0};
  119. 15 : lut_data = {RW_CTRL,24'h3703_5a};
  120. 16 : lut_data = {RW_CTRL,24'h3715_78};
  121. 17 : lut_data = {RW_CTRL,24'h3717_01};
  122. 18 : lut_data = {RW_CTRL,24'h370b_60};
  123. 19 : lut_data = {RW_CTRL,24'h3705_1a};
  124. 20 : lut_data = {RW_CTRL,24'h3905_02};
  125. 21 : lut_data = {RW_CTRL,24'h3906_10};
  126. 22 : lut_data = {RW_CTRL,24'h3901_0a};
  127. 23 : lut_data = {RW_CTRL,24'h3731_12};
  128. 24 : lut_data = {RW_CTRL,24'h3600_08}; // VCM control
  129. 25 : lut_data = {RW_CTRL,24'h3601_33}; // VCM control
  130. 26 : lut_data = {RW_CTRL,24'h302d_60}; // system control
  131. 27 : lut_data = {RW_CTRL,24'h3620_52};
  132. 28 : lut_data = {RW_CTRL,24'h371b_20};
  133. 29 : lut_data = {RW_CTRL,24'h471c_50};
  134. 30 : lut_data = {RW_CTRL,24'h3a13_43}; // pre-gain = 1.047x
  135. 31 : lut_data = {RW_CTRL,24'h3a18_00}; // gain ceiling
  136. 32 : lut_data = {RW_CTRL,24'h3a19_f8}; // gain ceiling = 15.5x
  137. 33 : lut_data = {RW_CTRL,24'h3635_13};
  138. 34 : lut_data = {RW_CTRL,24'h3636_03};
  139. 35 : lut_data = {RW_CTRL,24'h3634_40};
  140. 36 : lut_data = {RW_CTRL,24'h3622_01};
  141. // 50/60Hz detection 50/60Hz 灯光条纹过滤
  142. 37 : lut_data = {RW_CTRL,24'h3c01_34}; // Band auto, bit[7]
  143. 38 : lut_data = {RW_CTRL,24'h3c04_28}; // threshold low sum
  144. 39 : lut_data = {RW_CTRL,24'h3c05_98}; // threshold high sum
  145. 40 : lut_data = {RW_CTRL,24'h3c06_00}; // light meter 1 threshold[15:8]
  146. 41 : lut_data = {RW_CTRL,24'h3c07_08}; // light meter 1 threshold[7:0]
  147. 42 : lut_data = {RW_CTRL,24'h3c08_00}; // light meter 2 threshold[15:8]
  148. 43 : lut_data = {RW_CTRL,24'h3c09_1c}; // light meter 2 threshold[7:0]
  149. 44 : lut_data = {RW_CTRL,24'h3c0a_9c}; // sample number[15:8]
  150. 45 : lut_data = {RW_CTRL,24'h3c0b_40}; // sample number[7:0]
  151. 46 : lut_data = {RW_CTRL,24'h3810_00}; // Timing Hoffset[11:8]
  152. 47 : lut_data = {RW_CTRL,24'h3811_10}; // Timing Hoffset[7:0]
  153. 48 : lut_data = {RW_CTRL,24'h3812_00}; // Timing Voffset[10:8]
  154. 49 : lut_data = {RW_CTRL,24'h3708_64};
  155. 50 : lut_data = {RW_CTRL,24'h4001_02}; // BLC start from line 2
  156. 51 : lut_data = {RW_CTRL,24'h4005_1a}; // BLC always update
  157. 52 : lut_data = {RW_CTRL,24'h3000_00}; // enable blocks
  158. 53 : lut_data = {RW_CTRL,24'h3004_ff}; // enable clocks
  159. 54 : lut_data = {RW_CTRL,24'h300e_58}; // MIPI power down, DVP enable
  160. 55 : lut_data = {RW_CTRL,24'h302e_00};
  161. 56 : lut_data = {RW_CTRL,24'h4300_61}; // RGB,
  162. 57 : lut_data = {RW_CTRL,24'h501f_01}; // ISP RGB
  163. 58 : lut_data = {RW_CTRL,24'h440e_00};
  164. 59 : lut_data = {RW_CTRL,24'h5000_a7}; // Lenc on, raw gamma on, BPC on, WPC on, CIP on
  165. // AEC target 自动曝光控制
  166. 60 : lut_data = {RW_CTRL,24'h3a0f_30}; // stable range in high
  167. 61 : lut_data = {RW_CTRL,24'h3a10_28}; // stable range in low
  168. 62 : lut_data = {RW_CTRL,24'h3a1b_30}; // stable range out high
  169. 63 : lut_data = {RW_CTRL,24'h3a1e_26}; // stable range out low
  170. 64 : lut_data = {RW_CTRL,24'h3a11_60}; // fast zone high
  171. 65 : lut_data = {RW_CTRL,24'h3a1f_14}; // fast zone low
  172. // Lens correction for ? 镜头补偿
  173. 66 : lut_data = {RW_CTRL,24'h5800_23};
  174. 67 : lut_data = {RW_CTRL,24'h5801_14};
  175. 68 : lut_data = {RW_CTRL,24'h5802_0f};
  176. 69 : lut_data = {RW_CTRL,24'h5803_0f};
  177. 70 : lut_data = {RW_CTRL,24'h5804_12};
  178. 71 : lut_data = {RW_CTRL,24'h5805_26};
  179. 72 : lut_data = {RW_CTRL,24'h5806_0c};
  180. 73 : lut_data = {RW_CTRL,24'h5807_08};
  181. 74 : lut_data = {RW_CTRL,24'h5808_05};
  182. 75 : lut_data = {RW_CTRL,24'h5809_05};
  183. 76 : lut_data = {RW_CTRL,24'h580a_08};
  184. 77 : lut_data = {RW_CTRL,24'h580b_0d};
  185. 78 : lut_data = {RW_CTRL,24'h580c_08};
  186. 79 : lut_data = {RW_CTRL,24'h580d_03};
  187. 80 : lut_data = {RW_CTRL,24'h580e_00};
  188. 81 : lut_data = {RW_CTRL,24'h580f_00};
  189. 82 : lut_data = {RW_CTRL,24'h5810_03};
  190. 83 : lut_data = {RW_CTRL,24'h5811_09};
  191. 84 : lut_data = {RW_CTRL,24'h5812_07};
  192. 85 : lut_data = {RW_CTRL,24'h5813_03};
  193. 86 : lut_data = {RW_CTRL,24'h5814_00};
  194. 87 : lut_data = {RW_CTRL,24'h5815_01};
  195. 88 : lut_data = {RW_CTRL,24'h5816_03};
  196. 89 : lut_data = {RW_CTRL,24'h5817_08};
  197. 90 : lut_data = {RW_CTRL,24'h5818_0d};
  198. 91 : lut_data = {RW_CTRL,24'h5819_08};
  199. 92 : lut_data = {RW_CTRL,24'h581a_05};
  200. 93 : lut_data = {RW_CTRL,24'h581b_06};
  201. 94 : lut_data = {RW_CTRL,24'h581c_08};
  202. 95 : lut_data = {RW_CTRL,24'h581d_0e};
  203. 96 : lut_data = {RW_CTRL,24'h581e_29};
  204. 97 : lut_data = {RW_CTRL,24'h581f_17};
  205. 98 : lut_data = {RW_CTRL,24'h5820_11};
  206. 99 : lut_data = {RW_CTRL,24'h5821_11};
  207. 100: lut_data = {RW_CTRL,24'h5822_15};
  208. 101: lut_data = {RW_CTRL,24'h5823_28};
  209. 102: lut_data = {RW_CTRL,24'h5824_46};
  210. 103: lut_data = {RW_CTRL,24'h5825_26};
  211. 104: lut_data = {RW_CTRL,24'h5826_08};
  212. 105: lut_data = {RW_CTRL,24'h5827_26};
  213. 106: lut_data = {RW_CTRL,24'h5828_64};
  214. 107: lut_data = {RW_CTRL,24'h5829_26};
  215. 108: lut_data = {RW_CTRL,24'h582a_24};
  216. 109: lut_data = {RW_CTRL,24'h582b_22};
  217. 110: lut_data = {RW_CTRL,24'h582c_24};
  218. 111: lut_data = {RW_CTRL,24'h582d_24};
  219. 112: lut_data = {RW_CTRL,24'h582e_06};
  220. 113: lut_data = {RW_CTRL,24'h582f_22};
  221. 114: lut_data = {RW_CTRL,24'h5830_40};
  222. 115: lut_data = {RW_CTRL,24'h5831_42};
  223. 116: lut_data = {RW_CTRL,24'h5832_24};
  224. 117: lut_data = {RW_CTRL,24'h5833_26};
  225. 118: lut_data = {RW_CTRL,24'h5834_24};
  226. 119: lut_data = {RW_CTRL,24'h5835_22};
  227. 120: lut_data = {RW_CTRL,24'h5836_22};
  228. 121: lut_data = {RW_CTRL,24'h5837_26};
  229. 122: lut_data = {RW_CTRL,24'h5838_44};
  230. 123: lut_data = {RW_CTRL,24'h5839_24};
  231. 124: lut_data = {RW_CTRL,24'h583a_26};
  232. 125: lut_data = {RW_CTRL,24'h583b_28};
  233. 126: lut_data = {RW_CTRL,24'h583c_42};
  234. 127: lut_data = {RW_CTRL,24'h583d_ce}; // lenc BR offset
  235. // AWB 自动白平衡
  236. 128: lut_data = {RW_CTRL,24'h5180_ff}; // AWB B block
  237. 129: lut_data = {RW_CTRL,24'h5181_f2}; // AWB control
  238. 130: lut_data = {RW_CTRL,24'h5182_00}; // [7:4] max local counter, [3:0] max fast counter
  239. 131: lut_data = {RW_CTRL,24'h5183_14}; // AWB advanced
  240. 132: lut_data = {RW_CTRL,24'h5184_25};
  241. 133: lut_data = {RW_CTRL,24'h5185_24};
  242. 134: lut_data = {RW_CTRL,24'h5186_09};
  243. 135: lut_data = {RW_CTRL,24'h5187_09};
  244. 136: lut_data = {RW_CTRL,24'h5188_09};
  245. 137: lut_data = {RW_CTRL,24'h5189_75};
  246. 138: lut_data = {RW_CTRL,24'h518a_54};
  247. 139: lut_data = {RW_CTRL,24'h518b_e0};
  248. 140: lut_data = {RW_CTRL,24'h518c_b2};
  249. 141: lut_data = {RW_CTRL,24'h518d_42};
  250. 142: lut_data = {RW_CTRL,24'h518e_3d};
  251. 143: lut_data = {RW_CTRL,24'h518f_56};
  252. 144: lut_data = {RW_CTRL,24'h5190_46};
  253. 145: lut_data = {RW_CTRL,24'h5191_f8}; // AWB top limit
  254. 146: lut_data = {RW_CTRL,24'h5192_04}; // AWB bottom limit
  255. 147: lut_data = {RW_CTRL,24'h5193_70}; // red limit
  256. 148: lut_data = {RW_CTRL,24'h5194_f0}; // green limit
  257. 149: lut_data = {RW_CTRL,24'h5195_f0}; // blue limit
  258. 150: lut_data = {RW_CTRL,24'h5196_03}; // AWB control
  259. 151: lut_data = {RW_CTRL,24'h5197_01}; // local limit
  260. 152: lut_data = {RW_CTRL,24'h5198_04};
  261. 153: lut_data = {RW_CTRL,24'h5199_12};
  262. 154: lut_data = {RW_CTRL,24'h519a_04};
  263. 155: lut_data = {RW_CTRL,24'h519b_00};
  264. 156: lut_data = {RW_CTRL,24'h519c_06};
  265. 157: lut_data = {RW_CTRL,24'h519d_82};
  266. 158: lut_data = {RW_CTRL,24'h519e_38}; // AWB control
  267. // Gamma 伽玛曲线
  268. 159: lut_data = {RW_CTRL,24'h5480_01}; // Gamma bias plus on, bit[0]
  269. 160: lut_data = {RW_CTRL,24'h5481_08};
  270. 161: lut_data = {RW_CTRL,24'h5482_14};
  271. 162: lut_data = {RW_CTRL,24'h5483_28};
  272. 163: lut_data = {RW_CTRL,24'h5484_51};
  273. 164: lut_data = {RW_CTRL,24'h5485_65};
  274. 165: lut_data = {RW_CTRL,24'h5486_71};
  275. 166: lut_data = {RW_CTRL,24'h5487_7d};
  276. 167: lut_data = {RW_CTRL,24'h5488_87};
  277. 168: lut_data = {RW_CTRL,24'h5489_91};
  278. 169: lut_data = {RW_CTRL,24'h548a_9a};
  279. 170: lut_data = {RW_CTRL,24'h548b_aa};
  280. 171: lut_data = {RW_CTRL,24'h548c_b8};
  281. 172: lut_data = {RW_CTRL,24'h548d_cd};
  282. 173: lut_data = {RW_CTRL,24'h548e_dd};
  283. 174: lut_data = {RW_CTRL,24'h548f_ea};
  284. 175: lut_data = {RW_CTRL,24'h5490_1d};
  285. // color matrix 色彩矩阵
  286. 176: lut_data = {RW_CTRL,24'h5381_1e}; // CMX1 for Y
  287. 177: lut_data = {RW_CTRL,24'h5382_5b}; // CMX2 for Y
  288. 178: lut_data = {RW_CTRL,24'h5383_08}; // CMX3 for Y
  289. 179: lut_data = {RW_CTRL,24'h5384_0a}; // CMX4 for U
  290. 180: lut_data = {RW_CTRL,24'h5385_7e}; // CMX5 for U
  291. 181: lut_data = {RW_CTRL,24'h5386_88}; // CMX6 for U
  292. 182: lut_data = {RW_CTRL,24'h5387_7c}; // CMX7 for V
  293. 183: lut_data = {RW_CTRL,24'h5388_6c}; // CMX8 for V
  294. 184: lut_data = {RW_CTRL,24'h5389_10}; // CMX9 for V
  295. 185: lut_data = {RW_CTRL,24'h538a_01}; // sign[9]
  296. 186: lut_data = {RW_CTRL,24'h538b_98}; // sign[8:1]
  297. // UV adjust UV 色彩饱和度调整
  298. 187: lut_data = {RW_CTRL,24'h5580_06}; // saturation on, bit[1]
  299. 188: lut_data = {RW_CTRL,24'h5583_40};
  300. 189: lut_data = {RW_CTRL,24'h5584_10};
  301. 190: lut_data = {RW_CTRL,24'h5589_10};
  302. 191: lut_data = {RW_CTRL,24'h558a_00};
  303. 192: lut_data = {RW_CTRL,24'h558b_f8};
  304. 193: lut_data = {RW_CTRL,24'h501d_40}; // enable manual offset of contrast
  305. // CIP 锐化和降噪
  306. 194: lut_data = {RW_CTRL,24'h5300_08}; // CIP sharpen MT threshold 1
  307. 195: lut_data = {RW_CTRL,24'h5301_30}; // CIP sharpen MT threshold 2
  308. 196: lut_data = {RW_CTRL,24'h5302_10}; // CIP sharpen MT offset 1
  309. 197: lut_data = {RW_CTRL,24'h5303_00}; // CIP sharpen MT offset 2
  310. 198: lut_data = {RW_CTRL,24'h5304_08}; // CIP DNS threshold 1
  311. 199: lut_data = {RW_CTRL,24'h5305_30}; // CIP DNS threshold 2
  312. 200: lut_data = {RW_CTRL,24'h5306_08}; // CIP DNS offset 1
  313. 201: lut_data = {RW_CTRL,24'h5307_16}; // CIP DNS offset 2
  314. 202: lut_data = {RW_CTRL,24'h5309_08}; // CIP sharpen TH threshold 1
  315. 203: lut_data = {RW_CTRL,24'h530a_30}; // CIP sharpen TH threshold 2
  316. 204: lut_data = {RW_CTRL,24'h530b_04}; // CIP sharpen TH offset 1
  317. 205: lut_data = {RW_CTRL,24'h530c_06}; // CIP sharpen TH offset 2
  318. 206: lut_data = {RW_CTRL,24'h5025_00};
  319. 207: lut_data = {RW_CTRL,24'h3008_02}; // wake up from standby, bit[6]
  320. // input clock 24Mhz, PCLK 84Mhz
  321. 208: lut_data = {RW_CTRL,24'h3035_21}; // PLL
  322. 209: lut_data = {RW_CTRL,24'h3036_69}; // PLL
  323. 210: lut_data = {RW_CTRL,24'h3c07_07}; // lightmeter 1 threshold[7:0]
  324. 211: lut_data = {RW_CTRL,24'h3820_47}; // flip
  325. 212: lut_data = {RW_CTRL,24'h3821_01}; // no mirror
  326. 213: lut_data = {RW_CTRL,24'h3814_31}; // timing X inc
  327. 214: lut_data = {RW_CTRL,24'h3815_31}; // timing Y inc
  328. 215: lut_data = {RW_CTRL,24'h3800_00}; // HS
  329. 216: lut_data = {RW_CTRL,24'h3801_00}; // HS
  330. 217: lut_data = {RW_CTRL,24'h3802_00}; // VS
  331. 218: lut_data = {RW_CTRL,24'h3803_fa}; // VS
  332. 219: lut_data = {RW_CTRL,24'h3804_0a}; // HW : lut_data = HE}
  333. 220: lut_data = {RW_CTRL,24'h3805_3f}; // HW : lut_data = HE}
  334. 221: lut_data = {RW_CTRL,24'h3806_06}; // VH : lut_data = VE}
  335. 222: lut_data = {RW_CTRL,24'h3807_a9}; // VH : lut_data = VE}
  336. 223: lut_data = {RW_CTRL,24'h3808_05}; // DVPHO 1280
  337. 224: lut_data = {RW_CTRL,24'h3809_00}; // DVPHO
  338. 225: lut_data = {RW_CTRL,24'h380a_02}; // DVPVO 720
  339. 226: lut_data = {RW_CTRL,24'h380b_d0}; // DVPVO
  340. 227: lut_data = {RW_CTRL,24'h380c_07}; // HTS
  341. 228: lut_data = {RW_CTRL,24'h380d_64}; // HTS
  342. 229: lut_data = {RW_CTRL,24'h380e_02}; // VTS
  343. 230: lut_data = {RW_CTRL,24'h380f_e4}; // VTS
  344. 231: lut_data = {RW_CTRL,24'h3813_04}; // timing V offset
  345. 232: lut_data = {RW_CTRL,24'h3618_00};
  346. 233: lut_data = {RW_CTRL,24'h3612_29};
  347. 234: lut_data = {RW_CTRL,24'h3709_52};
  348. 235: lut_data = {RW_CTRL,24'h370c_03};
  349. 236: lut_data = {RW_CTRL,24'h3a02_02}; // 60Hz max exposure
  350. 237: lut_data = {RW_CTRL,24'h3a03_e0}; // 60Hz max exposure
  351. 238: lut_data = {RW_CTRL,24'h3a14_02}; // 50Hz max exposure
  352. 239: lut_data = {RW_CTRL,24'h3a15_e0}; // 50Hz max exposure
  353. 240: lut_data = {RW_CTRL,24'h4004_02}; // BLC line number
  354. 241: lut_data = {RW_CTRL,24'h3002_1c}; // reset JFIFO, SFIFO, JPG
  355. 242: lut_data = {RW_CTRL,24'h3006_c3}; // disable clock of JPEG2x, JPEG
  356. 243: lut_data = {RW_CTRL,24'h4713_03}; // JPEG mode 3
  357. 244: lut_data = {RW_CTRL,24'h4407_04}; // Quantization scale
  358. 245: lut_data = {RW_CTRL,24'h460b_37};
  359. 246: lut_data = {RW_CTRL,24'h460c_20};
  360. 247: lut_data = {RW_CTRL,24'h4837_16}; // MIPI global timing
  361. 248: lut_data = {RW_CTRL,24'h3824_04}; // PCLK manual divider
  362. 249: lut_data = {RW_CTRL,24'h5001_83}; // SDE on, CMX on, AWB on
  363. 250: lut_data = {RW_CTRL,24'h3503_00}; // AEC/AGC on
  364. 251: lut_data = {RW_CTRL,24'h4740_20}; // VS 1
  365. //252: lut_data = {RW_CTRL,24'h503d_80}; // color bar 选择彩条输出
  366. //253: lut_data = {RW_CTRL,24'h4741_00}; //
  367. default : lut_data = 0;
  368. endcase
  369. end
  370. endmodule

 IIC端口模块

  1. //IIC端口模块
  2. `include "param.v"
  3. module i2c_itfc(
  4. input clk ,
  5. input rst_n ,
  6. input [4:0] cmd ,
  7. input [7:0] wr_din ,
  8. input sda_in ,
  9. output reg sda_en ,
  10. output reg sda_out ,
  11. output reg scl ,
  12. output reg [7:0]rd_out ,
  13. output reg rd_out_vld ,
  14. output reg done0 ,
  15. output reg ack
  16. );
  17. //高位先发msb
  18. parameter PAN=150,
  19. DOW_TIME=75,
  20. WR_TIME =15, //发送数据不管
  21. RD_TIME =90;//采集数据
  22. localparam IDLE = 7'b000_0001,
  23. START = 7'b000_0010,
  24. WRITE = 7'b000_0100,
  25. ACTACK = 7'b000_1000,
  26. READ = 7'b001_0000,
  27. SENDACK = 7'b010_0000,
  28. STOP = 7'b100_0000;
  29. reg [6:0] state;
  30. reg [6:0] state_next;
  31. wire idle_start ;
  32. wire start_write ;
  33. wire write_actack ;
  34. wire actack_start ;
  35. wire actack_write ;
  36. wire actack_read ;
  37. wire read_sendack ;
  38. wire sendack_read ;
  39. wire sendack_stop ;
  40. wire stop_idle ;
  41. wire actack_stop ;
  42. reg [15:0] max;
  43. reg [15:0] cnt_bit;
  44. wire add_cnt_bit;
  45. wire end_cnt_bit;
  46. reg [3:0] cnt_byte;
  47. wire add_cnt_byte;
  48. wire end_cnt_byte;
  49. reg [7:0] data_flag ; //接收数据暂存
  50. always@(posedge clk or negedge rst_n) begin
  51. if(!rst_n) begin
  52. state<=IDLE;
  53. end
  54. else begin
  55. state<=state_next;
  56. end
  57. end
  58. always@(*) begin
  59. case(state)
  60. IDLE : begin
  61. if(idle_start) begin
  62. state_next=START;
  63. end
  64. else begin
  65. state_next<=state;
  66. end
  67. end
  68. START: begin
  69. if(start_write) begin
  70. state_next=WRITE;
  71. end
  72. else begin
  73. state_next<=state;
  74. end
  75. end
  76. WRITE: begin
  77. if(write_actack) begin
  78. state_next=ACTACK;
  79. end
  80. else begin
  81. state_next<=state;
  82. end
  83. end
  84. ACTACK: begin
  85. if(actack_start) begin
  86. state_next=START;
  87. end
  88. else if(actack_write) begin
  89. state_next=WRITE;
  90. end
  91. else if(actack_read) begin
  92. state_next=READ;
  93. end
  94. else if(actack_stop) begin
  95. state_next=STOP;
  96. end
  97. else begin
  98. state_next<=state;
  99. end
  100. end
  101. READ : begin
  102. if(read_sendack) begin
  103. state_next=SENDACK;
  104. end
  105. else begin
  106. state_next<=state;
  107. end
  108. end
  109. SENDACK: begin
  110. if(sendack_stop) begin
  111. state_next=STOP;
  112. end
  113. else if(sendack_read) begin
  114. state_next=READ;
  115. end
  116. else begin
  117. state_next<=state;
  118. end
  119. end
  120. STOP : begin
  121. if(stop_idle) begin
  122. state_next=IDLE;
  123. end
  124. else begin
  125. state_next<=state;
  126. end
  127. end
  128. default:state_next<=IDLE;
  129. endcase
  130. end
  131. assign idle_start =state==IDLE && (cmd==`CMD_EN ) ; //开始工作
  132. assign start_write =state==START && (end_cnt_byte ) ;
  133. assign write_actack=state==WRITE && (end_cnt_byte ) ;
  134. assign actack_start=state==ACTACK && (cmd==`CMD_RDST &&end_cnt_byte ) ; //读数据的时候发起始位1次
  135. assign actack_write=state==ACTACK && (cmd==`CMD_WR &&end_cnt_byte ) ; //写数据
  136. assign actack_read =state==ACTACK && (cmd==`CMD_RD &&end_cnt_byte ) ; //接收数据
  137. assign actack_stop =state==ACTACK && ((cmd==`CMD_NO &&end_cnt_byte)||ack==1) ; //写完数据接发停止位 或者ack无应答
  138. assign read_sendack=state==READ && ( end_cnt_byte ) ;
  139. assign sendack_read=state==SENDACK&& ( end_cnt_byte ) ;
  140. assign sendack_stop=state==SENDACK&& (cmd==`CMD_NO &&end_cnt_byte ) ; //发停止位
  141. assign stop_idle =state==STOP && (end_cnt_byte ) ;
  142. //一个字节周期
  143. always@(posedge clk or negedge rst_n) begin
  144. if(!rst_n) begin
  145. cnt_bit<=0;
  146. end
  147. else if(end_cnt_bit) begin
  148. cnt_bit<=0;
  149. end
  150. else if(add_cnt_bit) begin
  151. cnt_bit<=cnt_bit+1'b1;
  152. end
  153. end
  154. assign add_cnt_bit=state!=IDLE;
  155. assign end_cnt_bit=add_cnt_bit && cnt_bit==PAN-1;
  156. //cnt_byte多少个字节周期
  157. always@(posedge clk or negedge rst_n) begin
  158. if(!rst_n) begin
  159. cnt_byte<=0;
  160. end
  161. else if(end_cnt_byte) begin
  162. cnt_byte<=0;
  163. end
  164. else if(add_cnt_byte) begin
  165. cnt_byte<=cnt_byte+1'b1;
  166. end
  167. end
  168. assign add_cnt_byte=state!=IDLE && end_cnt_bit;
  169. assign end_cnt_byte=add_cnt_byte && cnt_byte==max-1; //cnt_byte==MAX-1之后等下个周期add_cnt_byte到了才为零
  170. ///max
  171. always@( * ) begin
  172. if(!rst_n) begin
  173. max=0;
  174. end
  175. else begin
  176. case(state)
  177. START : max=1;
  178. WRITE : max=8;
  179. ACTACK : max=1;
  180. READ : max=8;
  181. SENDACK: max=1;
  182. STOP : max=1;
  183. default:max=0;
  184. endcase
  185. end
  186. end
  187. //scl
  188. always@(posedge clk or negedge rst_n) begin
  189. if(!rst_n) begin
  190. scl<=1;
  191. end
  192. else if( cnt_bit==DOW_TIME-1 ) begin //
  193. scl<=1;
  194. end
  195. else if( start_write|| ( (state==WRITE||state==READ||state==ACTACK||state==SENDACK)&&cnt_bit==PAN-1&&actack_stop==0 ) ) begin
  196. scl<=0; //数据传输状态scl先低电平再高电平
  197. end
  198. else if(state==START ||state==STOP) begin //起始状态,stop状态高电平
  199. scl<=1;
  200. end
  201. end
  202. //ack
  203. always@(posedge clk or negedge rst_n) begin
  204. if(!rst_n) begin
  205. ack<=0;
  206. end
  207. else if(state==ACTACK && cnt_bit==RD_TIME) begin
  208. ack<=sda_in; //发数据时,反馈ack是否应答
  209. end
  210. else if( stop_idle ) begin //一次数据发送结束,反馈一个信号
  211. ack<=1;
  212. end
  213. else begin
  214. ack<=0;
  215. end
  216. end
  217. //sda_en
  218. always@(posedge clk or negedge rst_n) begin
  219. if(!rst_n) begin
  220. sda_en<=1;
  221. end
  222. else if(actack_read||write_actack||sendack_read) begin //接收应答信号 和 读数据时候 为低电平
  223. sda_en<=0;
  224. end
  225. else if( read_sendack ||actack_start||actack_write||actack_stop) begin
  226. sda_en<=1;
  227. end
  228. end
  229. //sda_out
  230. always@(posedge clk or negedge rst_n) begin
  231. if(!rst_n) begin
  232. sda_out<=1; //空闲为1
  233. end
  234. else if(state==START&& cnt_bit==DOW_TIME ) begin //起始状态,sda由高拉低
  235. sda_out<=0;
  236. end
  237. else if(state==WRITE && cnt_bit==WR_TIME ) begin //写数据状态,scl低电平写数据
  238. sda_out<=wr_din[7-cnt_byte]; //高字节先发
  239. end
  240. else if(read_sendack&&cmd==`CMD_NO) begin //发送应答信号状态, NO_ACK
  241. sda_out<=1;
  242. end
  243. else if( read_sendack ) begin //发送应答信号状态,ACK
  244. sda_out<=0;
  245. end
  246. else if( actack_stop|| sendack_stop ) begin //停止状态先拉低
  247. sda_out<=0;
  248. end
  249. else if( state==STOP && cnt_bit==DOW_TIME ) begin //停止状态又由低拉高
  250. sda_out<=1;
  251. end
  252. end
  253. //sda_in data_flag
  254. always@(posedge clk or negedge rst_n) begin
  255. if(!rst_n) begin
  256. data_flag<=0;
  257. end
  258. else if(state==READ && cnt_bit==RD_TIME-1 ) begin
  259. data_flag[8-cnt_byte]<=sda_in;
  260. end
  261. end
  262. //done
  263. always@(posedge clk or negedge rst_n) begin
  264. if(!rst_n) begin
  265. done0<=0;
  266. end
  267. else if( ((state==ACTACK|| state==READ )&&cnt_bit==PAN-4 && cnt_byte==max-1)||stop_idle) begin
  268. //done信号提前3个周期给出去,或者状态结束(反馈到控制模块)
  269. done0<=1;
  270. end
  271. else begin
  272. done0<=0;
  273. end
  274. end
  275. //rd_out rd_out_vld
  276. always@(posedge clk or negedge rst_n) begin
  277. if(!rst_n) begin
  278. rd_out<=0;
  279. rd_out_vld<=0;
  280. end
  281. else if( state==READ &&cnt_bit==PAN-1 ) begin
  282. rd_out<=data_flag;
  283. rd_out_vld<=1;
  284. end
  285. else begin
  286. rd_out_vld<=0;
  287. end
  288. end
  289. endmodule

IIC控制模块

  1. //IIC控制模块
  2. `include "param.v"
  3. module sio_drive(
  4. input clk ,
  5. input rst_n ,
  6. output reg redy , //写数据进来要求。1代表空闲中,0代表工作中
  7. input data_en , //lut数据传输开始使能
  8. input [24:0] data_l , //lut数据模块
  9. output [7:0] dout , //读出的数据
  10. output dout_vld , //读出有效数据
  11. output reg no_ack , //无应答
  12. //端口模块
  13. output reg [4:0] cmd ,
  14. output reg [7:0] data_i2c , //传给端口模块数据
  15. input [7:0] i2c_din , //端口模块传回数据
  16. input i2c_din_vld ,
  17. input done , //上次数据传输完成标志
  18. input ack //端口模块
  19. );
  20. //
  21. parameter WR_NUM=3'd4, //读操作一共周期数
  22. RD_NUM=3'd5, //写操作一共周期数
  23. WR_ID =8'h78, //摄像头写ID
  24. RD_ID =8'h79; //摄像头读ID
  25. reg [2:0] cnt_byte ;
  26. wire add_cnt_byte ;
  27. wire end_cnt_byte ;
  28. reg [2:0] MAX ;
  29. wire rw_ctrl ;
  30. reg [23:0] data_lut ; //数据暂存
  31. reg wr_rd ;
  32. reg [1:0] per ;
  33. assign rw_ctrl = data_en ? data_l[24]:1'b0; //是写+读 或者只写
  34. always @(posedge clk or negedge rst_n)begin
  35. if(!rst_n)begin
  36. data_lut<=0;
  37. end
  38. else if(data_en)begin
  39. data_lut<=data_l[23:0] ;
  40. end
  41. end
  42. //wr_rd per
  43. always@(posedge clk or negedge rst_n) begin
  44. if(!rst_n) begin
  45. per<=0;
  46. wr_rd<=0; //0代表读,1代表写
  47. end
  48. else if( rw_ctrl==1 && data_en ) begin //写模式+读模式
  49. per<=2;
  50. wr_rd<=1;
  51. end
  52. else if(rw_ctrl==0 && data_en) begin //只写模式
  53. per<=1;
  54. wr_rd<=1;
  55. end
  56. else if(cnt_byte==MAX && ack==1) begin //ack只有一个周期
  57. per<=per-1'b1;
  58. wr_rd<=0; //读数据
  59. end
  60. end
  61. //redy
  62. always@(* ) begin
  63. if( per==0 ) begin //per==1 代表空闲状态
  64. redy=1'b1 ;
  65. end
  66. else begin
  67. redy=0 ;
  68. end
  69. end
  70. //no_ack
  71. always@(posedge clk or negedge rst_n) begin
  72. if(!rst_n) begin
  73. no_ack<=0;
  74. end
  75. else if(cnt_byte>0&&cnt_byte<MAX) begin
  76. no_ack<=ack;
  77. end
  78. else begin
  79. no_ack<=0;
  80. end
  81. end
  82. //cnt_byte
  83. always@(posedge clk or negedge rst_n) begin
  84. if(!rst_n) begin
  85. cnt_byte<=0;
  86. end
  87. else if(end_cnt_byte && ack==1) begin
  88. cnt_byte<=0;
  89. end
  90. else if(end_cnt_byte ) begin
  91. cnt_byte<=cnt_byte;
  92. end
  93. else if(add_cnt_byte) begin
  94. cnt_byte<=cnt_byte+1'b1;
  95. end
  96. end
  97. assign add_cnt_byte= done==1 ; //提前一个周期给反馈信号
  98. assign end_cnt_byte=(add_cnt_byte && cnt_byte==MAX)||no_ack ; //最后一个数据发完再接收一个done
  99. //MAX
  100. always@(posedge clk or negedge rst_n) begin
  101. if(!rst_n) begin
  102. MAX<=0;
  103. end
  104. else if(wr_rd==1 && cnt_byte==0) begin
  105. MAX<=WR_NUM ;
  106. end
  107. else if(wr_rd==0 && cnt_byte==0 ) begin
  108. MAX<=RD_NUM ;
  109. end
  110. end
  111. //输出给端口模块数据data_i2c
  112. always@(posedge clk or negedge rst_n) begin
  113. if(!rst_n) begin
  114. data_i2c<=0;
  115. cmd<=0;
  116. end
  117. else if( wr_rd==1 ) begin //write
  118. if( (per==1 ||per==2)&&cnt_byte==0 ) begin //写模式
  119. cmd<=`CMD_EN; //端口模块开始工作
  120. data_i2c<=WR_ID;
  121. end
  122. else
  123. case(cnt_byte)
  124. 1 :begin
  125. data_i2c<=data_lut[23:16];
  126. cmd<=`CMD_WR;
  127. end //地址
  128. 2 :begin
  129. data_i2c<=data_lut[15:8] ;
  130. cmd<=`CMD_WR;
  131. end //数据
  132. 3 :begin
  133. data_i2c<=data_lut[7:0] ;
  134. cmd<=`CMD_WR;
  135. end
  136. 4 :begin
  137. cmd<=`CMD_NO;
  138. end
  139. default:data_i2c<=0;
  140. endcase
  141. end
  142. else if( wr_rd==0 ) begin //read
  143. if( (per==1 ||per==2)&&cnt_byte==0 ) begin
  144. cmd<=`CMD_EN; //端口模块开始工作
  145. data_i2c<=WR_ID;
  146. end
  147. else
  148. case(cnt_byte)
  149. 1 :begin
  150. data_i2c<=data_lut[23:16];
  151. cmd<=`CMD_WR;
  152. end
  153. 2 :begin
  154. data_i2c<=data_lut[15:8];
  155. cmd<=`CMD_WR;
  156. end
  157. 3 :begin
  158. data_i2c<=RD_ID;
  159. cmd<=`CMD_RDST;
  160. end
  161. 4 :begin
  162. cmd<=`CMD_RD;
  163. end
  164. 5 :begin
  165. cmd<=`CMD_NO;
  166. end
  167. default:begin
  168. data_i2c<=0;
  169. cmd<=0;
  170. end
  171. endcase
  172. end
  173. end
  174. assign dout =i2c_din ;
  175. assign dout_vld=i2c_din_vld;
  176. endmodule

图像采集模块 

  1. //图像采集模块
  2. `include "param.v"
  3. module ov5640_capture(
  4. input clk ,
  5. input rst_n ,
  6. input href ,//行同步
  7. input vsync ,//帧同步
  8. input config_done , //配置模块完成
  9. input [7:0] din ,
  10. //输出
  11. output reg [15:0] dout , //信号与数据和数据有效 在时钟周期内是同步的,
  12. output reg dout_vld , //信号与数据和数据有效 在时钟周期内是同步的,
  13. output reg sop , //信号与数据和数据有效 在时钟周期内是同步的,包头
  14. output reg eop , //信号与数据和数据有效 在时钟周期内是同步的,包尾
  15. output reg [23:0] cnt_dout_vld
  16. );
  17. reg [11:0] cnt_col; //行计数器 2560
  18. wire add_cnt_col;
  19. wire end_cnt_col;
  20. reg [9:0] cnt_row; //场计数器 720
  21. wire add_cnt_row;
  22. wire end_cnt_row;
  23. reg vsync_r; //一帧的起点
  24. reg href_flag;
  25. reg dout_lvd_en;
  26. //帧起点同步
  27. always@(posedge clk or negedge rst_n) begin
  28. if(!rst_n) begin
  29. vsync_r<=0;
  30. end
  31. else if( vsync && config_done) begin //摄像头配置完成
  32. vsync_r<=1'b1 ;
  33. end
  34. else if(dout_vld) begin
  35. vsync_r<=0;
  36. end
  37. end
  38. always @(posedge clk or negedge rst_n)begin
  39. if(!rst_n)begin
  40. href_flag <= 0;
  41. end
  42. else if(dout_lvd_en) begin
  43. href_flag<=0;
  44. end
  45. else if( href )begin
  46. href_flag<=1'b1;
  47. end
  48. else begin
  49. href_flag<=0;
  50. end
  51. end
  52. //行计数
  53. always @(posedge clk or negedge rst_n)begin
  54. if(!rst_n)begin
  55. cnt_col <= 0;
  56. end
  57. else if(add_cnt_col)begin
  58. if(end_cnt_col)begin
  59. cnt_col <= 0;
  60. end
  61. else begin
  62. cnt_col <= cnt_col + 1'b1;
  63. end
  64. end
  65. end
  66. assign add_cnt_col = href_flag ;
  67. assign end_cnt_col = add_cnt_col && cnt_col ==`COL_MAX-1 ;//1280
  68. //场计数
  69. always @(posedge clk or negedge rst_n)begin
  70. if(!rst_n)begin
  71. cnt_row <= 0;
  72. end
  73. else if(add_cnt_row)begin
  74. if(end_cnt_row)begin
  75. cnt_row <= 0;
  76. end
  77. else begin
  78. cnt_row <= cnt_row + 1'b1;
  79. end
  80. end
  81. end
  82. assign add_cnt_row = end_cnt_col;
  83. assign end_cnt_row = add_cnt_row && cnt_row ==`ROW_MAX-1; //720
  84. always @(posedge clk or negedge rst_n)begin
  85. if(!rst_n) begin
  86. dout<=0;
  87. end
  88. else begin
  89. dout[15-cnt_col[0]*8 -:8] <= din;
  90. end
  91. end
  92. //dout_vld 数据晚一个周期
  93. always @(posedge clk or negedge rst_n)begin
  94. if(!rst_n) begin
  95. dout_vld<=0;
  96. end
  97. else if(add_cnt_col && cnt_col[0]==1)begin
  98. dout_vld<=1'b1;
  99. end
  100. else begin
  101. dout_vld<=0;
  102. end
  103. end
  104. //sop
  105. always @(posedge clk or negedge rst_n)begin
  106. if(!rst_n)begin
  107. sop <= 0;
  108. end
  109. else if( add_cnt_col && cnt_col[0]==1&& vsync_r )begin
  110. sop<=1'b1;
  111. end
  112. else begin
  113. sop<=0;
  114. end
  115. end
  116. always @(*)begin
  117. if(end_cnt_row)begin
  118. eop=1'b1;
  119. end
  120. else begin
  121. eop=1'b0;
  122. end
  123. end
  124. //可修改
  125. always @(posedge clk or negedge rst_n)begin
  126. if(!rst_n)begin
  127. dout_lvd_en <= 0;
  128. end
  129. else if(eop)begin
  130. dout_lvd_en<=1'b1;
  131. end
  132. else if( vsync )begin
  133. dout_lvd_en<=1'b0;
  134. end
  135. end
  136. //仿真测试用
  137. always@(posedge clk or negedge rst_n) begin
  138. if(!rst_n) begin
  139. cnt_dout_vld<=0;
  140. end
  141. else if(eop) begin
  142. cnt_dout_vld<=0;
  143. end
  144. else if( add_cnt_col && dout_vld==1'b1) begin
  145. cnt_dout_vld<=cnt_dout_vld+1'b1;
  146. end
  147. end
  148. endmodule

异步FIFO控制模块

        此模块采用FIFO18位宽:数据+sop+eop判断

  1. //异步FIFO处理跨时域问题,判断是否丢帧问题
  2. `include "param.v"
  3. //wrfifo 18
  4. //rdfifo 16
  5. module fifo_ctrl (
  6. input clk , //100m
  7. input rst_n ,
  8. input clk_in , //84m
  9. input clk_out , //75m
  10. //采集模块数据
  11. input [15:0] din_pixel ,
  12. input din_pixel_vld ,
  13. input sop ,
  14. input eop ,
  15. //vga模块
  16. input req_vga ,
  17. output reg[15:0] data_vga ,
  18. output reg data_vga_vld ,
  19. //wrfifo 读出给sdram数据
  20. output [11:0] wrfifo_rdusedw ,
  21. output [17:0] wrfifo_q ,
  22. input wrfifo_rdreq ,
  23. //rdfifo sdram写进数据
  24. input [15:0] rdfifo_data ,
  25. input rdfifo_wrreq ,
  26. output reg sop_vld , //一帧数据丢失,不能读wrfifo数据
  27. output [10:0] rdfifo_wrusedw ,
  28. output reg[23:0] cnt_num ,
  29. output reg[23:0] cnt_vld
  30. );
  31. //wrfifo
  32. reg [17:0] wrfifo_data ;
  33. //reg eop_vld ;
  34. reg fail ;
  35. reg wrfifo_wrreq ;
  36. wire wrfifo_wrfull ;
  37. //rdfifo
  38. wire rdfifo_rdempty ;
  39. wire [15:0] rdfifo_q ;
  40. wire rdfifo_rdreq ;
  41. reg rdreq_flag ;
  42. wire [11:0] wrfifo_wusedw ;
  43. reg sop_flag ;
  44. wire [17:0] wrfifo_qout ;//wrFIFO输出
  45. wrfifo u_wrfifo(
  46. .aclr (~rst_n ) ,
  47. .data (wrfifo_data ) ,
  48. .rdclk (clk ) ,
  49. .rdreq (rdreq_flag ) ,
  50. .wrclk (clk_in ) ,
  51. .wrreq (wrfifo_wrreq ) ,
  52. .q (wrfifo_qout ) ,
  53. .rdusedw (wrfifo_rdusedw ) ,
  54. .wrfull (wrfifo_wrfull ) ,
  55. .wrusedw (wrfifo_wusedw )
  56. );
  57. //*****************************************WRFIFO*******************************************//
  58. always @(posedge clk_in or negedge rst_n)begin
  59. if(!rst_n)begin
  60. wrfifo_data <= 0;
  61. end
  62. else begin
  63. wrfifo_data<={sop,eop,din_pixel} ;
  64. end
  65. end
  66. //sop_vld为1代表这一帧数据丢失
  67. always @(posedge clk or negedge rst_n)begin //写时钟下
  68. if(!rst_n)begin
  69. sop_vld<=1'b0;
  70. end
  71. else if( wrfifo_rdusedw>4050 )begin
  72. sop_vld <= 1'b1;
  73. end
  74. else if( wrfifo_qout[17] /* sop */) begin //写数据时钟
  75. sop_vld<=1'b0;
  76. end
  77. end
  78. always @( * )begin
  79. if(sop_vld )begin
  80. rdreq_flag=1'b1;
  81. end
  82. else begin
  83. rdreq_flag = wrfifo_rdreq;
  84. end
  85. end
  86. always @(posedge clk or negedge rst_n)begin
  87. if(!rst_n)begin
  88. cnt_num <= 0;
  89. end
  90. else if(wrfifo_qout[16]) begin
  91. cnt_num<=0;
  92. end
  93. else if(sop_vld==0 &&rdreq_flag )begin
  94. cnt_num<=cnt_num+1'b1;
  95. end
  96. end
  97. assign wrfifo_q=(sop_vld==0)?wrfifo_qout:0;
  98. always @(posedge clk_in or negedge rst_n)begin
  99. if(!rst_n)begin
  100. sop_flag <= 0;
  101. end
  102. else if(sop==1'b1)begin
  103. sop_flag<=1'b1;
  104. end
  105. else if(eop)begin
  106. sop_flag <= 0;
  107. end
  108. end
  109. always @(posedge clk_in or negedge rst_n)begin
  110. if(!rst_n)begin
  111. wrfifo_wrreq <= 0;
  112. end
  113. else if(wrfifo_wrfull==1'b0)begin
  114. wrfifo_wrreq<=(sop_flag&& din_pixel_vld )||sop ;
  115. end
  116. end
  117. //tb测试用
  118. always @(posedge clk_in or negedge rst_n)begin
  119. if(!rst_n)begin
  120. cnt_vld <= 0;
  121. end
  122. else if(sop_flag==0) begin
  123. cnt_vld<=0;
  124. end
  125. else if(wrfifo_wrreq)begin
  126. cnt_vld<=cnt_vld+1'b1 ;
  127. end
  128. end
  129. //************************rdfifo****************************************//
  130. rdfifo u_rdfifo(
  131. .aclr (~rst_n ) ,
  132. .data (rdfifo_data ) ,
  133. .rdclk (clk_out ) ,
  134. .rdreq (rdfifo_rdreq ) ,
  135. .wrclk (clk ) ,
  136. .wrreq (rdfifo_wrreq ) ,
  137. .q (rdfifo_q ) ,
  138. .rdempty (rdfifo_rdempty ) ,
  139. .wrusedw (rdfifo_wrusedw )
  140. );
  141. //data_vga
  142. //data_vga_vld
  143. always@(posedge clk_out or negedge rst_n) begin
  144. if(!rst_n) begin
  145. data_vga<=0;
  146. data_vga_vld<=0;
  147. end
  148. else begin
  149. data_vga<=rdfifo_q;
  150. data_vga_vld<=rdfifo_rdreq;
  151. end
  152. end
  153. assign rdfifo_rdreq= rdfifo_rdempty==1'b0 ? req_vga : 1'b0 ;
  154. endmodule

SDRAM控制模块

  1. SDRAM控制模块
  2. `include "param.v"
  3. module sdram_ctrl (
  4. input clk ,
  5. input rst_n ,
  6. //wrfifo
  7. input [1:0] wrfifo_seop ,
  8. input [11:0] wrfifo_rdusedw ,
  9. input sop_vld ,
  10. //rdfifo
  11. input [10:0] rdfifo_wrusedw ,
  12. output reg [15:0] dout_fifo ,
  13. output reg dout_fifo_vld ,
  14. //接收端口模块数据
  15. input [2:0] done ,
  16. input [15:0] din_ctrl ,
  17. input din_ctrl_vld ,
  18. //传给端口模块
  19. output reg [23:0] addr_iftc ,
  20. output reg wr_en_out ,
  21. output reg rd_en_out ,
  22. output reg sop ,
  23. output reg eop
  24. );
  25. //状态参数
  26. localparam IDLE =5'b0000_1,
  27. ITFCEN=5'b0001_0,
  28. ADDR =5'b0010_0,
  29. WRITE =5'b0100_0,
  30. READ =5'b1000_0;
  31. reg [4:0] state;
  32. reg [4:0] state_next;
  33. wire idle_itfcen;
  34. wire itfcen_addr;
  35. wire idle_addr ;
  36. wire addr_write;
  37. wire addr_read ;
  38. wire write_idle;
  39. wire read_idle ;
  40. //信号参数
  41. wire [15:0] din ;
  42. reg wr_en ;
  43. reg rd_en ;
  44. reg [21:0] addr_wr;
  45. wire add_addr_wr;
  46. wire end_addr_wr;
  47. reg [21:0] addr_rd;
  48. wire add_addr_rd;
  49. wire end_addr_rd;
  50. reg flag ;
  51. reg [1:0] wr_bank ;
  52. reg [1:0] rd_bank ;
  53. reg seop ;
  54. reg bank_turn ;//bank翻转记录
  55. //打拍
  56. reg sop_flag;
  57. wire nedge;
  58. wire pedge;
  59. reg sop_vld_r0;
  60. reg sop_vld_r1;
  61. //********************************sop+打拍***************************************8/
  62. always @(posedge clk or negedge rst_n)begin
  63. if(!rst_n)begin
  64. sop<=0;
  65. eop<=0;
  66. end
  67. else if(state==WRITE||write_idle) begin
  68. eop<=wrfifo_seop[0];
  69. sop<=0;
  70. end
  71. else if(addr_write ) begin
  72. sop<=wrfifo_seop[1];
  73. eop<=0;
  74. end
  75. else begin
  76. sop<=0;
  77. eop<=0;
  78. end
  79. end
  80. //**************************状态机**********************************************/
  81. always @(posedge clk or negedge rst_n)begin
  82. if(!rst_n)begin
  83. state <= IDLE;
  84. end
  85. else begin
  86. state <= state_next;
  87. end
  88. end
  89. always @(*)begin
  90. case(state)
  91. IDLE :begin
  92. if(idle_itfcen) begin
  93. state_next=ITFCEN;
  94. end
  95. else begin
  96. state_next=state;
  97. end
  98. end
  99. ITFCEN :begin
  100. if(itfcen_addr) begin
  101. state_next=ADDR;
  102. end
  103. else begin
  104. state_next=state;
  105. end
  106. end
  107. ADDR: begin
  108. if(addr_write) begin
  109. state_next=WRITE;
  110. end
  111. else if(addr_read) begin
  112. state_next=READ;
  113. end
  114. else begin
  115. state_next=state;
  116. end
  117. end
  118. WRITE:begin
  119. if(write_idle) begin
  120. state_next=IDLE;
  121. end
  122. else begin
  123. state_next=state;
  124. end
  125. end
  126. READ :begin
  127. if(read_idle) begin
  128. state_next=IDLE;
  129. end
  130. else begin
  131. state_next=state;
  132. end
  133. end
  134. default:state_next=IDLE;
  135. endcase
  136. end
  137. assign idle_itfcen =state==IDLE && (wr_en ||rd_en ); //en必须只有一个周期
  138. assign itfcen_addr =state==ITFCEN &&(rd_en_out||wr_en_out) ;//仲裁后,判断读写
  139. assign addr_write=state==ADDR && (flag==1'b1 ); //提示下一周期给数据
  140. assign addr_read =state==ADDR && (flag==1'b0 );//读,给一次地址就行
  141. assign write_idle=state==WRITE && (done[2]==1'b0 );//提示下一周期停止给数据
  142. assign read_idle =state==READ && (done[2]==1'b0 );//done[2]代表一次突发完成
  143. //****************************地址*****************************************/
  144. always @(posedge clk or negedge rst_n)begin
  145. if(!rst_n)begin
  146. addr_wr <=1'b0;
  147. end
  148. else if(add_addr_wr)begin
  149. if(end_addr_wr)begin
  150. addr_wr <=1'b0;
  151. end
  152. else begin
  153. addr_wr <= addr_wr + `BUSRT_MAX;
  154. end
  155. end
  156. end
  157. assign add_addr_wr = write_idle; //突发完后再加一次
  158. assign end_addr_wr = add_addr_wr && addr_wr ==`FPS-`BUSRT_MAX ; //一帧像素-突发长度1800-1
  159. always @(posedge clk or negedge rst_n)begin
  160. if(!rst_n)begin
  161. addr_rd <=1'b0;
  162. end
  163. else if(add_addr_rd)begin
  164. if(end_addr_rd)begin
  165. addr_rd <=1'b0;
  166. end
  167. else begin
  168. addr_rd <= addr_rd + `BUSRT_MAX;
  169. end
  170. end
  171. end
  172. assign add_addr_rd = read_idle;
  173. assign end_addr_rd = add_addr_rd && addr_rd == `FPS-`BUSRT_MAX ;
  174. //*******************************************seop***************************************//
  175. ///
  176. always @(posedge clk or negedge rst_n)begin
  177. if(!rst_n)begin
  178. seop <= 1'b1;
  179. end
  180. else if( end_addr_wr )begin
  181. seop <=1'b0;
  182. end
  183. else if(bank_turn==0 ) begin //seop突发写标志,1才能写。0 不能写
  184. seop <= 1'b1;
  185. end
  186. end
  187. // rd_bank, wr_bank, bank_turn状态 写模式翻转记录
  188. always @(posedge clk or negedge rst_n)begin
  189. if(!rst_n)begin
  190. wr_bank <= 2'b00;
  191. rd_bank <=2'b11;
  192. bank_turn<=1'b0; //状态翻转记录 0代表已经翻转,可以写。1代表还未翻转等待翻转中
  193. end
  194. else if( seop==0 && end_addr_rd )begin
  195. wr_bank <=~wr_bank;
  196. rd_bank <=~rd_bank;
  197. bank_turn<=1'b0;
  198. end
  199. else if( seop==1'b1 && wr_en ) begin
  200. bank_turn<=1'b1; //翻转后
  201. end
  202. end
  203. //bank_flag 第一个bank写完标志
  204. //*****************************突发信号******************************/
  205. always @(posedge clk or negedge rst_n)begin
  206. if(!rst_n)begin
  207. sop_vld_r0 <=1'b0;
  208. sop_vld_r1 <=1'b0;
  209. end
  210. else begin //
  211. sop_vld_r0 <=sop_vld;
  212. sop_vld_r1 <=sop_vld_r0;
  213. end
  214. end
  215. assign pedge=sop_vld_r0&& ~sop_vld_r1;
  216. assign nedge=~sop_vld_r0&& sop_vld_r1;
  217. always @(posedge clk or negedge rst_n)begin
  218. if(!rst_n)begin
  219. sop_flag <=1'b0;
  220. end
  221. else if(pedge) begin
  222. sop_flag<=1'b1;
  223. end
  224. else if(nedge) begin
  225. sop_flag<=1'b0;
  226. end
  227. end
  228. always @(posedge clk or negedge rst_n)begin
  229. if(!rst_n)begin
  230. wr_en <=1'b0;
  231. end
  232. else if(idle_itfcen) begin
  233. wr_en<=1'b0;
  234. end
  235. else if( (wrfifo_rdusedw >=`BUSRT_MAX-1) && seop==1'b1 && state==IDLE && sop_flag==0 )begin
  236. wr_en<=1'b1; //代表一次突发写
  237. end
  238. end
  239. //rd_en//代表一次突发读
  240. always @(posedge clk or negedge rst_n)begin
  241. if(!rst_n)begin
  242. rd_en <=1'b0;
  243. end
  244. else if(idle_itfcen) begin
  245. rd_en <=1'b0;
  246. end
  247. else if(/*rd_flag && */rdfifo_wrusedw<`FIFO_L && state==IDLE )begin //读数据,rdfifo数据量小于300,且端口模块空闲中
  248. rd_en<=1'b1;
  249. end
  250. else if(rdfifo_wrusedw>`FIFO_H) begin //读数据,rdfifo数据量大于1600,
  251. rd_en<=1'b0;
  252. end
  253. end
  254. //读写仲裁标志
  255. always @(posedge clk or negedge rst_n)begin
  256. if(!rst_n)begin
  257. flag <=1'b0;
  258. end
  259. else if(wr_en&&rd_en &&state==IDLE) begin // 同时接到读请求、写请求.
  260. flag<=~flag;
  261. end
  262. else if(wr_en)begin //突发一次写,
  263. flag<=1'b1;
  264. end
  265. else if(rd_en)begin //突发一次读
  266. flag<=1'b0;
  267. end
  268. end
  269. //wr_en_out 传给端口模块的读写使能信号
  270. //rd_en_out
  271. always @(posedge clk or negedge rst_n)begin
  272. if(!rst_n)begin
  273. wr_en_out <=0 ;
  274. rd_en_out <=0 ;
  275. end
  276. else if( (wr_en_out||rd_en_out)&&state==ITFCEN) begin
  277. wr_en_out <=0 ;
  278. rd_en_out <=0 ;
  279. end
  280. else if( state==ITFCEN)begin
  281. wr_en_out <=flag ;
  282. rd_en_out <=~flag ;
  283. end
  284. else begin
  285. wr_en_out <=0 ;
  286. rd_en_out <=0 ;
  287. end
  288. end
  289. //**************************输出*********************************************/
  290. //addr_iftc
  291. always @(posedge clk or negedge rst_n)begin
  292. if(!rst_n)begin
  293. addr_iftc <= 0;
  294. end
  295. else if(flag==1'b0)begin
  296. addr_iftc <= {rd_bank,addr_rd};
  297. end
  298. else begin
  299. addr_iftc <= {wr_bank,addr_wr};
  300. end
  301. end
  302. //输出 时序
  303. always @(posedge clk or negedge rst_n)begin
  304. if(!rst_n)begin
  305. dout_fifo <= 0;
  306. dout_fifo_vld<=0;
  307. end
  308. else begin
  309. dout_fifo <= din_ctrl;
  310. dout_fifo_vld<=din_ctrl_vld;
  311. end
  312. end
  313. endmodule

SDRAM端口模块

  1. SDRAM端口模块
  2. `include "param.v"
  3. module sdram_itfc(
  4. input clk ,
  5. input rst_n ,
  6. input wr_en , //写使能 .同时地址数据有效
  7. input rd_en , //读使能
  8. input [23:0] addr , //12个地址加2个bank地址
  9. input [15:0] dout_sdram ,
  10. output reg dout_sdram_req ,
  11. output sclk ,
  12. output reg cke ,
  13. output cs_n , //除时钟外,使能型号
  14. output ras_n , //
  15. output cas_n , //
  16. output we_n , //
  17. output reg[1:0] ba_addr , //bank地址
  18. output reg[12:0] sdram_addr , //输进sdram地址
  19. //DQM mask
  20. output reg[1:0] dqm_out ,
  21. inout [15:0] dq ,
  22. //接控制模块
  23. output reg[2:0] done , //反馈信号。地址反馈 及一个数据写完了反馈
  24. output reg[15:0] data_ctrl ,
  25. output reg data_ctrl_vld
  26. );
  27. localparam WAIT =8'b0000_0001, //上电等待20us
  28. PRECH=8'b0000_0010,//预充电
  29. AREF =8'b0000_0100,//刷新
  30. MRS =8'b0000_1000,//模式设置
  31. IDLE =8'b0001_0000,//
  32. ACTI =8'b0010_0000,//bank+row激活 bank,block都是内部划分块名
  33. WRITE=8'b0100_0000,//bank+列激活+写
  34. READ =8'b1000_0000;//bank+列激活+
  35. reg [3:0] cmd;
  36. reg [7:0] state;
  37. reg [7:0] state_next;
  38. wire wait_prech ;
  39. wire prech_aref ;
  40. wire prech_idle ;
  41. wire aref_mrs ;
  42. wire aref_idle ;
  43. wire mrs_idle ;
  44. wire idle_aref ;
  45. wire idle_acti ;
  46. wire acti_write ;
  47. wire acti_read ;
  48. wire write_prech;
  49. wire read_prech ;
  50. reg [15:0] cnt0;
  51. wire add_cnt0;
  52. wire end_cnt0;
  53. reg [9:0] cnt_ref;
  54. reg ref_flag;
  55. reg [15:0] max; //每个状态cnt0计数最大值
  56. reg flag; //PRECH标志信号
  57. reg wrrd_flag;
  58. reg data_vld_r0; //CL为2的条件下
  59. reg data_vld_r1;
  60. reg data_vld_r2; //列延时为3的情况下选
  61. wire [1:0] bank;
  62. wire [12:0] row ;
  63. wire [8:0] col ;
  64. reg work;
  65. wire [15:0] dq_in ;
  66. reg [15:0] dq_out ;
  67. reg dq_en ;
  68. assign dq_in=dq;
  69. assign dq=dq_en?dq_out:16'bz;
  70. assign bank=addr[23:22];
  71. assign row =addr[21:9] ;
  72. assign col =addr[8:0] ;
  73. always@(posedge clk or negedge rst_n ) begin
  74. if(!rst_n) begin
  75. state<=WAIT;
  76. end
  77. else begin
  78. state<=state_next;
  79. end
  80. end
  81. always@(*) begin
  82. case(state)
  83. WAIT :begin
  84. if(wait_prech) begin
  85. state_next=PRECH;
  86. end
  87. else begin
  88. state_next=state;
  89. end
  90. end
  91. PRECH :begin
  92. if( prech_aref) begin
  93. state_next=AREF;
  94. end
  95. else if(prech_idle) begin
  96. state_next=IDLE;
  97. end
  98. else begin
  99. state_next=state;
  100. end
  101. end
  102. AREF :begin
  103. if(aref_mrs) begin
  104. state_next=MRS;
  105. end
  106. else if(aref_idle) begin
  107. state_next=IDLE;
  108. end
  109. else begin
  110. state_next=state;
  111. end
  112. end
  113. MRS :begin
  114. if(mrs_idle) begin
  115. state_next=IDLE;
  116. end
  117. else begin
  118. state_next=state;
  119. end
  120. end
  121. IDLE :begin
  122. if(idle_aref) begin//优先
  123. state_next=AREF;
  124. end
  125. else if(idle_acti) begin
  126. state_next=ACTI;
  127. end
  128. else begin
  129. state_next=state;
  130. end
  131. end
  132. ACTI :begin
  133. if(acti_write) begin
  134. state_next=WRITE;
  135. end
  136. else if(acti_read) begin
  137. state_next=READ;
  138. end
  139. else begin
  140. state_next=state;
  141. end
  142. end
  143. WRITE :begin
  144. if(write_prech) begin
  145. state_next=PRECH;
  146. end
  147. else begin
  148. state_next=state;
  149. end
  150. end
  151. READ :begin
  152. if(read_prech) begin
  153. state_next=PRECH;
  154. end
  155. else begin
  156. state_next=state;
  157. end
  158. end
  159. default:state_next=IDLE;
  160. endcase
  161. end
  162. assign wait_prech = state== WAIT && ( end_cnt0 );
  163. assign prech_aref = state== PRECH && ( flag==0 && end_cnt0 );
  164. assign prech_idle = state== PRECH && ( flag==1 && end_cnt0 );
  165. assign aref_mrs = state== AREF && ( flag==0 && end_cnt0 );
  166. assign aref_idle = state== AREF && ( flag==1 && end_cnt0 );
  167. assign mrs_idle = state== MRS && ( end_cnt0 );
  168. assign idle_aref = state== IDLE && ( ref_flag==1 );
  169. assign idle_acti = state== IDLE && ( work &&ref_flag==0 ); //ref_flag==1,done就不能发出信号,en就不能为1
  170. assign acti_write = state== ACTI && ( wrrd_flag==0 && end_cnt0 );
  171. assign acti_read = state== ACTI && ( wrrd_flag==1 && end_cnt0 );
  172. assign write_prech = state== WRITE && ( end_cnt0 ); //数据写完后还要延迟2个clk
  173. assign read_prech = state== READ && ( end_cnt0 ); //数据读完都可以立即发下一命令
  174. //cnt_max
  175. always@( * ) begin
  176. case(state)
  177. WAIT : max =`TIME_WAIT ; //20us
  178. PRECH : max =`TIME_TRP ; //预充电20ns
  179. AREF : max =`TIME_TRC ; //刷新70ns
  180. MRS : max =`TIME_TMRS ; //模式寄存器2clk
  181. IDLE : max = 0 ; //
  182. ACTI : max =`TIME_TRCD ; //激活行20ns//2
  183. WRITE : max =(`BUSRT_MAX+2) ; //突发长度完+2clk恢复周期
  184. READ : max = `BUSRT_MAX ; //突发长度+0clk
  185. default:max =0;
  186. endcase
  187. end
  188. always@(posedge clk or negedge rst_n) begin
  189. if(!rst_n) begin
  190. cnt0<=0;
  191. end
  192. else if(end_cnt0) begin
  193. cnt0<=0;
  194. end
  195. else if(add_cnt0) begin
  196. cnt0<=cnt0+1'b1;
  197. end
  198. end
  199. assign add_cnt0=state!=IDLE ;
  200. assign end_cnt0=add_cnt0 && cnt0==max-1;
  201. //flag //预充电下一状态标志//开机到idle后才开始计数
  202. always@(posedge clk or negedge rst_n) begin
  203. if(!rst_n) begin
  204. flag<=0;
  205. end
  206. else if(mrs_idle) begin
  207. flag<=1; //第一次模式寄存器标志
  208. end
  209. end
  210. //cnt_ref; //定时刷新标志
  211. //ref_flag;
  212. always@(posedge clk or negedge rst_n) begin
  213. if(!rst_n) begin
  214. cnt_ref<=0;
  215. end
  216. else if(cnt_ref==`TIME_REF-1) begin //780周期
  217. cnt_ref<=1;
  218. end
  219. else if( flag ) begin
  220. cnt_ref<=cnt_ref+1'b1;
  221. end
  222. end
  223. //刷新标志
  224. always@(posedge clk or negedge rst_n) begin
  225. if(!rst_n) begin
  226. ref_flag<=0;
  227. end
  228. else if(cnt_ref==`TIME_REF-1) begin //780周期
  229. ref_flag<=1;
  230. end
  231. else if(state==AREF) begin
  232. ref_flag<=0;
  233. end
  234. end
  235. //wrrd_flag //读或者写标志
  236. always@(posedge clk or negedge rst_n) begin
  237. if(!rst_n) begin
  238. wrrd_flag<=0;
  239. end
  240. else if(wr_en) begin //读写标志信号
  241. wrrd_flag<=0;
  242. end
  243. else if(rd_en) begin
  244. wrrd_flag<=1;
  245. end
  246. end
  247. always @(posedge clk or negedge rst_n)begin
  248. if(!rst_n)begin
  249. work <= 0;
  250. end
  251. else if(state==ACTI)begin
  252. work <= 0;
  253. end
  254. else if( wr_en||rd_en )begin
  255. work<=1'b1;
  256. end
  257. end
  258. //命令cmd
  259. assign cs_n = cmd[3] ;
  260. assign ras_n= cmd[2] ;
  261. assign cas_n= cmd[1] ;
  262. assign we_n = cmd[0] ;
  263. always@(posedge clk or negedge rst_n) begin
  264. if(!rst_n) begin
  265. cmd<=4'b1111;
  266. end
  267. else if(wait_prech) begin //预充电 0010 同时外加 地址a10 为1
  268. cmd<=`CMD_PREC; //3
  269. end
  270. else if(prech_aref) begin //刷新0001
  271. cmd<=`CMD_AREF; //7
  272. end
  273. else if(aref_mrs) begin //模式寄存器0000
  274. cmd<=`CMD_MRS; //2
  275. end
  276. else if(idle_aref) begin //刷新0001
  277. cmd<=`CMD_AREF; //7
  278. end
  279. else if(idle_acti) begin //激活行0011
  280. cmd<=`CMD_ACTI; //3
  281. end
  282. else if(acti_write) begin //写 0100
  283. cmd<=`CMD_WRITE;
  284. end
  285. else if(acti_read) begin //读 0101
  286. cmd<=`CMD_RDAD;
  287. end
  288. else if(read_prech||write_prech) begin //预充电0010
  289. cmd<=`CMD_PREC; //同时外加 地址a10 为1
  290. end
  291. else begin //空命令
  292. cmd<=`CMD_NOP;
  293. end
  294. end
  295. // sclk
  296. //cke
  297. always@(posedge clk or negedge rst_n) begin
  298. if(!rst_n) begin
  299. cke<=0;
  300. end
  301. else begin
  302. cke<=1;
  303. end
  304. end
  305. assign sclk=~clk;//~sclk延迟半个周期
  306. //ba_addr
  307. //sdram_addr
  308. always@(posedge clk or negedge rst_n) begin
  309. if(!rst_n) begin
  310. ba_addr <= 2'b00;
  311. sdram_addr<= 13'b0;
  312. end
  313. else if(wait_prech||write_prech||read_prech) begin //预充电模式
  314. sdram_addr<=13'd1024; //a101,所有预充电所有,不需要bank地址
  315. end
  316. else if(aref_mrs) begin
  317. ba_addr <= 2'b00;
  318. sdram_addr<={ 3'b000 ,`OP , 2'b00 , `CAS_LTY , `BT , `BL}; //模式寄存器
  319. end
  320. else if(idle_acti) begin //激活
  321. ba_addr <= bank;//bank
  322. sdram_addr<=row; //行地址
  323. end
  324. else if(acti_write||acti_read) begin
  325. ba_addr <= bank;//bank
  326. sdram_addr<= col; //列地址
  327. end
  328. end
  329. //done反馈信号
  330. always@(*) begin
  331. if(state!=IDLE||ref_flag ||work==1'b1 ) begin //780周期计数
  332. done=3'b100 ; //正在工作中 ,不能给读写命令
  333. end
  334. else begin
  335. done=3'b000;
  336. end
  337. end
  338. //写数据
  339. //dout_sdram_req
  340. always@( posedge clk or negedge rst_n ) begin
  341. if(!rst_n) begin
  342. dout_sdram_req<=0;
  343. end
  344. else if(state==WRITE && cnt0==max-4) begin
  345. dout_sdram_req<=0; //提示下下个周期停止给写数据,数据时序输出,打一拍
  346. end
  347. else if(state== ACTI&&wrrd_flag==0 && add_cnt0 && cnt0==max-2) begin
  348. dout_sdram_req<=1'b1; //提示下下个周期给写数据+列地址,数据时序输出,打一拍
  349. end
  350. end
  351. always@( posedge clk or negedge rst_n ) begin
  352. if(!rst_n) begin
  353. dq_out<=0;
  354. end
  355. else begin
  356. dq_out<=dout_sdram;
  357. end
  358. end
  359. //读数据
  360. always@(posedge clk or negedge rst_n) begin
  361. if(!rst_n) begin
  362. data_vld_r0<=0;
  363. end
  364. else if(read_prech) begin
  365. data_vld_r0<=0;
  366. end
  367. else if( acti_read ) begin
  368. data_vld_r0<=1; //突发写 ,经过CL列延迟个周期后,出数据
  369. end
  370. end
  371. //组合输出
  372. always@(*) begin
  373. if(!rst_n) begin
  374. data_ctrl=0;
  375. end
  376. else begin
  377. data_ctrl=dq_in;
  378. end
  379. end
  380. always@(posedge clk or negedge rst_n) begin
  381. if(!rst_n) begin
  382. data_ctrl_vld <=0;
  383. data_vld_r1<=0;
  384. end
  385. else begin
  386. data_vld_r1<=data_vld_r0;
  387. //data_vld_r2<=data_vld_r1; //列延时为3的情况下选
  388. data_ctrl_vld<=data_vld_r1;
  389. end
  390. end
  391. // dq_en /只在写的状态下拉高
  392. always@(posedge clk or negedge rst_n) begin
  393. if(!rst_n) begin
  394. dq_en<=0;
  395. end
  396. else if(acti_write) begin
  397. dq_en<=1;
  398. end
  399. else if(state==WRITE&&cnt0==max-3 ) begin
  400. dq_en<=0;
  401. end
  402. end
  403. always@(posedge clk or negedge rst_n) begin
  404. if(!rst_n) begin
  405. dqm_out<=0;
  406. end
  407. else if(state==WRITE&&cnt0==max-3 ) begin //写后要拉高dqm_out
  408. dqm_out<=2'b11;
  409. end
  410. else if(state!=WRITE) begin
  411. dqm_out<=0;
  412. end
  413. end
  414. endmodule

VGA显示模块

  1. VGA显示模块
  2. `include "param.v"
  3. module vga_itfc(
  4. input clk ,
  5. input rst_n ,
  6. input [15:0] din ,
  7. input din_vld , //数据有效
  8. output reg req ,//请求数据信号
  9. output reg [15:0]dout_rgb,
  10. output reg hsync ,
  11. output reg vhync
  12. );
  13. reg [11:0] cnt_h; //行计数器
  14. wire add_cnt_h;
  15. wire end_cnt_h;
  16. reg [9:0] cnt_v; //场计数器
  17. wire add_cnt_v;
  18. wire end_cnt_v;
  19. reg h_vld ; //行有效数据
  20. reg v_vld ; //场有效数据
  21. reg rdreq ;
  22. wire wrreq ;
  23. wire empty ;
  24. wire full ;
  25. wire [15:0] q ;
  26. wire [9:0] usedw ;
  27. // cnt_h
  28. always @(posedge clk or negedge rst_n)begin
  29. if(!rst_n)begin
  30. cnt_h <= 0;
  31. end
  32. else if(add_cnt_h)begin
  33. if(end_cnt_h)begin
  34. cnt_h <= 0;
  35. end
  36. else begin
  37. cnt_h <= cnt_h + 1'b1;
  38. end
  39. end
  40. end
  41. assign add_cnt_h = 1'b1; //上电即开始
  42. assign end_cnt_h = add_cnt_h && cnt_h ==`H_TP-1 ; //1650
  43. always @(posedge clk or negedge rst_n)begin
  44. if(!rst_n)begin
  45. cnt_v <= 0;
  46. end
  47. else if(add_cnt_v)begin
  48. if(end_cnt_v)begin
  49. cnt_v <= 0;
  50. end
  51. else begin
  52. cnt_v <= cnt_v + 1'b1;
  53. end
  54. end
  55. end
  56. assign add_cnt_v = end_cnt_h;
  57. assign end_cnt_v = add_cnt_v && cnt_v == `V_TP-1; //750
  58. //h_vld行有效数据
  59. always @(posedge clk or negedge rst_n)begin
  60. if(!rst_n)begin
  61. h_vld <= 0;
  62. end
  63. else if(add_cnt_h && cnt_h==(`H_SW+`H_BP-1) )begin //
  64. h_vld<=1'b1;
  65. end
  66. else if(add_cnt_h&&cnt_h== (`H_SW +`H_BP +`H_AP-1) )begin
  67. h_vld<=0;
  68. end
  69. end
  70. //v_vld
  71. always @(posedge clk or negedge rst_n)begin
  72. if(!rst_n)begin
  73. v_vld <= 0;
  74. end
  75. else if(add_cnt_v &&cnt_v== (`V_SW +`V_BP-1 ) )begin
  76. v_vld<=1'b1;
  77. end
  78. else if(add_cnt_v && cnt_v==(`V_SW +`V_BP +`V_AP-1) )begin
  79. v_vld<=0;
  80. end
  81. end
  82. //rdreq
  83. always @( * )begin
  84. if( v_vld && h_vld && empty==0 )begin
  85. rdreq=1'b1;
  86. end
  87. else begin
  88. rdreq=0;
  89. end
  90. end
  91. //dout_rgb
  92. always @(* )begin
  93. if(!rst_n)begin
  94. dout_rgb = 0;
  95. end
  96. else if( rdreq )begin
  97. dout_rgb=q;
  98. end
  99. else begin
  100. dout_rgb=0;
  101. end
  102. end
  103. //hsync
  104. always @(posedge clk or negedge rst_n)begin
  105. if(!rst_n)begin
  106. hsync <= 0;
  107. end
  108. else if( add_cnt_h && cnt_h== `H_SW-1 )begin
  109. hsync<=1'b1;
  110. end
  111. else if(end_cnt_h)begin
  112. hsync<=0;
  113. end
  114. end
  115. //vhync
  116. always @(posedge clk or negedge rst_n)begin
  117. if(!rst_n)begin
  118. vhync <= 0;
  119. end
  120. else if( add_cnt_v && cnt_v== `V_SW-1 )begin
  121. vhync<=1'b1;
  122. end
  123. else if(end_cnt_v)begin
  124. vhync<=0;
  125. end
  126. end
  127. buffer u_buffer(
  128. .clock ( clk ) ,
  129. .data ( din ) ,
  130. .rdreq ( rdreq ) ,
  131. .wrreq ( wrreq ) ,
  132. .empty ( empty ) ,
  133. .full ( full ) ,
  134. .q ( q ) ,
  135. .usedw ( usedw )
  136. );
  137. //req向sdram读数据
  138. always @(posedge clk or negedge rst_n)begin
  139. if(!rst_n)begin
  140. req <= 0;
  141. end
  142. else if( usedw<200 )begin
  143. req<=1'b1;
  144. end
  145. else if(usedw>900)begin
  146. req<=0;
  147. end
  148. end
  149. assign wrreq= (full==0) ? din_vld : 1'b0 ;
  150. endmodule

参数模块

  1. /**************************************sdram************************************/
  2. //sdram工作参数
  3. //`define BUSRT_1
  4. //`define BUSRT_2
  5. //`define BUSRT_4
  6. //`define BUSRT_8
  7. `define BUSRT_512 //突发长度
  8. `ifdef BUSRT_1
  9. `define BUSRT_MAX 1
  10. `define BL 3'b000 //A0-A2
  11. `elsif BUSRT_2
  12. `define BUSRT_MAX 2
  13. `define BL 3'b001
  14. `elsif BUSRT_4
  15. `define BUSRT_MAX 4
  16. `define BL 3'b010
  17. `elsif BUSRT_8
  18. `define BUSRT_MAX 8
  19. `define BL 3'b011
  20. `define FIFO_L 300 //写FIFO的数量低值
  21. `define FIFO_H 1500 //写FIFO的数量高值
  22. `elsif BUSRT_512
  23. `define BUSRT_MAX 512
  24. `define BL 3'b111
  25. `define FIFO_L 300 //写FIFO的数量低值
  26. `define FIFO_H 1500 //写FIFO的数量高值
  27. `endif
  28. //连续突发
  29. //`define BT 1 //A3
  30. `define BT 1'b0
  31. //突发写/单写
  32. //`define OP 1
  33. `define OP 1'b0 //A9
  34. `define CAS_LTY1 //列选 延迟
  35. //`define CAS_LTY2
  36. `ifdef CAS_LTY1 //列选通延迟设置 延迟 A4-A6
  37. `define CAS_LTY 3'b010
  38. `define CL 2
  39. `elsif CAS_LTY2
  40. `define CAS_LTY 3'b011
  41. `define CL 3
  42. `endif
  43. `define ADDR_MAX 16777215
  44. //时间参数
  45. `define TIME_TRC 7 //刷新命令生效时间
  46. `define TIME_TRP 3 //预充电时间
  47. `define TIME_TMRS 2 //2个clk时钟周期 模式寄存器
  48. `define TIME_WAIT 20000 //上电等待20us
  49. `define TIME_TRCD 3 //激活命令
  50. `define TIME_REF 780 //自动刷新间隔
  51. //cmd命令参数 cs_n使能,ras_n行选,cas_n列选,we_n写使能
  52. `define CMD_WRITE 4'b0100 //
  53. `define CMD_RDAD 4'b0101 //读
  54. `define CMD_ACTI 4'b0011 //激活
  55. `define CMD_NOP 4'b0111 //空操作
  56. `define CMD_MRS 4'b0000 //模式寄存器
  57. `define CMD_AREF 4'b0001 //自刷新 A10==1
  58. `define CMD_PREC 4'b0010 //预充电 所有bank
  59. /**************************************图像采集模块************************************/
  60. `define ROW_MAX 720 //一共720
  61. `define COL_MAX 2560 //一行1280个像素,一个像素2字节
  62. `define FPS 921600 //一帧数据有多少个数据 9216
  63. `define BUSRT_NUM 1800 //突发1800次,一帧数据完
  64. /**************************************vga端口模块************************************/
  65. //vga端口模块 1280*720像素
  66. `define H_FP 110 //行前沿
  67. `define H_SW 40 //行同步脉冲
  68. `define H_BP 220 //行后沿
  69. `define H_AP 1280 //行有效像素
  70. `define H_TP 1650 //行总时序
  71. `define V_FP 5 //场前沿
  72. `define V_SW 5 //场同步脉冲
  73. `define V_BP 20 //场后沿
  74. `define V_AP 720 //场有效像素
  75. `define V_TP 750 //场总时序
  76. /**************************************I2C端口模块************************************/
  77. //I2C端口模块
  78. `define CMD_EN 5'b000_01 //[0]表示为开始工作
  79. `define CMD_RDST 5'b000_10 //[1]表示发起始位
  80. `define CMD_WR 5'b001_00 //[2] 表示写数据
  81. `define CMD_RD 5'b010_00 //[3]表示接收数据
  82. `define CMD_NO 5'b100_00 //[4] 表示发送停止位不应答

备注:fifo_ctrl模块中调用了两个FIFO深度为1024,宽度一个为18bit(包含sop,eop),一个16bit;

VGA显示模块调用FIFO深度为1024,宽度为16bit;

另外调用pll生成时钟24M(摄像头配置输输出时钟)、75M(VGA显示模块输出时钟)、100M(SDRAM时钟)

工程代码:https://download.csdn.net/download/wyong0306/88728960

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

闽ICP备14008679号