URL
https://opencores.org/ocsvn/openmsp430/openmsp430/trunk
Subversion Repositories openmsp430
[/] [openmsp430/] [trunk/] [fpga/] [actel_m1a3pl_dev_kit/] [rtl/] [verilog/] [dac_spi_if.v] - Rev 91
Go to most recent revision | Compare with Previous | Blame | View Log
//---------------------------------------------------------------------------- // Copyright (C) 2001 Authors // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of the authors nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE // //---------------------------------------------------------------------------- // // *File Name: dac_spi_if.v // // *Module Description: // SPI interface for National's DAC121S101 12 bit DAC // // *Author(s): // - Olivier Girard, olgirard@gmail.com // //---------------------------------------------------------------------------- // $Rev: 66 $ // $LastChangedBy: olivier.girard $ // $LastChangedDate: 2010-03-07 09:09:38 +0100 (Sun, 07 Mar 2010) $ //---------------------------------------------------------------------------- `include "timescale.v" module dac_spi_if ( // OUTPUTs cntrl1, // Control value 1 cntrl2, // Control value 2 din, // SPI Serial Data per_dout, // Peripheral data output sclk, // SPI Serial Clock sync_n, // SPI Frame synchronization signal (low active) // INPUTs mclk, // Main system clock per_addr, // Peripheral address per_din, // Peripheral data input per_en, // Peripheral enable (high active) per_wen, // Peripheral write enable (high active) puc // Main system reset ); // PARAMETERs //============ parameter SCLK_DIV = 0; // Serial clock divider (Tsclk=Tmclk*(SCLK_DIV+1)*2) parameter BASE_ADDR = 9'h190; // Registers base address // OUTPUTs //========= output [3:0] cntrl1; // Control value 1 output [3:0] cntrl2; // Control value 2 output din; // SPI Serial Data output [15:0] per_dout; // Peripheral data output output sclk; // SPI Serial Clock output sync_n; // SPI Frame synchronization signal (low active) // INPUTs //========= input mclk; // Main system clock input [7:0] per_addr; // Peripheral address input [15:0] per_din; // Peripheral data input input per_en; // Peripheral enable (high active) input [1:0] per_wen; // Peripheral write enable (high active) input puc; // Main system reset //============================================================================= // 1) PARAMETER DECLARATION //============================================================================= // Register addresses parameter DAC_VAL = BASE_ADDR; parameter DAC_STAT = BASE_ADDR+2; parameter CNTRL1 = BASE_ADDR+4; parameter CNTRL2 = BASE_ADDR+6; // Register one-hot decoder parameter DAC_VAL_D = (512'h1 << DAC_VAL); parameter DAC_STAT_D = (512'h1 << DAC_STAT); parameter CNTRL1_D = (512'h1 << CNTRL1); parameter CNTRL2_D = (512'h1 << CNTRL2); //============================================================================ // 2) REGISTER DECODER //============================================================================ // Register address decode reg [511:0] reg_dec; always @(per_addr) case ({per_addr,1'b0}) DAC_VAL : reg_dec = DAC_VAL_D; DAC_STAT: reg_dec = DAC_STAT_D; CNTRL1 : reg_dec = CNTRL1_D; CNTRL2 : reg_dec = CNTRL2_D; default : reg_dec = {512{1'b0}}; endcase // Read/Write probes wire reg_write = |per_wen & per_en; wire reg_read = ~|per_wen & per_en; // Read/Write vectors wire [511:0] reg_wr = reg_dec & {512{reg_write}}; wire [511:0] reg_rd = reg_dec & {512{reg_read}}; //============================================================================ // 3) REGISTERS //============================================================================ // DAC_VAL Register //------------------ reg [11:0] dac_val; reg dac_pd0; reg dac_pd1; wire dac_val_wr = reg_wr[DAC_VAL]; always @ (posedge mclk or posedge puc) if (puc) begin dac_val <= 12'h000; dac_pd0 <= 1'b0; dac_pd1 <= 1'b0; end else if (dac_val_wr) begin dac_val <= per_din[11:0]; dac_pd0 <= per_din[12]; dac_pd1 <= per_din[13]; end // CNTRL1 Register //------------------ reg [3:0] cntrl1; wire cntrl1_wr = reg_wr[CNTRL1]; always @ (posedge mclk or posedge puc) if (puc) cntrl1 <= 4'h0; else if (cntrl1_wr) cntrl1 <= per_din; // CNTRL2 Register //------------------ reg [3:0] cntrl2; wire cntrl2_wr = reg_wr[CNTRL2]; always @ (posedge mclk or posedge puc) if (puc) cntrl2 <= 4'h0; else if (cntrl2_wr) cntrl2 <= per_din; //============================================================================ // 4) DATA OUTPUT GENERATION //============================================================================ // Data output mux wire [15:0] dac_val_rd = { 2'b00, dac_pd1, dac_pd0, dac_val} & {16{reg_rd[DAC_VAL]}}; wire [15:0] dac_stat_rd = {15'h0000, ~sync_n} & {16{reg_rd[DAC_STAT]}}; wire [15:0] cntrl1_rd = {12'h000, cntrl1} & {16{reg_rd[CNTRL1]}}; wire [15:0] cntrl2_rd = {12'h000, cntrl2} & {16{reg_rd[CNTRL2]}}; wire [15:0] per_dout = dac_val_rd | dac_stat_rd | cntrl1_rd | cntrl2_rd; //============================================================================ // 5) SPI INTERFACE //============================================================================ // SPI Clock divider reg [3:0] spi_clk_div; always @ (posedge mclk or posedge puc) if (puc) spi_clk_div <= SCLK_DIV; else if (spi_clk_div==0) spi_clk_div <= SCLK_DIV; else spi_clk_div <= spi_clk_div-1; // SPI Clock generation reg sclk; always @ (posedge mclk or posedge puc) if (puc) sclk <= 1'b0; else if (spi_clk_div==0) sclk <= ~sclk; wire sclk_re = (spi_clk_div==0) & ~sclk; // SPI Transfer trigger reg spi_tfx_trig; always @ (posedge mclk or posedge puc) if (puc) spi_tfx_trig <= 1'b0; else if (dac_val_wr) spi_tfx_trig <= 1'b1; else if (sclk_re & sync_n) spi_tfx_trig <= 1'b0; wire spi_tfx_init = spi_tfx_trig & sync_n; // Data counter reg [3:0] spi_cnt; wire spi_cnt_done = (spi_cnt==4'hf); always @ (posedge mclk or posedge puc) if (puc) spi_cnt <= 4'hf; else if (sclk_re) if (spi_tfx_init) spi_cnt <= 4'he; else if (~spi_cnt_done) spi_cnt <= spi_cnt-1; // Frame synchronization signal (low active) reg sync_n; always @ (posedge mclk or posedge puc) if (puc) sync_n <= 1'b1; else if (sclk_re) if (spi_tfx_init) sync_n <= 1'b0; else if (spi_cnt_done) sync_n <= 1'b1; // Value to be shifted_out reg [15:0] dac_shifter; always @ (posedge mclk or posedge puc) if (puc) dac_shifter <= 16'h000; else if (sclk_re) if (spi_tfx_init) dac_shifter <= {2'b00, dac_pd1, dac_pd0, dac_val[11:0]}; else dac_shifter <= {dac_shifter[14:0], 1'b0}; assign din = dac_shifter[15]; endmodule // dac_spi_if
Go to most recent revision | Compare with Previous | Blame | View Log