URL
https://opencores.org/ocsvn/next186mp3/next186mp3/trunk
Subversion Repositories next186mp3
[/] [next186mp3/] [trunk/] [HW/] [timer8253.v] - Rev 2
Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////////////////// // // This file is part of the Next186 Soc PC project // http://opencores.org/project,next186 // // Filename: timer8253.v // Description: Part of the Next186 SoC PC project, timer // 8253 simplified timer (no gate, only counters 0 and 2, no read back command) // Version 1.0 // Creation date: May2012 // // Author: Nicolae Dumitrache // e-mail: ndumitrache@opencores.org // ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2012 Nicolae Dumitrache // // This source file may be used and distributed without // restriction provided that this copyright statement is not // removed from the file and that any derivative work contains // the original copyright notice and the associated disclaimer. // // This source file is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General // Public License as published by the Free Software Foundation; // either version 2.1 of the License, or (at your option) any // later version. // // This source is distributed in the hope that it will be // useful, but WITHOUT ANY WARRANTY; without even the implied // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the GNU Lesser General Public License for more // details. // // You should have received a copy of the GNU Lesser General // Public License along with this source; if not, download it // from http://www.opencores.org/lgpl.shtml // /////////////////////////////////////////////////////////////////////////////////// // Additional Comments: // http://wiki.osdev.org/Programmable_Interval_Timer ////////////////////////////////////////////////////////////////////////////////// `timescale 1ns / 1ps module timer_8253( input CS, input WR, input [1:0]addr, input [7:0]din, output wire [7:0]dout, input CLK_25, input clk, // cpu CLK output out0, output out2 ); reg [8:0]rclk = 0; // rclk[8] oscillates at 1193181.8181... Hz reg [1:0]cclk = 0; always @(posedge CLK_25) begin if(rclk[7:0] < 8'd208) rclk <= rclk + 21; else rclk <= rclk + 57; end always @ (posedge clk) begin cclk <= {cclk[0], rclk[8]}; end wire a0 = addr == 0; wire a2 = addr == 2; wire a3 = addr == 3; wire cmd0 = a3 && din[7:6] == 0; wire cmd2 = a3 && din[7:6] == 2; wire [7:0]dout0; wire [7:0]dout2; wire [7:0]mode0; wire [7:0]mode2; counter counter0 ( .CS(CS && (a0 || cmd0)), .WR(WR), .clk(clk), .cmd(cmd0), .din(din), .dout(dout0), .mode(mode0), .CE(cclk) ); counter counter2 ( .CS(CS && (a2 || cmd2)), .WR(WR), .clk(clk), .cmd(cmd2), .din(din), .dout(dout2), .mode(mode2), .CE(cclk) ); assign out0 = mode0[7]; assign out2 = mode2[7]; assign dout = a0 ? dout0 : dout2; endmodule module counter( input CS, input WR, // write cmd/data input clk, // CPU clk input cmd, input [7:0]din, output [7:0]dout, output reg [7:0]mode, // mode[7] = output input [1:0]CE // count enable ); reg [15:0]count = 0; reg [15:0]init = 0; reg [1:0]state = 0; // state[1] = init reg filled reg strobe = 0; reg rd = 0; reg latch = 0; reg newcmd = 0; wire c1 = count == 1; wire c2 = count == 2; reg CE1 = 0; assign dout = mode[5] & (~mode[4] | rd) ? count[15:8] : count[7:0]; always @(posedge clk) begin if(CE == 2'b10) CE1 <= 1; if(CS) begin if(WR) begin mode[6] <= 1; rd <= 0; latch <= 0; if(cmd) begin // command if(|din[5:4]) begin mode[5:0] <= din[5:0]; newcmd <= 1; state <= {1'b0, din[5] & ~din[4]}; end else latch <= &mode[5:4]; end else begin // data state <= state[0] + ^mode[5:4] + 1; if(state[0]) init[15:8] <= din; else init[7:0] <= din; end end else begin rd <= ~rd; if(rd) latch <= 0; end end else if(state[1] && CE1 && !latch) begin newcmd <= 0; CE1 <= 0; case(mode[3:1]) 3'b000, 3'b001: if(mode[6]) begin mode[7:6] <= 2'b00; count <= init; end else begin count <= count - 1; if(c1) mode[7] <= 1; end 3'b010, 3'b110: begin mode[7] <= ~c2; if(c1 | newcmd) begin mode[6] <= 1'b0; count <= init; end else count <= count - 1; end 3'b011, 3'b111: begin if(c1 | c2 | newcmd) begin mode[7:6] <= {~mode[7] | newcmd, 1'b0}; count <= {init[15:1], (~mode[7] | newcmd) & init[0]}; end else count <= count - 2; end 3'b100, 3'b101: if(mode[6]) begin mode[7:6] <= 2'b10; count <= init; strobe <= 1; end else begin count <= count - 1; if(c1) begin if(strobe) mode[7] <= 0; strobe <= 0; end else mode[7] <= 1; end endcase end end endmodule