zynq-sandbox

old FPGA projects for ZYNQ
git clone http://frotz.net/git/zynq-sandbox.git
Log | Files | Refs | README

xadc.sv (3893B)


      1 // Copyright 2014 Travis Geiselbrecht <geist@foobox.com>
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 `timescale 1ns / 1ps
     16 
     17 module xadc(
     18 	input clk,
     19 	input rst,
     20 
     21 	input vp,
     22 	input vn,
     23 	input [15:0] aux_channel_n,
     24 	input [15:0] aux_channel_p,
     25 
     26 	output [3:0] debug_out,
     27 
     28 	axi_ifc.slave axi
     29 );
     30 
     31 parameter reg [15:0] CLKDIV = 8; // default ADCCLK divide from input clk
     32 parameter reg [15:0] CHSEL1 = 16'b0000000100000000; // CHSEL1 - enable temperature
     33 parameter reg [15:0] CHSEL2 = 16'b0000000011000000; // CHSEL2 - enable simultaneous channels 6/14, 7/15
     34 
     35 reg adc_den;
     36 reg adc_dwe;
     37 reg [15:0] adc_din;
     38 wire [15:0] adc_dout;
     39 reg [6:0] adc_daddr;
     40 wire adc_drdy;
     41 
     42 wire [4:0] adc_channel;
     43 wire adc_eoc;
     44 wire adc_eos;
     45 wire adc_busy;
     46 
     47 XADC #(
     48 	.INIT_40(16'b1000000000000000),// No averaging
     49 	.INIT_41(16'b0100111011110000),// Simultaneous sampling mode, Disable unused ALMs, Enable calibration
     50 	.INIT_42(16'b0000000000000000 | (CLKDIV << 8)),// DCLK divide
     51 	.INIT_48(CHSEL1),
     52 	.INIT_49(CHSEL2),
     53 )
     54 adc0(
     55 	.DI(adc_din), // 16 bit in
     56 	.DO(adc_dout), // 16 bit out
     57 	.DADDR(adc_daddr), // 7 bit address
     58 	.DEN(adc_den), // enable
     59 	.DWE(adc_dwe), // write enable
     60 	.DCLK(clk), // clock
     61 	.DRDY(adc_drdy), // data ready out
     62 	.RESET(rst), // reset
     63 	.CONVST(0), // not used
     64 	.CONVSTCLK(0), // not used
     65 
     66 	.VN(vn),
     67 	.VP(vp),
     68 	.VAUXN(aux_channel_n[15:0]),
     69 	.VAUXP(aux_channel_p[15:0]),
     70 
     71 	.ALM(), // alarm outputs
     72 	.OT(), // over temp alarm output
     73 
     74 	.MUXADDR(),// not used
     75 	.CHANNEL(adc_channel), // channel output
     76 
     77 	.EOC(adc_eoc), // end of conversion
     78 	.EOS(adc_eos), // end of sequence
     79 	.BUSY(adc_busy), // busy during adc conversion
     80 
     81 	.JTAGBUSY(),// not used
     82 	.JTAGLOCKED(),// not used
     83 	.JTAGMODIFIED()// not used
     84 );
     85 
     86 localparam ADC_REG_COUNT = 32;
     87 localparam ADC_REG_COUNT_BITS = $clog2(ADC_REG_COUNT);
     88 reg [15:0] adc_data [ADC_REG_COUNT];
     89 
     90 typedef enum {
     91 	WAIT_FOR_EOS,
     92 	READ_REG,
     93 	READ_REG_WAIT
     94 } state_t;
     95 
     96 state_t state = WAIT_FOR_EOS;
     97 reg [ADC_REG_COUNT_BITS-1:0] reg_count;
     98 
     99 /* wait for EOS then pull out readings from each ADC we care about */
    100 always_ff @(posedge clk) begin
    101 	adc_den = 0;
    102 	adc_dwe = 0;
    103 	adc_daddr = 0;
    104 	adc_din = 0;
    105 
    106 	if (rst) begin
    107 		state = WAIT_FOR_EOS;
    108 		for (int i = 0; i < ADC_REG_COUNT; i++)
    109 			adc_data[i] = 0;
    110 	end else begin
    111 		case (state)
    112 		WAIT_FOR_EOS: begin
    113 			reg_count = 0;
    114 			if (adc_eos) state = READ_REG;
    115 		end
    116 		READ_REG: begin
    117 			if (!adc_drdy) begin
    118 				adc_den = 1;
    119 				adc_daddr = { 2'b0, reg_count };
    120 				state = READ_REG_WAIT;
    121 			end
    122 		end
    123 		READ_REG_WAIT: begin
    124 			if (adc_drdy) begin
    125 				adc_data[reg_count] <= adc_dout;
    126 				if (reg_count == ADC_REG_COUNT[ADC_REG_COUNT_BITS-1:0] - 1) begin
    127 					reg_count = 0;
    128 					state = WAIT_FOR_EOS;
    129 				end else begin
    130 					reg_count = reg_count + 1;
    131 					state = READ_REG;
    132 				end
    133 			end
    134 		end
    135 		endcase
    136 	end
    137 end
    138 
    139 /* AXI stuffs */
    140 wire [31:0]wdata;
    141 reg [31:0]rdata;
    142 wire [4:0]wreg;
    143 wire [4:0]rreg;
    144 wire wr;
    145 wire rd;
    146 
    147 axi_registers #(
    148 	.R_ADDR_WIDTH(5)
    149 )
    150 regs(
    151 	.clk(clk),
    152 	.s(axi),
    153 	.o_rreg(rreg),
    154 	.o_wreg(wreg),
    155 	.i_rdata(rdata),
    156 	.o_wdata(wdata),
    157 	.o_rd(rd),
    158 	.o_wr(wr)
    159 	);
    160 
    161 always_comb begin
    162 	rdata = { 16'h0, adc_data[rreg[ADC_REG_COUNT_BITS-1:0]] };
    163 end
    164 
    165 always_ff @(posedge clk) begin
    166 	if (wr) begin
    167 		case (wreg)
    168 		default: ;
    169 		endcase
    170 	end
    171 end
    172 
    173 assign debug_out[0] = adc_eoc;
    174 assign debug_out[1] = adc_eos;
    175 assign debug_out[2] = adc_busy;
    176 assign debug_out[3] = 0;
    177 
    178 endmodule
    179 
    180 // vim: set noexpandtab: