zynq-sandbox

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 2b248574a0cbeb16af03b0f76f36fae59ba6eec2
parent 7963051ca5b4c23bc8397e70e66f121a5a2529c8
Author: Travis Geiselbrecht <geist@foobox.com>
Date:   Mon,  8 Sep 2014 19:03:34 -0700

adc: break the xadc code into a separate module

Diffstat:
MMakefile | 1+
Ahdl/xadc.sv | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mhdl/zybo_adc.sv | 168+++++++++++--------------------------------------------------------------------
3 files changed, 203 insertions(+), 146 deletions(-)

diff --git a/Makefile b/Makefile @@ -12,6 +12,7 @@ MODULE_NAME := zybo-adc MODULE_PART := xc7z010clg400-1 MODULE_SRCS := hdl/zybo_adc.sv MODULE_SRCS += hdl/axi_ifc.sv hdl/axi_registers.sv +MODULE_SRCS += hdl/xadc.sv MODULE_SRCS += hdl/zynq_ps_1m.sv MODULE_SRCS += hdl/zybo_adc.xdc include build/vivado-bitfile.mk diff --git a/hdl/xadc.sv b/hdl/xadc.sv @@ -0,0 +1,180 @@ +// Copyright 2014 Travis Geiselbrecht <geist@foobox.com> +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +`timescale 1ns / 1ps + +module xadc( + input clk, + input rst, + + input vp, + input vn, + input [15:0] aux_channel_n, + input [15:0] aux_channel_p, + + output [3:0] debug_out, + + axi_ifc.slave axi +); + +parameter reg [15:0] CLKDIV = 8; // default ADCCLK divide from input clk +parameter reg [15:0] CHSEL1 = 16'b0000000100000000; // CHSEL1 - enable temperature +parameter reg [15:0] CHSEL2 = 16'b0000000011000000; // CHSEL2 - enable simultaneous channels 6/14, 7/15 + +reg adc_den; +reg adc_dwe; +reg [15:0] adc_din; +wire [15:0] adc_dout; +reg [6:0] adc_daddr; +wire adc_drdy; + +wire [4:0] adc_channel; +wire adc_eoc; +wire adc_eos; +wire adc_busy; + +XADC #( + .INIT_40(16'b1000000000000000),// No averaging + .INIT_41(16'b0100111011110000),// Simultaneous sampling mode, Disable unused ALMs, Enable calibration + .INIT_42(16'b0000000000000000 | (CLKDIV << 8)),// DCLK divide + .INIT_48(CHSEL1), + .INIT_49(CHSEL2), +) +adc0( + .DI(adc_din), // 16 bit in + .DO(adc_dout), // 16 bit out + .DADDR(adc_daddr), // 7 bit address + .DEN(adc_den), // enable + .DWE(adc_dwe), // write enable + .DCLK(clk), // clock + .DRDY(adc_drdy), // data ready out + .RESET(rst), // reset + .CONVST(0), // not used + .CONVSTCLK(0), // not used + + .VN(vn), + .VP(vp), + .VAUXN(aux_channel_n[15:0]), + .VAUXP(aux_channel_p[15:0]), + + .ALM(), // alarm outputs + .OT(), // over temp alarm output + + .MUXADDR(),// not used + .CHANNEL(adc_channel), // channel output + + .EOC(adc_eoc), // end of conversion + .EOS(adc_eos), // end of sequence + .BUSY(adc_busy), // busy during adc conversion + + .JTAGBUSY(),// not used + .JTAGLOCKED(),// not used + .JTAGMODIFIED()// not used +); + +localparam ADC_REG_COUNT = 32; +localparam ADC_REG_COUNT_BITS = $clog2(ADC_REG_COUNT); +reg [15:0] adc_data [ADC_REG_COUNT]; + +typedef enum { + WAIT_FOR_EOS, + READ_REG, + READ_REG_WAIT +} state_t; + +state_t state = WAIT_FOR_EOS; +reg [ADC_REG_COUNT_BITS-1:0] reg_count; + +/* wait for EOS then pull out readings from each ADC we care about */ +always_ff @(posedge clk) begin + adc_den = 0; + adc_dwe = 0; + adc_daddr = 0; + adc_din = 0; + + if (rst) begin + state = WAIT_FOR_EOS; + for (int i = 0; i < ADC_REG_COUNT; i++) + adc_data[i] = 0; + end else begin + case (state) + WAIT_FOR_EOS: begin + reg_count = 0; + if (adc_eos) state = READ_REG; + end + READ_REG: begin + if (!adc_drdy) begin + adc_den = 1; + adc_daddr = { 2'b0, reg_count }; + state = READ_REG_WAIT; + end + end + READ_REG_WAIT: begin + if (adc_drdy) begin + adc_data[reg_count] <= adc_dout; + if (reg_count == ADC_REG_COUNT[ADC_REG_COUNT_BITS-1:0] - 1) begin + reg_count = 0; + state = WAIT_FOR_EOS; + end else begin + reg_count = reg_count + 1; + state = READ_REG; + end + end + end + endcase + end +end + +/* AXI stuffs */ +wire [31:0]wdata; +reg [31:0]rdata; +wire [4:0]wreg; +wire [4:0]rreg; +wire wr; +wire rd; + +axi_registers #( + .R_ADDR_WIDTH(5) +) +regs( + .clk(clk), + .s(axi), + .o_rreg(rreg), + .o_wreg(wreg), + .i_rdata(rdata), + .o_wdata(wdata), + .o_rd(rd), + .o_wr(wr) + ); + +always_comb begin + rdata = { 16'h0, adc_data[rreg[ADC_REG_COUNT_BITS-1:0]] }; +end + +always_ff @(posedge clk) begin + if (wr) begin + case (wreg) + default: ; + endcase + end +end + +assign debug_out[0] = adc_eoc; +assign debug_out[1] = adc_eos; +assign debug_out[2] = adc_busy; +assign debug_out[3] = 0; + +endmodule + +// vim: set noexpandtab: diff --git a/hdl/zybo_adc.sv b/hdl/zybo_adc.sv @@ -1,4 +1,4 @@ -// Copyright 2014 Brian Swetland <swetland@frotz.net> +// Copyright 2014 Travis Geiselbrecht <geist@foobox.com> // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -36,6 +36,8 @@ zynq_ps7 zynq( .m_axi_gp0(axi_ctl) ); +wire vn = 0; +wire vp = 0; wire [15:0] aux_channel_n; wire [15:0] aux_channel_p; @@ -48,155 +50,28 @@ assign aux_channel_p[15] = ja_p[2]; assign aux_channel_n[6] = ja_n[3]; assign aux_channel_p[6] = ja_p[3]; -reg adc_den; -reg adc_dwe; -reg [15:0] adc_din; -wire [15:0] adc_dout; -reg [6:0] adc_daddr; -wire adc_drdy; - -wire [4:0] adc_channel; -wire adc_eoc; -wire adc_eos; -wire adc_busy; - -(* DONT_TOUCH = "true" *) -XADC #( - .INIT_40(16'h9000),// averaging of 16 selected for external channels - .INIT_41(16'h2ef0),// Continuous Seq Mode, Disable unused ALMs, Enable calibration - .INIT_42(16'h0500),// DCLK divide 125Mhz / 5 - .INIT_48(16'b0000011100000001),// CHSEL1 - enable Temp, VCCINT, VCCAUX, and calibration - .INIT_49(16'b1100000011000000),// CHSEL2 - enable aux channels 15, 14, 7, 6 -) -adc0( - .DI(adc_din), // 16 bit in - .DO(adc_dout), // 16 bit out - .DADDR(adc_daddr), // 7 bit address - .DEN(adc_den), // enable - .DWE(adc_dwe), // write enable - .DCLK(axiclk), // clock - .DRDY(adc_drdy), // data ready out - .RESET(0), // reset - .CONVST(0), // not used - .CONVSTCLK(0), // not used - - .VP(0), - .VN(0), - .VAUXN(aux_channel_n[15:0]), - .VAUXP(aux_channel_p[15:0]), - - .ALM(), // alarm outputs - .OT(), // over temp alarm output - - .MUXADDR(),// not used - .CHANNEL(adc_channel), // channel output - - .EOC(adc_eoc), // end of conversion - .EOS(adc_eos), // end of sequence - .BUSY(adc_busy), // busy during adc conversion - - .JTAGBUSY(),// not used - .JTAGLOCKED(),// not used - .JTAGMODIFIED()// not used -); +wire [3:0] adc_debug_out; -parameter integer ADC_REG_COUNT = 8; -reg [15:0] adc_data [ADC_REG_COUNT]; - -typedef enum { - WAIT_FOR_EOS, - READ_REG, - READ_REG_WAIT -} state_t; - -state_t state = WAIT_FOR_EOS; -int reg_count; -reg [6:0] reg_num; - -/* mapping of current register count to XADC register */ -always_comb begin - case (reg_count) - 0: reg_num = 7'h0; // temperature - 1: reg_num = 7'h1; // VCCINT - 2: reg_num = 7'h2; // VCCAUX - 3: reg_num = 7'h5; // VCCREFN - 4: reg_num = 7'h10 + 7'd14; // AD14 - 5: reg_num = 7'h10 + 7'd6; // AD6 - 6: reg_num = 7'h10 + 7'd15; // AD15 - 7: reg_num = 7'h10 + 7'd7; // AD7 - default: reg_num = 0; - endcase -end - -/* wait for EOS then pull out readings from each ADC we care about */ -always_ff @(posedge axiclk) begin - adc_den = 0; - adc_dwe = 0; - adc_daddr = 0; - adc_din = 0; - case (state) - WAIT_FOR_EOS: begin - reg_count = 0; - if (adc_eos == 1) state = READ_REG; - end - READ_REG: begin - if (adc_drdy == 0) begin - adc_den = 1; - adc_daddr = reg_num[6:0]; - state = READ_REG_WAIT; - end - end - READ_REG_WAIT: begin - if (adc_drdy) begin - adc_data[reg_count] <= adc_dout; - reg_count = reg_count + 1; - if (reg_count == ADC_REG_COUNT) begin - state = WAIT_FOR_EOS; - end else begin - state = READ_REG; - end - end - end - endcase -end - -/* AXI stuffs */ -wire [31:0]wdata; -reg [31:0]rdata; -wire [2:0]wreg; -wire [2:0]rreg; -wire wr; -wire rd; - -axi_registers #( - .R_ADDR_WIDTH(3) +xadc #( + .CLKDIV(5) ) -regs( +adc( .clk(axiclk), - .s(axi_ctl), - .o_rreg(rreg), - .o_wreg(wreg), - .i_rdata(rdata), - .o_wdata(wdata), - .o_rd(rd), - .o_wr(wr) - ); + .rst(btn[0]), + + .vn(vn), + .vp(vp), + .aux_channel_n(aux_channel_n), + .aux_channel_p(aux_channel_p), + + .debug_out(adc_debug_out), + + .axi(axi_ctl) +); -always_comb begin - rdata = { 16'h0, adc_data[rreg[2:0]] }; -end - -always_ff @(posedge axiclk) begin - if (wr) begin - case (wreg) - 0: ; - 1: ; - 2: ; - 3: ; - endcase - end -end +assign jb_p = adc_debug_out; +/* // debugging assign led[0] = adc_eoc; assign led[1] = adc_eos; @@ -204,7 +79,8 @@ assign led[2] = adc_busy; assign jb_p[0] = adc_eoc; assign jb_p[1] = adc_eos; -assign jb_p[2] = adc_busy; +assign jb_p[2] = rd; +*/ endmodule