OpenCores
URL https://opencores.org/ocsvn/wbpwmaudio/wbpwmaudio/trunk

Subversion Repositories wbpwmaudio

[/] [wbpwmaudio/] [trunk/] [rtl/] [wbpwmaudio.v] - Diff between revs 3 and 4

Show entire file | Details | Blame | View Log

Rev 3 Rev 4
Line 1... Line 1...
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    wbpwmaudio.v
// Filename:    wbpwmaudio.v
//              
//              
// Project:     A Wishbone Controlled PWM (audio) controller
// Project:     A Wishbone Controlled PWM (audio) controller
//
//
Line 51... Line 51...
//      controller, to keep that from bothering you as well.
//      controller, to keep that from bothering you as well.
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// modify it under the terms of  the GNU General Public License as published
Line 74... Line 74...
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
module  wbpwmaudio(i_clk,
//
 
//
 
`default_nettype        none
 
//
 
module  wbpwmaudio(i_clk, i_reset,
                // Wishbone interface
                // Wishbone interface
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
                        o_wb_ack, o_wb_stall, o_wb_data,
                        o_wb_ack, o_wb_stall, o_wb_data,
                o_pwm, o_aux, o_int);
                o_pwm, o_aux, o_int);
        parameter       DEFAULT_RELOAD = 17'd1814, // about 44.1 kHz @  80MHz
        parameter       DEFAULT_RELOAD = 16'd1814, // about 44.1 kHz @  80MHz
                        //DEFAULT_RELOAD = 32'd2268,//about 44.1 kHz @ 100MHz
                        //DEFAULT_RELOAD = 16'd2268,//about 44.1 kHz @ 100MHz
                        NAUX=2, // Dev control values
                        NAUX=2, // Dev control values
                        VARIABLE_RATE=0,
                        VARIABLE_RATE=0,
                        TIMING_BITS=17;
                        TIMING_BITS=16;
        input   i_clk;
        input   wire            i_clk, i_reset;
        input   i_wb_cyc, i_wb_stb, i_wb_we;
        input   wire            i_wb_cyc, i_wb_stb, i_wb_we;
        input           i_wb_addr;
        input   wire            i_wb_addr;
        input   [31:0]   i_wb_data;
        input   wire    [31:0]   i_wb_data;
        output  reg             o_wb_ack;
        output  reg             o_wb_ack;
        output  wire            o_wb_stall;
        output  wire            o_wb_stall;
        output  wire    [31:0]   o_wb_data;
        output  wire    [31:0]   o_wb_data;
        output  reg             o_pwm;
        output  reg             o_pwm;
        output  reg     [(NAUX-1):0]     o_aux;
        output  reg     [(NAUX-1):0]     o_aux;
        output  reg             o_int;
        output  wire            o_int;
 
 
 
 
        // How often shall we create an interrupt?  Every reload_value clocks!
        // How often shall we create an interrupt?  Every reload_value clocks!
        // If VARIABLE_RATE==0, this value will never change and will be kept
        // If VARIABLE_RATE==0, this value will never change and will be kept
        // at the default reload rate (defined up top)
        // at the default reload rate (defined up top)
Line 107... Line 111...
        if (VARIABLE_RATE != 0)
        if (VARIABLE_RATE != 0)
        begin
        begin
                reg     [(TIMING_BITS-1):0]      r_reload_value;
                reg     [(TIMING_BITS-1):0]      r_reload_value;
                initial r_reload_value = DEFAULT_RELOAD;
                initial r_reload_value = DEFAULT_RELOAD;
                always @(posedge i_clk) // Data write
                always @(posedge i_clk) // Data write
                        if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_addr)&&(i_wb_we))
                        if ((i_wb_stb)&&(i_wb_addr)&&(i_wb_we))
                                r_reload_value <= i_wb_data[(TIMING_BITS-1):0];
                                r_reload_value <= i_wb_data[(TIMING_BITS-1):0] - 1'b1;
                assign  w_reload_value = r_reload_value;
                assign  w_reload_value = r_reload_value;
        end else begin
        end else begin
                assign  w_reload_value = DEFAULT_RELOAD;
                assign  w_reload_value = DEFAULT_RELOAD;
        end endgenerate
        end endgenerate
 
 
 
        //
 
        // The next value timer
 
        //
 
        // We'll want a new sample every w_reload_value clocks.  When the
 
        // timer hits zero, the signal ztimer (zero timer) will also be
 
        // set--allowing following logic to depend upon it.
 
        //
 
        reg                             ztimer;
        reg     [(TIMING_BITS-1):0]      timer;
        reg     [(TIMING_BITS-1):0]      timer;
        initial timer = DEFAULT_RELOAD;
        initial timer = DEFAULT_RELOAD;
 
        initial ztimer= 1'b0;
 
        always @(posedge i_clk)
 
                if (i_reset)
 
                        ztimer <= 1'b0;
 
                else
 
                        ztimer <= (timer == { {(TIMING_BITS-1){1'b0}}, 1'b1 });
 
 
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (timer == 0)
                if ((ztimer)||(i_reset))
                        timer <= w_reload_value;
                        timer <= w_reload_value;
                else
                else
                        timer <= timer - {{(TIMING_BITS-1){1'b0}},1'b1};
                        timer <= timer - {{(TIMING_BITS-1){1'b0}},1'b1};
 
 
 
        //
 
        // Whenever the timer runs out, accept the next value from the single
 
        // sample buffer.
 
        //
        reg     [15:0]   sample_out;
        reg     [15:0]   sample_out;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (timer == 0)
                if (ztimer)
                        sample_out <= next_sample;
                        sample_out <= next_sample;
 
 
 
 
 
        //
 
        // Control what's in the single sample buffer, next_sample, as well as
 
        // whether or not it's a valid sample.  Specifically, if next_valid is
 
        // false, then the sample buffer needs a new value.  Once the buffer
 
        // has a value within it, further writes will just quietly overwrite
 
        // this value.
        reg     [15:0]   next_sample;
        reg     [15:0]   next_sample;
        reg             next_valid;
        reg             next_valid;
        initial next_valid = 1'b1;
        initial next_valid = 1'b1;
        initial next_sample = 16'h8000;
        initial next_sample = 16'h8000;
        always @(posedge i_clk) // Data write
        always @(posedge i_clk) // Data write
                if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we)
                if ((i_wb_stb)&&(i_wb_we)
                                &&((~i_wb_addr)||(VARIABLE_RATE==0)))
                                &&((!i_wb_addr)||(VARIABLE_RATE==0)))
                begin
                begin
                        // Write with two's complement data, convert it
                        // Write with two's complement data, convert it
                        // internally to binary offset
                        // internally to an unsigned binary offset
                        next_sample <= { ~i_wb_data[15], i_wb_data[14:0] };
                        // representation
 
                        next_sample <= { !i_wb_data[15], i_wb_data[14:0] };
                        next_valid <= 1'b1;
                        next_valid <= 1'b1;
                        if (i_wb_data[16])
                        if (i_wb_data[16])
                                o_aux <= i_wb_data[(NAUX+20-1):20];
                                o_aux <= i_wb_data[(NAUX+20-1):20];
                end else if (timer == 0)
                end else if (ztimer)
                        next_valid <= 1'b0;
                        next_valid <= 1'b0;
 
 
        initial o_int = 1'b0;
        // If the value in our sample buffer isn't valid, create an interrupt
        always @(posedge i_clk)
        // that can be sent to a processor to know when to send a new sample.
                o_int <= (~next_valid);
        // This output can also be used to control a read from a FIFO as well,
 
        // depending on how you wish to use the core.
 
        assign  o_int = (!next_valid);
 
 
 
        //
 
        // To generate our waveform, we'll compare our sample value against
 
        // a bit reversed counter.  This counter is kept in pwm_counter.
 
        // The choice of a 16-bit counter is arbitrary, but it was made to
 
        // match the sixteen bits of the input
        reg     [15:0]   pwm_counter;
        reg     [15:0]   pwm_counter;
        initial pwm_counter = 16'h00;
        initial pwm_counter = 16'h00;
        always @(posedge i_clk)
        always @(posedge i_clk)
 
                if (i_reset)
 
                        pwm_counter <= 16'h0;
 
                else
                pwm_counter <= pwm_counter + 16'h01;
                pwm_counter <= pwm_counter + 16'h01;
 
 
 
        // Bit-reverse the counter
        wire    [15:0]   br_counter;
        wire    [15:0]   br_counter;
        genvar  k;
        genvar  k;
        generate for(k=0; k<16; k=k+1)
        generate for(k=0; k<16; k=k+1)
        begin : bit_reversal_loop
        begin : bit_reversal_loop
                assign br_counter[k] = pwm_counter[15-k];
                assign br_counter[k] = pwm_counter[15-k];
        end endgenerate
        end endgenerate
 
 
 
        // Apply our comparison to determine the next output bit
        always @(posedge i_clk)
        always @(posedge i_clk)
                o_pwm <= (sample_out >= br_counter);
                o_pwm <= (sample_out >= br_counter);
 
 
 
        //
 
        // Handle the bus return traffic.
        generate
        generate
        if (VARIABLE_RATE == 0)
        if (VARIABLE_RATE == 0)
        begin
        begin
 
                // If we are running off of a fixed rate, then just return
 
                // the current setting of the aux registers, the current
 
                // interrupt value, and the current sample we are outputting.
                assign o_wb_data = { {(12-NAUX){1'b0}}, o_aux,
                assign o_wb_data = { {(12-NAUX){1'b0}}, o_aux,
                                        3'h0, o_int, sample_out };
                                        3'h0, o_int, sample_out };
        end else begin
        end else begin
 
                // On the other hand, if we have been built to support a
 
                // variable sample rate, then return the reload value for
 
                // address one but otherwise the data value (above) for address
 
                // zero.
                reg     [31:0]   r_wb_data;
                reg     [31:0]   r_wb_data;
                always @(posedge i_clk)
                always @(posedge i_clk)
                        if (i_wb_addr)
                        if (i_wb_addr)
                                r_wb_data <= w_reload_value;
                                r_wb_data <= { (32-TIMING_BITS),w_reload_value};
                        else
                        else
                                r_wb_data <= { {(12-NAUX){1'b0}}, o_aux,
                                r_wb_data <= { {(12-NAUX){1'b0}}, o_aux,
                                                3'h0, o_int, sample_out };
                                                3'h0, o_int, sample_out };
                assign  o_wb_data = r_wb_data;
                assign  o_wb_data = r_wb_data;
        end endgenerate
        end endgenerate
 
 
 
        // Always ack on the clock following any request
        initial o_wb_ack = 1'b0;
        initial o_wb_ack = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                o_wb_ack <= (i_wb_cyc)&&(i_wb_stb);
                o_wb_ack <= (i_wb_stb);
 
 
 
        // Never stall
        assign  o_wb_stall = 1'b0;
        assign  o_wb_stall = 1'b0;
 
 
 
        // Make Verilator happy.  Since we aren't using all of the bits from
 
        // the bus, Verilator -Wall will complain.  This just informs
 
        // V*rilator that we already know these bits aren't being used.
 
        //
 
        // verilator lint_off UNUSED
 
        wire    [14:0] unused;
 
        assign  unused = { i_wb_cyc, i_wb_data[31:21], i_wb_data[19:17] };
 
        // verilator lint_on  UNUSED
 
 
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.