From 8cccea85e0945f3503b5b51a297a922c8cf19e7f Mon Sep 17 00:00:00 2001 From: Joppe Blondel Date: Wed, 4 Mar 2026 23:35:02 +0100 Subject: [PATCH] Added adc->dac path test --- .../lvds_comparator_spartan6.v | 4 +- cores/system/mcu/rtl/mcu_peripherals.v | 7 +- cores/system/mimas_sd_adc_r2r/mimas.ucf | 54 +++++++++++ .../mimas_sd_adc_r2r/mimas_sd_adc_r2r.core | 46 ++++++++++ cores/system/mimas_sd_adc_r2r/options.tcl | 2 + cores/system/mimas_sd_adc_r2r/rtl/toplevel.v | 91 +++++++++++++++++++ cores/system/test/sw/sweep/sweep.c | 6 +- cores/wb/wb_gpio_banks/rtl/wb_gpio_banks.v | 6 +- 8 files changed, 204 insertions(+), 12 deletions(-) create mode 100644 cores/system/mimas_sd_adc_r2r/mimas.ucf create mode 100644 cores/system/mimas_sd_adc_r2r/mimas_sd_adc_r2r.core create mode 100644 cores/system/mimas_sd_adc_r2r/options.tcl create mode 100644 cores/system/mimas_sd_adc_r2r/rtl/toplevel.v diff --git a/cores/primitive/lvds_comparator/lvds_comparator_spartan6.v b/cores/primitive/lvds_comparator/lvds_comparator_spartan6.v index 2eeaa04..958f88b 100644 --- a/cores/primitive/lvds_comparator/lvds_comparator_spartan6.v +++ b/cores/primitive/lvds_comparator/lvds_comparator_spartan6.v @@ -5,10 +5,10 @@ module lvds_comparator_spartan6_impl ( ); IBUFDS #( .DIFF_TERM("FALSE"), - .IOSTANDARD("LVDS33") + .IOSTANDARD("LVDS_33") ) lvds_buf ( .O(o), .I(a), .IB(b) ); -endmodule \ No newline at end of file +endmodule diff --git a/cores/system/mcu/rtl/mcu_peripherals.v b/cores/system/mcu/rtl/mcu_peripherals.v index ec3d61b..adec532 100644 --- a/cores/system/mcu/rtl/mcu_peripherals.v +++ b/cores/system/mcu/rtl/mcu_peripherals.v @@ -91,11 +91,10 @@ module mcu_peripherals ( ); wb_gpio_banks #( - .BASE_ADDR(GPIO_BASE_ADDR), - .NUM_BANKS(4) + .num_banks(4) ) gpio ( - .i_wb_clk(i_clk), - .i_wb_rst(i_rst), + .i_clk(i_clk), + .i_rst(i_rst), .i_wb_dat(gpio_wbs_dat_w), .i_wb_adr(gpio_wbs_adr), .i_wb_we(gpio_wbs_we), diff --git a/cores/system/mimas_sd_adc_r2r/mimas.ucf b/cores/system/mimas_sd_adc_r2r/mimas.ucf new file mode 100644 index 0000000..3d3524c --- /dev/null +++ b/cores/system/mimas_sd_adc_r2r/mimas.ucf @@ -0,0 +1,54 @@ +# Main clock input +NET "aclk" LOC = P126; +NET "aclk" TNM_NET = "SYS_CLK_PIN"; +TIMESPEC TS_SYS_CLK_PIN = PERIOD "SYS_CLK_PIN" 10 ns HIGH 50 %; + +# Boards button row +NET "aresetn" LOC = P120; +NET "aresetn" IOSTANDARD = LVCMOS33; +NET "aresetn" PULLUP; + +NET "adc_a" LOC = P33; +NET "adc_a" IOSTANDARD = LVDS_33; +NET "adc_b" LOC = P32; +NET "adc_b" IOSTANDARD = LVDS_33; +NET "adc_o" LOC = P34; +NET "adc_o" IOSTANDARD = LVCMOS33; + +NET "r2r[0]" LOC = P131; +NET "r2r[1]" LOC = P133; +NET "r2r[2]" LOC = P137; +NET "r2r[3]" LOC = P139; +NET "r2r[4]" LOC = P141; +NET "r2r[5]" LOC = P1; +NET "r2r[0]" IOSTANDARD = LVCMOS33; +NET "r2r[1]" IOSTANDARD = LVCMOS33; +NET "r2r[2]" IOSTANDARD = LVCMOS33; +NET "r2r[3]" IOSTANDARD = LVCMOS33; +NET "r2r[4]" IOSTANDARD = LVCMOS33; +NET "r2r[5]" IOSTANDARD = LVCMOS33; + +NET "LED[0]" LOC = P119; +NET "LED[0]" IOSTANDARD = LVCMOS33; +NET "LED[0]" DRIVE = 8; +NET "LED[1]" LOC = P118; +NET "LED[1]" IOSTANDARD = LVCMOS33; +NET "LED[1]" DRIVE = 8; +NET "LED[2]" LOC = P117; +NET "LED[2]" IOSTANDARD = LVCMOS33; +NET "LED[2]" DRIVE = 8; +NET "LED[3]" LOC = P116; +NET "LED[3]" IOSTANDARD = LVCMOS33; +NET "LED[3]" DRIVE = 8; +NET "LED[4]" LOC = P115; +NET "LED[4]" IOSTANDARD = LVCMOS33; +NET "LED[4]" DRIVE = 8; +NET "LED[5]" LOC = P114; +NET "LED[5]" IOSTANDARD = LVCMOS33; +NET "LED[5]" DRIVE = 8; +NET "LED[6]" LOC = P112; +NET "LED[6]" IOSTANDARD = LVCMOS33; +NET "LED[6]" DRIVE = 8; +NET "LED[7]" LOC = P111; +NET "LED[7]" IOSTANDARD = LVCMOS33; +NET "LED[7]" DRIVE = 8; diff --git a/cores/system/mimas_sd_adc_r2r/mimas_sd_adc_r2r.core b/cores/system/mimas_sd_adc_r2r/mimas_sd_adc_r2r.core new file mode 100644 index 0000000..722f1b8 --- /dev/null +++ b/cores/system/mimas_sd_adc_r2r/mimas_sd_adc_r2r.core @@ -0,0 +1,46 @@ +CAPI=2: + +name: joppeb:system:mimas_sd_adc_r2r:1.0 +description: Mimas top-level wiring sigma-delta ADC output directly to R2R DAC + +filesets: + rtl: + depend: + - joppeb:primitive:clkgen + - joppeb:signal:sd_adc_q15 + - joppeb:util:conv + files: + - rtl/toplevel.v + file_type: verilogSource + + mimas: + files: + - mimas.ucf : {file_type : UCF} + - options.tcl : {file_type : tclSource} + +targets: + default: + filesets: + - rtl + toplevel: toplevel + + mimas: + filesets: + - rtl + - mimas + toplevel: toplevel + parameters: + - FPGA_SPARTAN6=true + default_tool: ise + tools: + ise: + family: Spartan6 + device: xc6slx9 + package: tqg144 + speed: -2 + +parameters: + FPGA_SPARTAN6: + datatype: bool + description: Select Spartan-6 family specific implementations + paramtype: vlogdefine diff --git a/cores/system/mimas_sd_adc_r2r/options.tcl b/cores/system/mimas_sd_adc_r2r/options.tcl new file mode 100644 index 0000000..62c6220 --- /dev/null +++ b/cores/system/mimas_sd_adc_r2r/options.tcl @@ -0,0 +1,2 @@ +project set "Create Binary Configuration File" TRUE -process "Generate Programming File" +project set "Keep Hierarchy" Yes -process "Synthesize - XST" diff --git a/cores/system/mimas_sd_adc_r2r/rtl/toplevel.v b/cores/system/mimas_sd_adc_r2r/rtl/toplevel.v new file mode 100644 index 0000000..f729a5c --- /dev/null +++ b/cores/system/mimas_sd_adc_r2r/rtl/toplevel.v @@ -0,0 +1,91 @@ +`timescale 1ns/1ps + +module toplevel( + input wire aclk, + input wire aresetn, + + input wire adc_a, + input wire adc_b, + output wire adc_o, + + output wire [5:0] r2r, + output wire [7:0] LED +); + `include "conv.vh" + + // Clocking + wire clk_100; + assign clk_100 = aclk; + wire clk_15; + clkgen #( + .CLK_IN_HZ(100000000), + .CLKFX_DIVIDE(20), + .CLKFX_MULTIPLY(3) + ) clk_gen_15 ( + .clk_in(clk_100), + .clk_out(clk_15) + ); + + // Asynchronous assert on reset button, synchronous release in clk_15 domain. + localparam [17:0] RESET_RELEASE_CYCLES = 18'd150000; // ~10 ms @ 15 MHz + reg [17:0] rst_cnt = 18'd0; + reg sys_reset_r = 1'b1; + always @(posedge clk_15 or negedge aresetn) begin + if (!aresetn) begin + rst_cnt <= 18'd0; + sys_reset_r <= 1'b1; + end else if (sys_reset_r) begin + if (rst_cnt == RESET_RELEASE_CYCLES - 1'b1) + sys_reset_r <= 1'b0; + else + rst_cnt <= rst_cnt + 1'b1; + end + end + + wire signed [15:0] signal_q15; + wire signal_valid; + sd_adc_q15 #( + .R_OHM(3300), + .C_PF(220) + ) sd_adc ( + .i_clk_15(clk_15), + .i_rst_n(!sys_reset_r), + .i_adc_a(adc_a), + .i_adc_b(adc_b), + .o_adc(adc_o), + .o_signal_q15(signal_q15), + .o_signal_valid(signal_valid) + ); + + // signal_q15 is unipolar and biased (0-3.3V -> 0..32767) + reg signed [15:0] signal_unbiased_q15 = 16'sd0; + reg signal_unbiased_valid = 1'b0; + localparam bias = 2**14; + localparam gain = 2; + always @(posedge clk_15) begin + if (sys_reset_r) begin + signal_unbiased_q15 <= 16'sd0; + signal_unbiased_valid <= 1'b0; + end else begin + signal_unbiased_valid <= signal_valid; + if (signal_valid) begin + signal_unbiased_q15 <= (signal_q15 - $signed(bias)) * gain; + end + end + end + + reg [5:0] dac_code = 6'd0; + always @(posedge clk_15) begin + if (sys_reset_r) + dac_code <= 6'd0; + else if (signal_unbiased_valid) + dac_code <= q15_to_uq16(signal_unbiased_q15) >> 10; + end + + assign r2r = dac_code; + + // Quick status indication: show ADC validity and most recent DAC code. + assign LED[0] = signal_valid; + assign LED[6:1] = dac_code; + assign LED[7] = sys_reset_r; +endmodule diff --git a/cores/system/test/sw/sweep/sweep.c b/cores/system/test/sw/sweep/sweep.c index 447ba27..5a8e866 100644 --- a/cores/system/test/sw/sweep/sweep.c +++ b/cores/system/test/sw/sweep/sweep.c @@ -35,13 +35,13 @@ void main(){ irq_init(); *LEDGR = 1; - *TIMER_LD = 2 * 15000000/1000; + *TIMER_LD = 1000 * 15000; for(;;){ - for(int i=1000; i<10000; i+=10){ + for(int i=500; i<6000; i+=10){ *R_FREQ = i; *LEDS = i>>4; - // for(int j=0; j<80; j++) asm volatile("nop"); + for(int j=0; j<800; j++) asm volatile("nop"); } } } \ No newline at end of file diff --git a/cores/wb/wb_gpio_banks/rtl/wb_gpio_banks.v b/cores/wb/wb_gpio_banks/rtl/wb_gpio_banks.v index 04476ec..7b2cc81 100644 --- a/cores/wb/wb_gpio_banks/rtl/wb_gpio_banks.v +++ b/cores/wb/wb_gpio_banks/rtl/wb_gpio_banks.v @@ -13,7 +13,7 @@ module wb_gpio_banks #( input wire i_wb_we, input wire i_wb_cyc, input wire i_wb_stb, - output wire o_wb_ack, + output reg o_wb_ack, input wire [num_banks*32-1:0] i_gpio, output wire [num_banks*32-1:0] o_gpio @@ -48,8 +48,8 @@ module wb_gpio_banks #( integer bi; always @* begin - o_wb_rdt = 0; - o_wb_ack = 0; + o_wb_rdt = 32'h00000000; + o_wb_ack = 1'b0; for(bi=0; bi