DE248 Home Page

DE248 Drive Electronics

WINDOW COUNTER MODULE

(Last Modified: 04 November 2010 06:09:20 PM )



Top Level Instantiation

wire WC_TC;
WindowCounter16 MCNT (
    .Q(BFE_X), .TC(WC_TC), .CE1(HI), .CE2(HI), .LoadB(~WC_TC),
    .D(BFE_D), .A(BFE_A), .ID(6'b000000), .WS(BFE_WS),

    .DefStart(16'd0), .DefStop(16'd50),
    .ClkR(MclkRise), .PrstB(~rst), .Pclk(clk)
);

 


User-level Description

The Window Counter is a simple counter that runs between a Start value and a Stop value. The counter contains four 8-bit internal registers that are used to store the Start and Stop values. Upon a global reset, the default values (DefStart and DefStop) are loaded into the registers. These may be overwritten using the register interface. The address of the registers are obtained by taking the 6-bit ID value and appending the local register value. The register map is thus:

The register map is interlaced to improve the compatibility of the map between window counters of various depths, such as 8-bit, 16-bit, 24-bit, and 32-bit.

Note, however, that upon a global reset, the counter is reset to a state of zero and not the Start value. The Start value is only applied in response to an explicit Load (LoadB being LO) command.

The number of states in each cycle of the counter is ((Stop - Start) + 1) since the counter will be placed in both the Start and the Stop states. The Terminal Count output (TC) is asserted whenever the present state of the counter is equal to the Stop value.

There are two Count Enable inputs (CE1 and CE2) used to interrupt the counting process. Both must be HI in order for the counter to increment.

There is also a Clock Rising Edge input (ClkR) which is used to enable the counter only on those system clock rising edges that are coincident with the rising edge of a generated master clock. This is a feature that is not on the ASIC version of the counter and is there to accommodate the desire to have programmatic control over the clock speed while avoiding gated clocks in an FPGA.


Module Code

module WindowCounter16(

    Q, TC, CE1, CE2, LoadB,

    D, A, ID, WS,

    DefStart, DefStop,

    ClkR, PrstB, Pclk);

    output [15:0] Q;
    output TC;
    input CE1, CE2, LoadB;
    input [ 7:0] D, A;
    input [ 7:2] ID;
    input WS;
    input [15:0] DefStart, DefStop;
    input ClkR, PrstB, Pclk;

    parameter HI = 1'b1, LO = 1'b0;

    // Control Register Interface
    wire [15:0] Start, Stop;
    RegBank4 REG (
        .D(D), .A(A), .ID(ID), .WS(WS),
        .Q3(Stop[15:8]),  .V3(DefStop[15:8]),
        .Q2(Start[15:8]), .V2(DefStart[15:8]),
        .Q1(Stop[7:0]),   .V1(DefStop[7:0]),
        .Q0(Start[7:0]),  .V0(DefStart[7:0]),
        .PrstB(PrstB), .Pclk(Pclk)
    );

    // Control Signals

    reg [15:0] Q_reg;
    assign Q = Q_reg;

    wire TC_int;
    assign TC = TC_int;
    assign TC_int = (Q_reg == Stop)? HI : LO;

    wire CE, Load, LoadTCB;
    assign CE = (CE1 & CE2)? HI : LO;
    assign LoadTCB = ~((TC_int & CE)? HI : LO);
    assign Load = ~((LoadB & LoadTCB)? HI : LO);
   
    // State Machine

    always @(posedge Pclk or negedge PrstB)
    begin
        if (PrstB == LO)
            Q_reg <= 16'd0;
        else if (ClkR == HI)
            begin
                if (Load == HI)
                    Q_reg <= Start;
                else if (CE == HI)
                    Q_reg <= Q_reg + 1;

                else

                    Q_reg <= Q_reg;
            end
        else
            Q_reg <= Q_reg;
    end

endmodule
 


Theory of Operation

The counter contains a 4-byte register that is used to store the Start and Stop values. 

    // Control Register Interface
    wire [15:0] Start, Stop;
    RegBank4 REG (
        .D(D), .A(A), .ID(ID), .WS(WS),
        .Q3(Stop[15:8]),  .V3(DefStop[15:8]),
        .Q2(Start[15:8]), .V2(DefStart[15:8]),
        .Q1(Stop[7:0]),   .V1(DefStop[7:0]),
        .Q0(Start[7:0]),  .V0(DefStart[7:0]),
        .PrstB(PrstB), .Pclk(Pclk)
    );

The default values, which are applied to the DefStart and DefStop inputs to the module, are loaded into the counter whenever PrstB is taken LO. The user may program different values into the register via the 8-bit register bus. The address is obtained by using the 6-bit ID input to the module and appending the 2-bit internal address of the desired register. After placing the address and data on the bus, the values are loaded into the register by strobing the Write Strobe (WS) input.

    // Control Signals

    reg [15:0] Q_reg;
    assign Q = Q_reg;

    wire TC_int;
    assign TC = TC_int;
    assign TC_int = (Q_reg == Stop)? HI : LO;

    wire CE;

    assign CE = (CE1 & CE2)? HI : LO;
   

    wire LoadTCB, Load;
    assign LoadTCB = ~((TC_int & CE)? HI : LO);
    assign Load = ~((LoadB & LoadTCB)? HI : LO);

The control signals are structural implementations of the logic on the BFE297 and, as such, are not the most readable statements. The first pair of statements above simply creates an internal register variable, Q_reg, that the state machine can use and statically assigns its value to the module output. The next block of statements generates the Terminal Count output, TC, in a similar fashion. Instead of instantiating a digital comparator, as is done on the ASIC, this code used an equivalent behavioral statement. The third block of statements simply says that the internal Count Enable, CE, signal is the logical-AND of the two externally applied signals (CE1 and CE2). The final block of statements is the most cryptic, but all it says is that the Load signal is asserted whenever either the external LoadB signal (which is active-LO) is asserted or the counter is in its terminal count state and counting is enabled.

    // State Machine

    always @(posedge Pclk or negedge PrstB)
    begin
        if (PrstB == LO)
            Q_reg <= 16'd0;
        else if (ClkR == HI)
            begin
                if (Load == HI)
                    Q_reg <= Start;
                else if (CE == HI)
                    Q_reg <= Q_reg + 1;

                else

                    Q_reg <= Q_reg;
            end
        else
            Q_reg <= Q_reg;
    end

The actual state machine is very straight-forward. First, if the PrstB signal, which is active-LO, is asserted then the counter is immediately set to the all-zero state. Otherwise, things only happen on the positive edge of the system clock (Pclk) and then only if the master clock is about to rise (ClkR signal is asserted). If these conditions are met, then if the Load signal is asserted (either due to an explicit load command or as a result of the counter reaching the Stop value) then the Start value is loaded. If the Load signal is not asserted, then the counter will increment, but only if both count enable inputs are asserted; otherwise, the present state of the counter will be retained..