I8253f.v
上传用户:xuqufe
上传日期:2022-08-10
资源大小:2378k
文件大小:14k
源码类别:

VHDL/FPGA/Verilog

开发平台:

VHDL

  1. module I8253f(datain, dataout, gate0, gate1, gate2, reset, CS, RD, WR, A1, A0, clk0, clk1, clk2, clk_out, cnt0, en);
  2. input gate0, gate1, gate2;
  3. input reset, CS, RD, WR;
  4. input A1, A0;
  5. input clk0, clk1, clk2;
  6. input[7:0] datain;
  7. output[2:0] clk_out;
  8. output en;
  9. output[7:0] dataout;
  10. output[15:0]cnt0;
  11. reg[2:0] clk_out; //计数器输出
  12. reg[7:0] dataout;
  13. reg[7:0] cmd; //输入指令
  14. reg[5:0] cmd0, cmd1, cmd2; //各个计数器输入指令
  15. reg[15:0] set0, set1, set2; //装入计数初值的寄存器
  16. reg[15:0] lock; //锁存用计数器
  17. reg write0, write1, write2, read0, read1, read2;
  18. wire all_set0, all_gate0, all_set1, all_gate1, all_set2, all_gate2, reg1a; //所有的置数和门控信号
  19. reg[1:0]  wlh0, rlh0, wlh1, rlh1, wlh2, rlh2; //记录操作输入顺序
  20. wire edge0a, edge1a, edge2a, start0, start1, start2, reg0, reg2; //标志信号
  21. reg reg0a, reg2a, edge0, edge1, edge2;
  22. wire dataoutall; //标志信号
  23. wire[4:0] cbus; //控制信号
  24. reg[15:0] cnt0, cnt1, cnt2; //计数器
  25. wire[15:0] buffer; //缓冲器
  26. reg wreset1, rreset1, wover2, rover2, wreset2, rreset2, wover0, rover0, wreset0, rreset0, wover1, rover1, reg1;
  27. //write 信号表示对计数器输入寄存器的写操作   
  28. //read  信号表示对计数器输出寄存器的读操作
  29. //wover 信号表示写操作结束 
  30. //rover 信号表示读操作结束
  31. //wreset 清空输入寄存器
  32. //rreset 清空输出寄存器
  33. assign cbus = {CS, RD, WR, A1, A0};
  34. // 对计数器0的设置
  35. assign all_set0 = (write0 && (cmd0[3:1] == 3'b000)) ||  // 方式0
  36.   (edge0 && (cmd0[3:1] == 3'b001)) ||  // 方式1
  37.   (((buffer == 0) || ~gate0) && cmd0[3:2] == 3'b01) || // 方式2或3
  38.   ((write0 || ~gate0) && cmd0[3:1] == 3'b100) ||  // 方式4
  39.   (((start0 && ~write0) || edge0) && cmd0[3:1] == 3'b101) || reset; // 方式5
  40. assign all_gate0 = (gate0 && cnt0 != 16'h0000 && cmd0[3:1] == 3'b000) ||  // 方式0
  41.    (cnt0 != 16'h0000 && cmd0[3:1] == 3'b001) ||  // 方式1
  42.    (gate0 && cmd0[3:1] == 3'b010) ||  // 方式2
  43.    (gate0 && cmd0[3:1] == 3'b011) ||  // 方式3
  44.    (gate0 && cnt0 != 16'h0000 && cmd0[3:1] == 3'b100) ||  // 方式4
  45.    (cnt0 != 16'h0000 && cmd0[3:1] == 3'b101); // 方式5
  46. // 对计数器1的设置
  47. assign all_set1 = (write1 && (cmd1[3:1] == 3'b000)) ||  // 方式0
  48.   (~edge1 && (cmd1[3:1] == 3'b001)) ||  // 方式1
  49.   (((cnt1 == 16'h0000) || ~gate1) && cmd1[3:1] == 3'b010) ||  // 方式2
  50.   (((cnt1 == 16'h0000) || ~gate1) && cmd1[3:1] == 3'b011) ||  // 方式3
  51.   ((start1 || edge1) && cmd1[3:1] == 3'b100) ||  // 方式4
  52.   ((start1 || edge1) && cmd1[3:1] == 3'b101) || reset; // 方式5
  53. assign all_gate1 = (gate1 && cnt1 != 16'h0000 && cmd1[3:1] == 3'b000) ||  // 方式0
  54.    (cnt1 != 16'h0000 && cmd1[3:1] == 3'b001) ||  // 方式1
  55.    (gate1 && cnt1 != 16'h0000 && cmd1[3:1] == 3'b010) ||  // 方式2
  56.    (gate1 && cmd1[3:1] == 3'b011) ||  // 方式3
  57.    (gate1 && cnt1 != 16'h0000 && cmd1[3:1] == 3'b100) ||  // 方式4
  58.    (cnt1 != 16'h0000 && cmd1[3:1] == 3'b101); // 方式5
  59. // 对计数器2的设置
  60. assign all_set2 = (write2 && (cmd2[3:1] == 3'b000)) || // 方式0  
  61.      (~edge2 && (cmd2[3:1] == 3'b001)) ||  // 方式1
  62.   (((cnt2 == 16'h0000) || ~gate2) && cmd2[3:1] == 3'b010) ||  // 方式2
  63.   (((cnt2 == 16'h0000) || ~gate2) && cmd2[3:1] == 3'b011) ||  // 方式3
  64.   ((start2 || edge2) && cmd2[3:1] == 3'b100) ||  // 方式4
  65.   ((start2 || edge2) && cmd2[3:1] == 3'b101) || reset; // 方式5
  66. assign all_gate2 = (gate2 && cnt2 != 16'h0000 && cmd2[3:1] == 3'b000) ||  // 方式0
  67.   (cnt2 != 16'h0000 && cmd2[3:1] == 3'b001) ||  // 方式1
  68.   (gate2 && cnt2 == 16'h0000 && cmd2[3:1] == 3'b010) ||  // 方式2
  69.   (gate2 && cmd2[3:1] == 3'b011) ||  // 方式3
  70.   (gate2 && cnt2 != 16'h0000 && cmd2[3:1] == 3'b100) ||  // 方式4
  71.   (cnt2 != 16'h0000 && cmd2[3:1] == 3'b101); // 方式5
  72. // 读操作发生
  73. assign en = (read0 || read1 || read2);
  74. assign start1 = (cnt1 == 16'h0000 || ~gate1) ? (reg1 ? 1 : write1) : 0;
  75. assign reg1a = start1 & ~write1;
  76. // 门控信号为高,且计数到了设置的初始值
  77. assign edge1a = (gate1 && cnt1 == set1);
  78. assign buffer = (cnt0 != buffer || write0) ? cnt0 : buffer;
  79. assign start0 = (buffer == 16'h0000 || ~gate0) ? (reg0 ? 1 : write0) : 0;
  80. assign reg0 =  (start0 && ~write0) ? 0 : reg0a;
  81. assign edge0a = (gate0 && cnt0 == set0);
  82. assign start2 = (cnt2 == 16'h0000 || ~gate2) ? (reg2 ? 1 : write2) : 0;
  83. assign reg2 =  (start2 && ~write2) ? 0 : reg2a;
  84. assign edge2a = (gate2 && cnt2 == set2);
  85. assign dataoutall = cmd0[5] == 1'b1 || cmd0[5:4] == 2'b01 || 
  86.    cmd1[5] == 1'b1 || cmd1[5:4] == 2'b01 || 
  87.    cmd2[5] == 1'b1 || cmd2[5:4] == 2'b01;
  88. // 是否其他所有的信号都应该清零呢???疑惑!!!
  89. always @(cbus)
  90. begin
  91. case(cbus)
  92. 5'b01000 : write0 <= 1;  //加载T/C0
  93.          5'b01001 : 
  94. begin
  95. write1 <= 1;  //加载T/C1
  96. write0 <= 0;
  97. end
  98.         5'b01010 : 
  99. begin
  100. write2 <= 1;  //加载T/C2
  101. write0 <= 0;
  102. end
  103. 5'b01011 : 
  104. begin
  105. cmd <= datain; //向控制寄存器写方式控制字
  106. write0 <= 0;
  107. end
  108.          5'b00100 : 
  109. begin
  110. read0 <= 1;  //读T/C0
  111. write0 <= 0;
  112. end
  113.          5'b00101 : 
  114. begin
  115. read1 <= 1;  //读T/C1
  116. write0 <= 0; 
  117. end
  118.          5'b00110 : 
  119. begin
  120. read2 <= 1;  //读T/C2
  121. write0 <= 0;
  122. end
  123.          default : 
  124. begin
  125. write0 <= 0; 
  126. write1 <= 0; 
  127. write2 <= 0; 
  128. read0 <= 0; 
  129. read1 <= 0; 
  130. read2 <= 0; 
  131. end
  132. endcase
  133. end
  134. always @(cmd) // 输入控制字
  135. begin
  136. case(cmd)
  137. 8'b00000000 : 
  138. lock <= cnt0; //锁存counter0,方式0,2进制计数
  139. 8'b01000000 : 
  140. lock <= cnt1; //锁存counter1,方式0,2进制计数
  141. 8'b10000000 : 
  142. lock <= cnt2; //锁存counter2,方式0,2进制计数
  143. default : 
  144. begin
  145. if(cmd[7:6] == 2'b00 && cmd[5:4] != 2'b00)
  146. cmd0 <= cmd[5:0]; //counter0命令
  147. if(cmd[7:6] == 2'b01 && cmd[5:4] != 2'b00)
  148. cmd1 <= cmd[5:0]; //counter1命令
  149. if(cmd[7:6] == 2'b10 && cmd[5:4] != 2'b00)
  150. cmd2 <= cmd[5:0]; //counter2命令
  151. end
  152. endcase
  153. end
  154. // 1号计数器
  155. always @(posedge write1 or posedge reg1a) // 置reg信号
  156. begin
  157. if(reg1a)
  158. reg1 <= 0;
  159. else if(cnt1 != 16'h0000 && cmd1[3:2] == 2'b10) // 方式4和5
  160. reg1 <= 1;
  161. end
  162. always @(posedge gate1 or posedge edge1a) // 置edge信号
  163. begin
  164. if(edge1a)
  165. edge1 <= 0;
  166. else if(cmd1[2:1] == 2'b01 || cmd1[3:1] == 3'b100) // 方式1或方式5或方式4下
  167. edge1 <= 1;
  168. end
  169. always @(posedge write1 or posedge wreset1) // 置wlh信号
  170. begin
  171. if(wreset1)
  172. wlh1 <= 2'b00;
  173. else if(wlh1 == 2'b10)
  174. wlh1 <= 2'b01;
  175. else
  176. wlh1 <= wlh1 + 1;
  177. end
  178. always @(posedge read1 or posedge rreset1) //置rlh信号
  179. begin
  180. if(rreset1)
  181. rlh1 <= 2'b00;
  182. else if(rlh1 == 2'b10)
  183. rlh1 <= 2'b01;
  184. else
  185. rlh1 <= rlh1 + 1;
  186. end
  187. always @(negedge clk1 or posedge all_set1) // 计数器1计数工作
  188. begin
  189. if(all_set1)
  190. cnt1 <= set1;
  191. else if(all_gate1)
  192. cnt1 <= cnt1 - 1;
  193. end
  194. always @(cmd1[3:1])
  195. begin
  196. case(cmd1[3:1])
  197. 3'b000 : clk_out[1] <= (cnt1 == 16'h0000) ? 1 : 0; //0方式输出
  198. 3'b001 : clk_out[1] <= (cnt1 == 16'h0000) ? 1 : 0; //1方式输出
  199. 3'b010 : clk_out[1] <= (cnt1 == 16'h0001) ? 0 : 1; //2方式输出
  200. 3'b011 : clk_out[1] <= (cnt1 < {1'b0, set1[14:0]}) ? 1 : 0; //3方式输出
  201. 3'b100 : clk_out[1] <= (cnt1 == 16'h0001) ? 0 : 1; //4方式输出
  202. 3'b101 : clk_out[1] <= (cnt1 == 16'h0001) ? 0 : 1;  //5方式输出
  203. endcase
  204. end
  205. //0号计数器
  206. always @(posedge write0)
  207. begin
  208. if(cnt0 != 16'h0000 && cmd0[3:2] == 2'b10) // 0号计数器,方式4和5
  209. reg0a <= 1;
  210. end
  211. always @(posedge gate0 or posedge edge0a)
  212. begin
  213. if(edge0a)
  214. edge0 <= 0;
  215. else if(cmd0[2:1] == 2'b01 || cmd0[3:1] == 3'b100) // 0号计数器,方式1,4,5
  216. edge0 <= 1;
  217. end
  218. always @(posedge write0 or posedge wreset0)
  219. begin
  220. if(wreset0)
  221. wlh0 <= 2'b00;
  222. else if(wlh0 == 2'b10)
  223. wlh0 <= 2'b01;
  224. else
  225. wlh0 <= wlh0 + 1;
  226. end
  227. always @(posedge read0 or posedge rreset0)
  228. begin
  229. if(rreset0)
  230. rlh0 <= 2'b00;
  231. else if(rlh0 == 2'b10)
  232. rlh0 <= 2'b01;
  233. else
  234. rlh0 <= rlh0 + 1;
  235. end
  236. always @(negedge clk0 or posedge all_set0) // 计数工作
  237. begin
  238. if(all_set0)
  239. cnt0 <= set0;
  240. else if(all_gate0)
  241. cnt0 <= cnt0 - 1;
  242. end
  243. always @(cmd0[3:1])
  244. begin
  245. case(cmd0[3:1])
  246. 3'b000 : clk_out[0] <= (cnt0 != 16'h0000) ? 0 : 1;
  247. 3'b001 : clk_out[0] <= (cnt0 == 16'h0000) ? 1 : 0;
  248. 3'b010 : clk_out[0] <= (cnt0 == 16'h0001) ? 0 : 1;
  249. 3'b011 : clk_out[0] <= cnt0 < ((set0[11:0] >> 1) + 1) ? 1 : 0;
  250. 3'b100 : clk_out[0] <= (cnt0 == 16'h0001) ? 0 : 1;
  251. 3'b101 : clk_out[0] <= (cnt0 == 16'h0001) ? 0 : 1;
  252. endcase
  253. end
  254. //2号计数器
  255. always @(posedge write2)
  256. begin
  257. if(cnt2 != 16'h0000 && cmd2[3:2] == 2'b10) // 方式4和5
  258. reg2a <= 1;
  259. end
  260. always @(posedge gate2 or posedge edge2a)
  261. begin
  262. if(edge2a)
  263. edge2 <= 0;
  264. else if(cmd2[2:1] == 2'b01 || cmd2[3:1] == 3'b100) // 方式1,4或5
  265. edge2 <= 1;
  266. end
  267. always @(posedge write2 or posedge wreset2)
  268. begin
  269. if(wreset2)
  270. wlh2 <= 2'b00;
  271. else if(wlh2 == 2'b10)
  272. wlh2 <= 2'b01;
  273. else
  274. wlh2 <= wlh2 + 1;
  275. end
  276. always @(posedge read2 or posedge rreset2)
  277. begin
  278. if(rreset2)
  279. rlh2 <= 2'b00;
  280. else if(rlh2 == 2'b10)
  281. rlh2 <= 2'b01;
  282. else
  283. rlh2 <= rlh2 + 1;
  284. end
  285. always @(negedge clk2 or posedge all_set2) // 计数器工作
  286. begin
  287. if(all_set2)
  288. cnt2 <= set2;
  289. else if(all_gate2)
  290. cnt2 <= cnt2 - 1;
  291. end
  292. always @(cmd2[3:1])
  293. begin
  294. case(cmd2[3:1])
  295. 3'b000 : clk_out[2] <= (cnt2 == 16'h0000) ? 1 : 0;
  296. 3'b001 : clk_out[2] <= (cnt2 == 16'h0000) ? 0 : 1;
  297. 3'b010 : clk_out[2] <= (cnt2 == 16'h0001) ? 0 : 1;
  298. 3'b011 : clk_out[2] <= (cnt2 < {1'b0, set2[14:0]}) ? 1 : 0;
  299. 3'b100 : clk_out[2] <= (cnt2 == 16'h0001) ? 0 : 1;
  300. 3'b101 : clk_out[2] <= (cnt2 == 16'h0001) ? 0 : 1;
  301. endcase
  302. end
  303. // 读写操作
  304. always @(dataoutall)
  305. begin
  306. // 0号计数器
  307. if(write0)
  308. begin
  309. case(cmd0[5:4])
  310. 2'b01 : 
  311. begin
  312. set0[7:0] <= datain;  // 写低字节
  313. set0[15:8] <= 8'h00; 
  314. wover0 <= 1;
  315. end
  316. 2'b10 : 
  317. begin
  318. set0[15:8] <= datain;  // 写高字节
  319. wover0 <= 1;
  320. end
  321. 2'b11 :  // 写两个字节
  322. begin
  323. if(wlh0 == 2'b01)
  324. set0[7:0] <= datain;    // 先低
  325. else if(wlh0 == 2'b10)
  326. begin
  327. set0[15:8] <= datain; 
  328. wover0 <= 1;
  329. end // 后高
  330. end
  331. endcase
  332. end
  333. else if(wover0) // 写操作结束
  334. begin
  335. wreset0 <= 1;
  336. wover0 <= 0;
  337. end
  338. else 
  339. wreset0 <= 0;
  340. // 1号计数器
  341. if(write1)
  342. begin
  343. case(cmd1[5:4])
  344. 2'b01 :  // 只读/写计数器低字节
  345. begin
  346. set1[7:0] <= datain; 
  347. set1[15:8] <= 0; 
  348. wover1 <= 1;
  349. end
  350. 2'b10 :  // 只读/写计数器高字节
  351. begin
  352. set1[15:8] <= datain; 
  353. wover1 <= 1;
  354. end
  355. 2'b11 :  // 先读/写计数器低字节、后读写计数器高字节
  356. begin
  357. if(wlh1 == 2'b01)
  358. set1[7:0] <= datain;
  359. else if(wlh1 == 2'b10)
  360. begin
  361. set1[15:8] <= datain; 
  362. wover1 <= 1;
  363. end
  364. end
  365. endcase
  366. end
  367. else if(wover1)
  368. begin
  369. wreset1 <= 1;
  370. wover1 <= 0;
  371. end
  372. else 
  373. wreset1 <= 0;
  374. // 2号计数器
  375. if(write2)
  376. begin
  377. case(cmd2[5:4])
  378. 2'b01 : 
  379. begin
  380. set2[7:0] <= datain; 
  381. set2[15:8] <= 0;
  382. wover2 <= 1;
  383. end
  384. 2'b10 : 
  385. begin
  386. set2[15:8] <= datain; 
  387. wover2 <= 1;
  388. end
  389. 2'b11 : 
  390. begin
  391. if(wlh2 == 2'b01)
  392. set2[7:0] <= datain;
  393. else if(wlh2 == 2'b10)
  394. begin
  395. set2[15:8] <= datain; 
  396. wover2 <= 1;
  397. end
  398. end
  399. endcase
  400. end
  401. else if(wover2)
  402. begin
  403. wreset2 <= 1;
  404. wover2 <= 0;
  405. end
  406. else 
  407. wreset2 <= 0;
  408. //0号计数器
  409. if(read0)
  410. begin
  411. case(cmd0[5:4])
  412. 2'b01 : 
  413. begin
  414. dataout <= lock[7:0]; 
  415. rover0 <= 1;
  416. end // 读低字节
  417. 2'b10 : 
  418. begin
  419. dataout <= lock[15:8]; 
  420. rover0 <= 1;
  421. end // 读高字节
  422. 2'b11 :  // 读两个字节
  423. begin
  424. if(rlh0 == 2'b01)
  425. dataout <= lock[7:0]; // 先低
  426. else if(rlh0 == 2'b10)
  427. begin
  428. dataout <= lock[15:8]; 
  429. rover0 <= 1;
  430. end   // 后高
  431. end
  432. endcase
  433. end
  434. else if(rover0)
  435. begin
  436. rreset0 <= 1;
  437. rover0 <= 0;
  438. end
  439. //1号计数器
  440. if(read1)
  441. begin
  442. case(cmd1[5:4])
  443. 2'b01 :
  444. begin
  445. dataout <= lock[7:0]; 
  446. rover1 <= 1; 
  447. end
  448. 2'b10 : 
  449. begin
  450. dataout <= lock[15:8]; 
  451. rover1 <= 1;
  452. end
  453. 2'b11 : 
  454. begin
  455. if(rlh1 == 2'b01)
  456. dataout <= lock[7:0];
  457. else if(rlh1 == 2'b10)
  458. begin
  459. dataout <= lock[15:8]; 
  460. rover1 <= 1;
  461. end
  462. end
  463. endcase
  464. end
  465. else if(rover1)
  466. begin
  467. rreset1 <= 1;
  468. rover1 <= 0;
  469. end
  470. //2号计数器
  471. if(read2)
  472. begin
  473. case(cmd2[5:4])
  474. 2'b01 : 
  475. begin
  476. dataout <= lock[7:0]; 
  477. rover2 <= 1; 
  478. end
  479. 2'b10 : 
  480. begin
  481. dataout <= lock[15:8]; 
  482. rover2 <= 1;
  483. end
  484. 2'b11 : 
  485. begin
  486. if(rlh2 == 2'b01)
  487. dataout <= lock[7:0];
  488. else if(rlh2 == 2'b10)
  489. begin
  490. dataout <= lock[15:8]; 
  491. rover2 <= 1;
  492. end
  493. end
  494. endcase
  495. end
  496. else if(rover2)
  497. begin
  498. rreset2 <= 1;
  499. rover2 <= 0;
  500. end
  501. end
  502. endmodule