PTC Module from OpenCores
diff --git a/verilog/rtl/ptc/ptc_defines.v b/verilog/rtl/ptc/ptc_defines.v new file mode 100644 index 0000000..baa3a93 --- /dev/null +++ b/verilog/rtl/ptc/ptc_defines.v
@@ -0,0 +1,163 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE PWM/Timer/Counter Definitions //// +//// //// +//// This file is part of the PTC project //// +//// http://www.opencores.org/cores/ptc/ //// +//// //// +//// Description //// +//// PTC definitions. //// +//// //// +//// To Do: //// +//// Nothing //// +//// //// +//// Author(s): //// +//// - Damjan Lampret, lampret@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// 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 //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.2 2001/08/21 23:23:50 lampret +// Changed directory structure, defines and port names. +// +// Revision 1.2 2001/07/17 00:18:08 lampret +// Added new parameters however RTL still has some issues related to hrc_match and int_match +// +// Revision 1.1 2001/06/05 07:45:36 lampret +// Added initial RTL and test benches. There are still some issues with these files. +// +// + +// +// Width of the PTC counter +// +// +`define PTC_CW 32 + +// +// Undefine this one if you don't want to remove PTC block from your design +// but you also don't need it. When it is undefined, all PTC ports still +// remain valid and the core can be synthesized however internally there is +// no PTC funationality. +// +// Defined by default (duhh !). +// +`define PTC_IMPLEMENTED + +// +// Undefine if you don't need to read PTC registers. +// When it is undefined all reads of PTC registers return zero. This +// is usually useful if you want really small area (for example when +// implemented in FPGA). +// +// To follow PTC IP core specification document this one must be defined. +// Also to successfully run the test bench it must be defined. By default +// it is defined. +// +`define PTC_READREGS + +// +// Full WISHBONE address decoding +// +// It is is undefined, partial WISHBONE address decoding is performed. +// Undefine it if you need to save some area. +// +// By default it is defined. +// +`define PTC_FULL_DECODE + +// +// Strict 32-bit WISHBONE access +// +// If this one is defined, all WISHBONE accesses must be 32-bit. If it is +// not defined, err_o is asserted whenever 8- or 16-bit access is made. +// Undefine it if you need to save some area. +// +// By default it is defined. +// +`define PTC_STRICT_32BIT_ACCESS + +// +// WISHBONE address bits used for full decoding of PTC registers. +// +`define PTC_ADDRHH 15 +`define PTC_ADDRHL 5 +`define PTC_ADDRLH 1 +`define PTC_ADDRLL 0 + +// +// Bits of WISHBONE address used for partial decoding of PTC registers. +// +// Default 4:2. +// +`define PTC_OFS_BITS `PTC_ADDRHL-1:`PTC_ADDRLH+1 + +// +// Addresses of PTC registers +// +// To comply with PTC IP core specification document they must go from +// address 0 to address 0xC in the following order: RPTC_CNTR, RPTC_HRC, +// RPTC_LRC and RPTC_CTRL +// +// If particular alarm/ctrl register is not needed, it's address definition +// can be omitted and the register will not be implemented. Instead a fixed +// default value will +// be used. +// +`define PTC_RPTC_CNTR 2'h0 // Address 0x0 +`define PTC_RPTC_HRC 2'h1 // Address 0x4 +`define PTC_RPTC_LRC 2'h2 // Address 0x8 +`define PTC_RPTC_CTRL 2'h3 // Address 0xc + +// +// Default values for unimplemented PTC registers +// +`define PTC_DEF_RPTC_CNTR `PTC_CW'b0 +`define PTC_DEF_RPTC_HRC `PTC_CW'b0 +`define PTC_DEF_RPTC_LRC `PTC_CW'b0 +`define PTC_DEF_RPTC_CTRL 9'h01 // RPTC_CTRL[EN] = 1 + +// +// RPTC_CTRL bits +// +// To comply with the PTC IP core specification document they must go from +// bit 0 to bit 8 in the following order: EN, ECLK, NEC, OE, SINGLE, INTE, +// INT, CNTRRST, CAPTE +// +`define PTC_RPTC_CTRL_EN 0 +`define PTC_RPTC_CTRL_ECLK 1 +`define PTC_RPTC_CTRL_NEC 2 +`define PTC_RPTC_CTRL_OE 3 +`define PTC_RPTC_CTRL_SINGLE 4 +`define PTC_RPTC_CTRL_INTE 5 +`define PTC_RPTC_CTRL_INT 6 +`define PTC_RPTC_CTRL_CNTRRST 7 +`define PTC_RPTC_CTRL_CAPTE 8 +
diff --git a/verilog/rtl/ptc/ptc_top.v b/verilog/rtl/ptc/ptc_top.v new file mode 100644 index 0000000..a405a1b --- /dev/null +++ b/verilog/rtl/ptc/ptc_top.v
@@ -0,0 +1,391 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE PWM/Timer/Counter //// +//// //// +//// This file is part of the PTC project //// +//// http://www.opencores.org/cores/ptc/ //// +//// //// +//// Description //// +//// Implementation of PWM/Timer/Counter IP core according to //// +//// PTC IP core specification document. //// +//// //// +//// To Do: //// +//// Nothing //// +//// //// +//// Author(s): //// +//// - Damjan Lampret, lampret@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// 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 //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.4 2001/09/18 18:48:29 lampret +// Changed top level ptc into ptc_top. Changed defines.v into ptc_defines.v. Reset of the counter is now synchronous. +// +// Revision 1.3 2001/08/21 23:23:50 lampret +// Changed directory structure, defines and port names. +// +// Revision 1.2 2001/07/17 00:18:10 lampret +// Added new parameters however RTL still has some issues related to hrc_match and int_match +// +// Revision 1.1 2001/06/05 07:45:36 lampret +// Added initial RTL and test benches. There are still some issues with these files. +// +// + +`include "ptc_defines.v" + +module ptc_top( + // WISHBONE Interface + wb_clk_i, wb_rst_i, wb_cyc_i, wb_adr_i, wb_dat_i, wb_sel_i, wb_we_i, wb_stb_i, + wb_dat_o, wb_ack_o, wb_err_o, wb_inta_o, + + // External PTC Interface + gate_clk_pad_i, capt_pad_i, pwm_pad_o, oen_padoen_o +); + +parameter dw = 32; +parameter aw = `PTC_ADDRHH+1; +parameter cw = `PTC_CW; + +// +// WISHBONE Interface +// +input wb_clk_i; // Clock +input wb_rst_i; // Reset +input wb_cyc_i; // cycle valid input +input [aw-1:0] wb_adr_i; // address bus inputs +input [dw-1:0] wb_dat_i; // input data bus +input [3:0] wb_sel_i; // byte select inputs +input wb_we_i; // indicates write transfer +input wb_stb_i; // strobe input +output [dw-1:0] wb_dat_o; // output data bus +output wb_ack_o; // normal termination +output wb_err_o; // termination w/ error +output wb_inta_o; // Interrupt request output + +// +// External PTC Interface +// +input gate_clk_pad_i; // EClk/Gate input +input capt_pad_i; // Capture input +output pwm_pad_o; // PWM output +output oen_padoen_o; // PWM output driver enable + +`ifdef PTC_IMPLEMENTED + +// +// PTC Main Counter Register (or no register) +// +`ifdef PTC_RPTC_CNTR +reg [cw-1:0] rptc_cntr; // RPTC_CNTR register +`else +wire [cw-1:0] rptc_cntr; // No RPTC_CNTR register +`endif + +// +// PTC HI Reference/Capture Register (or no register) +// +`ifdef PTC_RPTC_HRC +reg [cw-1:0] rptc_hrc; // RPTC_HRC register +`else +wire [cw-1:0] rptc_hrc; // No RPTC_HRC register +`endif + +// +// PTC LO Reference/Capture Register (or no register) +// +`ifdef PTC_RPTC_LRC +reg [cw-1:0] rptc_lrc; // RPTC_LRC register +`else +wire [cw-1:0] rptc_lrc; // No RPTC_LRC register +`endif + +// +// PTC Control Register (or no register) +// +`ifdef PTC_RPTC_CTRL +reg [8:0] rptc_ctrl; // RPTC_CTRL register +`else +wire [8:0] rptc_ctrl; // No RPTC_CTRL register +`endif + +// +// Internal wires & regs +// +wire rptc_cntr_sel; // RPTC_CNTR select +wire rptc_hrc_sel; // RPTC_HRC select +wire rptc_lrc_sel; // RPTC_LRC select +wire rptc_ctrl_sel; // RPTC_CTRL select +wire hrc_match; // RPTC_HRC matches RPTC_CNTR +wire lrc_match; // RPTC_LRC matches RPTC_CNTR +wire restart; // Restart counter when asserted +wire stop; // Stop counter when asserted +wire cntr_clk; // Counter clock +wire cntr_rst; // Counter reset +wire hrc_clk; // RPTC_HRC clock +wire lrc_clk; // RPTC_LRC clock +wire eclk_gate; // ptc_ecgt xored by RPTC_CTRL[NEC] +wire gate; // Gate function of ptc_ecgt +wire pwm_rst; // Reset of a PWM output +reg [dw-1:0] wb_dat_o; // Data out +reg pwm_pad_o; // PWM output +reg intr_reg; // Interrupt reg +wire int_match; // Interrupt match +wire full_decoding; // Full address decoding qualification + +// +// All WISHBONE transfer terminations are successful except when: +// a) full address decoding is enabled and address doesn't match +// any of the PTC registers +// b) sel_i evaluation is enabled and one of the sel_i inputs is zero +// +assign wb_ack_o = wb_cyc_i & wb_stb_i & !wb_err_o; +`ifdef PTC_FULL_DECODE +`ifdef PTC_STRICT_32BIT_ACCESS +assign wb_err_o = wb_cyc_i & wb_stb_i & (!full_decoding | (wb_sel_i != 4'b1111)); +`else +assign wb_err_o = wb_cyc_i & wb_stb_i & !full_decoding; +`endif +`else +`ifdef PTC_STRICT_32BIT_ACCESS +assign wb_err_o = wb_cyc_i & wb_stb_i & (wb_sel_i != 4'b1111); +`else +assign wb_err_o = 1'b0; +`endif +`endif + +// +// Counter clock is selected by RPTC_CTRL[ECLK]. When it is set, +// external clock is used. +// +assign cntr_clk = rptc_ctrl[`PTC_RPTC_CTRL_ECLK] ? eclk_gate : wb_clk_i; + +// +// Counter reset +// +assign cntr_rst = wb_rst_i; + +// +// HRC clock is selected by RPTC_CTRL[CAPTE]. When it is set, +// ptc_capt is used as a clock. +// +assign hrc_clk = rptc_ctrl[`PTC_RPTC_CTRL_CAPTE] ? capt_pad_i : wb_clk_i; + +// +// LRC clock is selected by RPTC_CTRL[CAPTE]. When it is set, +// inverted ptc_capt is used as a clock. +// +assign lrc_clk = rptc_ctrl[`PTC_RPTC_CTRL_CAPTE] ? ~capt_pad_i : wb_clk_i; + +// +// PWM output driver enable is inverted RPTC_CTRL[OE] +// +assign oen_padoen_o = ~rptc_ctrl[`PTC_RPTC_CTRL_OE]; + +// +// Use RPTC_CTRL[NEC] +// +assign eclk_gate = gate_clk_pad_i ^ rptc_ctrl[`PTC_RPTC_CTRL_NEC]; + +// +// Gate function is active when RPTC_CTRL[ECLK] is cleared +// +assign gate = eclk_gate & ~rptc_ctrl[`PTC_RPTC_CTRL_ECLK]; + +// +// Full address decoder +// +`ifdef PTC_FULL_DECODE +assign full_decoding = (wb_adr_i[`PTC_ADDRHH:`PTC_ADDRHL] == {`PTC_ADDRHH-`PTC_ADDRHL+1{1'b0}}) & + (wb_adr_i[`PTC_ADDRLH:`PTC_ADDRLL] == {`PTC_ADDRLH-`PTC_ADDRLL+1{1'b0}}); +`else +assign full_decoding = 1'b1; +`endif + +// +// PTC registers address decoder +// +assign rptc_cntr_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`PTC_OFS_BITS] == `PTC_RPTC_CNTR) & full_decoding; +assign rptc_hrc_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`PTC_OFS_BITS] == `PTC_RPTC_HRC) & full_decoding; +assign rptc_lrc_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`PTC_OFS_BITS] == `PTC_RPTC_LRC) & full_decoding; +assign rptc_ctrl_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`PTC_OFS_BITS] == `PTC_RPTC_CTRL) & full_decoding; + +// +// Write to RPTC_CTRL or update of RPTC_CTRL[INT] bit +// +`ifdef PTC_RPTC_CTRL +always @(posedge wb_clk_i or posedge wb_rst_i) + if (wb_rst_i) + rptc_ctrl <= #1 9'b0; + else if (rptc_ctrl_sel && wb_we_i) + rptc_ctrl <= #1 wb_dat_i[8:0]; + else if (rptc_ctrl[`PTC_RPTC_CTRL_INTE]) + rptc_ctrl[`PTC_RPTC_CTRL_INT] <= #1 rptc_ctrl[`PTC_RPTC_CTRL_INT] | intr_reg; +`else +assign rptc_ctrl = `PTC_DEF_RPTC_CTRL; +`endif + +// +// Write to RPTC_HRC +// +`ifdef PTC_RPTC_HRC +always @(posedge hrc_clk or posedge wb_rst_i) + if (wb_rst_i) + rptc_hrc <= #1 {cw{1'b0}}; + else if (rptc_hrc_sel && wb_we_i) + rptc_hrc <= #1 wb_dat_i[cw-1:0]; + else if (rptc_ctrl[`PTC_RPTC_CTRL_CAPTE]) + rptc_hrc <= #1 rptc_cntr; +`else +assign rptc_hrc = `DEF_RPTC_HRC; +`endif + +// +// Write to RPTC_LRC +// +`ifdef PTC_RPTC_LRC +always @(posedge lrc_clk or posedge wb_rst_i) + if (wb_rst_i) + rptc_lrc <= #1 {cw{1'b0}}; + else if (rptc_lrc_sel && wb_we_i) + rptc_lrc <= #1 wb_dat_i[cw-1:0]; + else if (rptc_ctrl[`PTC_RPTC_CTRL_CAPTE]) + rptc_lrc <= #1 rptc_cntr; +`else +assign rptc_lrc = `DEF_RPTC_LRC; +`endif + +// +// Write to or increment of RPTC_CNTR +// +`ifdef PTC_RPTC_CNTR +always @(posedge cntr_clk or posedge cntr_rst) + if (cntr_rst) + rptc_cntr <= #1 {cw{1'b0}}; + else if (rptc_cntr_sel && wb_we_i) + rptc_cntr <= #1 wb_dat_i[cw-1:0]; + else if (restart) + rptc_cntr <= #1 {cw{1'b0}}; + else if (!stop && rptc_ctrl[`PTC_RPTC_CTRL_EN] && !gate) + rptc_cntr <= #1 rptc_cntr + 1; +`else +assign rptc_cntr = `DEF_RPTC_CNTR; +`endif + +// +// Read PTC registers +// +always @(wb_adr_i or rptc_hrc or rptc_lrc or rptc_ctrl or rptc_cntr) + case (wb_adr_i[`PTC_OFS_BITS]) // synopsys full_case parallel_case +`ifdef PTC_READREGS + `PTC_RPTC_HRC: wb_dat_o[dw-1:0] = {{dw-cw{1'b0}}, rptc_hrc}; + `PTC_RPTC_LRC: wb_dat_o[dw-1:0] = {{dw-cw{1'b0}}, rptc_lrc}; + `PTC_RPTC_CTRL: wb_dat_o[dw-1:0] = {{dw-9{1'b0}}, rptc_ctrl}; +`endif + default: wb_dat_o[dw-1:0] = {{dw-cw{1'b0}}, rptc_cntr}; + endcase + +// +// A match when RPTC_HRC is equal to RPTC_CNTR +// +assign hrc_match = rptc_ctrl[`PTC_RPTC_CTRL_EN] & (rptc_cntr == rptc_hrc); + +// +// A match when RPTC_LRC is equal to RPTC_CNTR +// +assign lrc_match = rptc_ctrl[`PTC_RPTC_CTRL_EN] & (rptc_cntr == rptc_lrc); + +// +// Restart counter when lrc_match asserted and RPTC_CTRL[SINGLE] cleared +// or when RPTC_CTRL[CNTRRST] is set +// +assign restart = lrc_match & ~rptc_ctrl[`PTC_RPTC_CTRL_SINGLE] + | rptc_ctrl[`PTC_RPTC_CTRL_CNTRRST]; + +// +// Stop counter when lrc_match and RPTC_CTRL[SINGLE] both asserted +// +assign stop = lrc_match & rptc_ctrl[`PTC_RPTC_CTRL_SINGLE]; + +// +// PWM reset when lrc_match or system reset +// +assign pwm_rst = lrc_match | wb_rst_i; + +// +// PWM output +// +always @(posedge wb_clk_i) // posedge pwm_rst or posedge hrc_match !!! Damjan + if (pwm_rst) + pwm_pad_o <= #1 1'b0; + else if (hrc_match) + pwm_pad_o <= #1 1'b1; + +// +// Generate an interrupt request +// +assign int_match = (lrc_match | hrc_match) & rptc_ctrl[`PTC_RPTC_CTRL_INTE]; + +// Register interrupt request +always @(posedge wb_rst_i or posedge wb_clk_i) // posedge int_match (instead of wb_rst_i) + if (wb_rst_i) + intr_reg <= #1 1'b0; + else if (int_match) + intr_reg <= #1 1'b1; + else + intr_reg <= #1 1'b0; + +// +// Alias +// +assign wb_inta_o = rptc_ctrl[`PTC_RPTC_CTRL_INT]; + +`else + +// +// When PTC is not implemented, drive all outputs as would when RPTC_CTRL +// is cleared and WISHBONE transfers complete with errors +// +assign wb_inta_o = 1'b0; +assign wb_ack_o = 1'b0; +assign wb_err_o = cyc_i & stb_i; +assign pwm_pad_o = 1'b0; +assign oen_padoen_o = 1'b1; + +// +// Read PTC registers +// +`ifdef PTC_READREGS +assign wb_dat_o = {dw{1'b0}}; +`endif + +`endif + +endmodule