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:
M | Makefile | | | 1 | + |
A | hdl/xadc.sv | | | 180 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | hdl/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