diff --git a/firmware/rtl/base/base.v.m4 b/firmware/rtl/base/base.v.m4 index 84d8b03..041616f 100644 --- a/firmware/rtl/base/base.v.m4 +++ b/firmware/rtl/base/base.v.m4 @@ -43,6 +43,7 @@ m4_define(m4_dac_wires, ⟨ /* Same thing but for ADCs */ m4_define(m4_adc_wires, ⟨ + input [$3-1:0] adc_sel_$2, output adc_finished_$2, input adc_arm_$2, output [$1-1:0] from_adc_$2 @@ -86,6 +87,7 @@ m4_define(m4_dac_switch, ⟨ .SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ) ) dac_master_$2 ( .clk(clk), + .rst_L(rst_L), .mosi(mosi_port_$2[0]), .miso(miso_port_$2[0]), .sck_wire(sck_port_$2[0]), @@ -135,6 +137,27 @@ m4_define(m4_dac_switch, ⟨ /* Same thing but for ADCs */ m4_define(m4_adc_switch, ⟨ + wire adc_mosi_unused_output_$2; + wire [$3-1:0] adc_mosi_port_$2; /* Unused! */ + wire [$3-1:0] adc_sdo_port_$2; + wire [$3-1:0] adc_sck_port_$2; + wire [$3-1:0] adc_conv_L_port_$2; + + spi_switch #( + .PORTS($3) + ) adc_switch_$2 ( + .select(adc_sel_$2), + .mosi(adc_mosi_unused_output_$2), + .miso(adc_sdo[$2]), + .sck(adc_sck[$2]), + .ss_L(adc_conv_L[$2]), + + .mosi_ports(adc_mosi_port_$2), + .miso_ports(adc_sdo_port_$2), + .sck_ports(adc_sck_port_$2), + .ss_L_ports(adc_conv_L_port_$2) + ); + spi_master_ss_no_write #( .WID($1), .WID_LEN(ADC_WID_SIZ), @@ -146,13 +169,21 @@ m4_define(m4_adc_switch, ⟨ .PHASE(ADC_PHASE) ) adc_master_$2 ( .clk(clk), - .miso(adc_sdo[$2]), - .sck_wire(adc_sck[$2]), - .ss_L(adc_conv_L[$2]), + .rst_L(rst_L), + .miso(adc_sdo_port_$2[0]), + .sck_wire(adc_sck_port_$2[0]), + .ss_L(adc_conv_L_port_$2[0]), .finished(adc_finished_$2), .arm(adc_arm_$2), .from_slave(from_adc_$2) - ) + ); + +/* 2nd option for each ADC is the non-converting option. + * This is used to flush output from reset ADCs. + */ + assign adc_sdo_port[1] = adc_sdo_port[0]; + assign adc_sck_port[1] = adc_sck_port[0]; + assign adc_conv_L_port[1] = 1; ⟩) /*********************************************************/ @@ -181,7 +212,7 @@ m4_define(DAC_PORTS_CONTROL_LOOP, (DAC_PORTS + 1)) parameter WF_RAM_WORD_WID = 16, parameter WF_RAM_WORD_INCR = 2, - parameter ADC_PORTS = 1, + parameter ADC_PORTS = 2, m4_define(ADC_PORTS_CONTROL_LOOP, (ADC_PORTS + 1)) parameter ADC_NUM = 8, /* Three types of ADC. For now assume that their electronics @@ -211,6 +242,7 @@ m4_define(CL_DATA_WID, CL_CONSTS_WID) parameter CL_CYCLE_COUNT_WID = 18 ) ( input clk, + input rst_L, output [DAC_NUM-1:0] dac_mosi, input [DAC_NUM-1:0] dac_miso, @@ -230,16 +262,14 @@ m4_define(CL_DATA_WID, CL_CONSTS_WID) m4_dac_wires(DAC_PORTS, 6), m4_dac_wires(DAC_PORTS, 7), - input [ADC_PORTS_CONTROL_LOOP-1:0] adc_sel_0, - - m4_adc_wires(ADC_TYPE1_WID, 0), - m4_adc_wires(ADC_TYPE1_WID, 1), - m4_adc_wires(ADC_TYPE1_WID, 2), - m4_adc_wires(ADC_TYPE1_WID, 3), - m4_adc_wires(ADC_TYPE1_WID, 4), - m4_adc_wires(ADC_TYPE1_WID, 5), - m4_adc_wires(ADC_TYPE1_WID, 6), - m4_adc_wires(ADC_TYPE1_WID, 7), + m4_adc_wires(ADC_TYPE1_WID, 0, ADC_PORTS_CONTROL_LOOP), + m4_adc_wires(ADC_TYPE1_WID, 1, ADC_PORTS), + m4_adc_wires(ADC_TYPE1_WID, 2, ADC_PORTS), + m4_adc_wires(ADC_TYPE1_WID, 3, ADC_PORTS), + m4_adc_wires(ADC_TYPE1_WID, 4, ADC_PORTS), + m4_adc_wires(ADC_TYPE1_WID, 5, ADC_PORTS), + m4_adc_wires(ADC_TYPE1_WID, 6, ADC_PORTS), + m4_adc_wires(ADC_TYPE1_WID, 7, ADC_PORTS), output cl_in_loop, input [M4_CONTROL_LOOP_CMD_WIDTH-1:0] cl_cmd, @@ -263,58 +293,53 @@ m4_dac_switch(DAC_PORTS, 5); m4_dac_switch(DAC_PORTS, 6); m4_dac_switch(DAC_PORTS, 7); -reg [ADC_CYCLE_HALF_WAIT_SIZ-1:0] counter = 0; +initial test_clock <= 0; +reg [8-1:0] counter = 0; +/* always @ (posedge clk) begin - if (counter >= ADC_CYCLE_HALF_WAIT) begin + if (!rst_L) begin + counter <= 0; + test_clock <= 0; + end else if (counter >= ADC_CYCLE_HALF_WAIT) begin counter <= 0; test_clock <= !test_clock; end else begin counter <= counter + 1; end end +*/ +/* +always @ (posedge clk) begin + if(!rst_L) begin + test_clock <= 0; + end else begin + test_clock <= !test_clock; + end +end +*/ +always @ (posedge clk) begin + if (!rst_L) begin + counter <= 0; + test_clock <= 0; + end else begin + if (counter >= 3) begin + counter <= 0; + test_clock <= !test_clock; + end else begin + counter <= counter + 1; + end + end +end -/* 1st adc is Type 1 (18 bit) */ - -wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_conv_L_port_0; -wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_sdo_port_0; -wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_sck_port_0; -wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_mosi_port_0_unassigned; -wire adc_mosi_unassigned; - -spi_switch #( - .PORTS(ADC_PORTS_CONTROL_LOOP) -) switch_adc_0 ( - .select(adc_sel_0), - .mosi(adc_mosi_unassigned), - .miso(adc_sdo[0]), - .sck(adc_sck[0]), - .ss_L(adc_conv_L[0]), - - .mosi_ports(adc_mosi_port_0_unassigned), - .miso_ports(adc_sdo_port_0), - .sck_ports(adc_sck_port_0), - .ss_L_ports(adc_conv_L_port_0) -); - -spi_master_ss_no_write #( - .WID(ADC_TYPE1_WID), - .WID_LEN(ADC_WID_SIZ), - .CYCLE_HALF_WAIT(ADC_CYCLE_HALF_WAIT), - .TIMER_LEN(ADC_CYCLE_HALF_WAIT_SIZ), - .SS_WAIT(ADC_CONV_WAIT), - .SS_WAIT_TIMER_LEN(ADC_CONV_WAIT_SIZ), - .POLARITY(ADC_POLARITY), - .PHASE(ADC_PHASE) -) adc_master_0 ( - .clk(clk), - .miso(adc_sdo_port_0[0]), - .sck_wire(adc_sck_port_0[0]), - .ss_L(adc_conv_L_port_0[0]), - .finished(adc_finished_0), - .arm(adc_arm_0), - .from_slave(from_adc_0) -); +m4_adc_switch(ADC_TYPE1_WID, 0, ADC_PORTS_CONTROL_LOOP); +m4_adc_switch(ADC_TYPE1_WID, 1, ADC_PORTS); +m4_adc_switch(ADC_TYPE1_WID, 2, ADC_PORTS); +m4_adc_switch(ADC_TYPE1_WID, 3, ADC_PORTS); +m4_adc_switch(ADC_TYPE1_WID, 4, ADC_PORTS); +m4_adc_switch(ADC_TYPE1_WID, 5, ADC_PORTS); +m4_adc_switch(ADC_TYPE1_WID, 6, ADC_PORTS); +m4_adc_switch(ADC_TYPE1_WID, 7, ADC_PORTS); control_loop #( .ADC_WID(ADC_TYPE1_WID), @@ -342,14 +367,15 @@ control_loop #( .DAC_SS_WAIT_SIZ(DAC_SS_WAIT_SIZ) ) cl ( .clk(clk), + .rst_L(rst_L), .in_loop(cl_in_loop), .dac_mosi(mosi_port_0[2]), .dac_miso(miso_port_0[2]), .dac_ss_L(ss_L_port_0[2]), .dac_sck(sck_port_0[2]), - .adc_miso(adc_sdo_port_0[1]), - .adc_conv_L(adc_conv_L_port_0[1]), - .adc_sck(adc_sck_port_0[1]), + .adc_miso(adc_sdo_port_0[2]), + .adc_conv_L(adc_conv_L_port_0[2]), + .adc_sck(adc_sck_port_0[2]), .cmd(cl_cmd), .word_in(cl_word_in), .word_out(cl_word_out), @@ -357,12 +383,4 @@ control_loop #( .finish_cmd(cl_finish_cmd) ); -m4_adc_switch(ADC_TYPE1_WID, 1); -m4_adc_switch(ADC_TYPE1_WID, 2); -m4_adc_switch(ADC_TYPE1_WID, 3); -m4_adc_switch(ADC_TYPE1_WID, 4); -m4_adc_switch(ADC_TYPE1_WID, 5); -m4_adc_switch(ADC_TYPE1_WID, 6); -m4_adc_switch(ADC_TYPE1_WID, 7); - endmodule diff --git a/firmware/rtl/common.makefile b/firmware/rtl/common.makefile index fc712e0..4d9df90 100644 --- a/firmware/rtl/common.makefile +++ b/firmware/rtl/common.makefile @@ -1,7 +1,7 @@ # Generate verilog from m4 file +#m4 -P --synclines $< | awk -v filename=$< '/^#line/ {printf("`line %d %s 0\n", $$2, filename); next} {print}' > $@ +# NOTE: f4pga yosys does not support `line directives. Use above for debug. %.v: %.v.m4 - #m4 -P --synclines $< | awk -v filename=$< '/^#line/ {printf("`line %d %s 0\n", $$2, filename); next} {print}' > $@ - # NOTE: f4pga yosys does not support `line directives. Use above for debug. m4 -P $< > $@ %_preprocessed.v: %.v verilator -P -E $< > $@ diff --git a/firmware/rtl/control_loop/adc_sim.v b/firmware/rtl/control_loop/adc_sim.v index c115a4a..5647e9a 100644 --- a/firmware/rtl/control_loop/adc_sim.v +++ b/firmware/rtl/control_loop/adc_sim.v @@ -7,6 +7,7 @@ module adc_sim #( input clk, input [WID-1:0] indat, + input rst_L, output reg request, input fulfilled, output err, @@ -26,7 +27,14 @@ reg rdy = 0; wire spi_fin; always @ (posedge clk) begin - if (ss && !ss_raised) begin + if (!rst_L) begin + ss_raised <= 0; + fulfilled_raised <= 0; + ss_buf_L <= 1; + data <= 0; + rdy <= 0; + request <= 0; + end else if (ss && !ss_raised) begin request <= 1; ss_raised <= 1; end else if (ss_raised && !ss) begin @@ -56,6 +64,7 @@ spi_slave_no_read #( ) spi ( .clk(clk), .sck(sck), + .rst_L(rst_L), .ss_L(ss_buf_L), .miso(miso), .to_master(data), diff --git a/firmware/rtl/control_loop/control_loop.v.m4 b/firmware/rtl/control_loop/control_loop.v.m4 index de0a6e3..08dd3a5 100644 --- a/firmware/rtl/control_loop/control_loop.v.m4 +++ b/firmware/rtl/control_loop/control_loop.v.m4 @@ -41,6 +41,7 @@ m4_define(M4_E_WID, (DAC_DATA_WID + 1)) parameter DAC_SS_WAIT_SIZ = 3 ) ( input clk, + input rst_L, output in_loop, output dac_mosi, @@ -64,6 +65,7 @@ m4_define(M4_E_WID, (DAC_DATA_WID + 1)) reg dac_arm; reg dac_finished; +wire dac_ready_to_arm_unused; reg [DAC_WID-1:0] to_dac; /* verilator lint_off UNUSED */ @@ -80,6 +82,8 @@ spi_master_ss #( .SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ) ) dac_master ( .clk(clk), + .rst_L(rst_L), + .ready_to_arm(dac_ready_to_arm_unused), .mosi(dac_mosi), .miso(dac_miso), .sck_wire(dac_sck), @@ -93,6 +97,7 @@ spi_master_ss #( reg adc_arm; reg adc_finished; wire [ADC_WID-1:0] measured_value; +wire adc_ready_to_arm_unused; localparam [3-1:0] DAC_REGISTER = 3'b001; @@ -107,6 +112,8 @@ spi_master_ss_no_write #( .SS_WAIT_TIMER_LEN(ADC_CONV_WAIT_SIZ) ) adc_master ( .clk(clk), + .ready_to_arm(adc_ready_to_arm_unused), + .rst_L(rst_L), .arm(adc_arm), .from_slave(measured_value), .miso(adc_miso), @@ -166,6 +173,7 @@ control_loop_math #( .ADC_TO_DAC({32'b01000001100, 32'b01001001101110100101111000110101}) ) math ( .clk(clk), + .rst_L(rst_L), .arm(arm_math), .finished(math_finished), .setpt(setpt), @@ -228,7 +236,10 @@ reg [DELAY_WID-1:0] timer = 0; /**** Timing. ****/ always @ (posedge clk) begin - if (state == CYCLE_START && timer == 0) begin + if (!rst_L) begin + counting_timer <= 0; + last_timer <= 0; + end else if (state == CYCLE_START && timer == 0) begin counting_timer <= 1; last_timer <= counting_timer; end else if (running) begin @@ -245,7 +256,11 @@ wire write_control = state == CYCLE_START || !running; reg dirty_bit = 0; always @ (posedge clk) begin - if (start_cmd && !finish_cmd) begin + if (!rst_L) begin + dirty_bit <= 0; + finish_cmd <= 0; + word_out <= 0; + end else if (start_cmd && !finish_cmd) begin case (cmd) M4_CONTROL_LOOP_NOOP: finish_cmd <= 1; @@ -331,7 +346,21 @@ end assign in_loop = state != INIT_READ_FROM_DAC || running; always @ (posedge clk) begin - case (state) + if (!rst_L) begin + to_dac <= 0; + dac_arm <= 0; + state <= INIT_READ_FROM_DAC; + timer <= 0; + stored_dac_val <= 0; + setpt <= 0; + dely <= 0; + cl_I_reg <= 0; + adjval_prev <= 0; + err_prev <= 0; + + adc_arm <= 0; + arm_math <= 0; + end else case (state) INIT_READ_FROM_DAC: begin if (running) begin to_dac <= {1'b1, DAC_REGISTER, 20'b0}; diff --git a/firmware/rtl/control_loop/control_loop_math.v.m4 b/firmware/rtl/control_loop/control_loop_math.v.m4 index 2c6dab8..53d3273 100644 --- a/firmware/rtl/control_loop/control_loop_math.v.m4 +++ b/firmware/rtl/control_loop/control_loop_math.v.m4 @@ -42,6 +42,7 @@ m4_define(M4_E_WID, (DAC_WID + 1)) ) ( input clk, input arm, + input rst_L, output reg finished, input signed [ADC_WID-1:0] setpt, @@ -86,6 +87,7 @@ boothmul #( .a1(a1), .a2(a2), .clk(clk), + .rst_L(rst_L), .outn(out_untrunc), .fin(mul_fin), .arm(mul_arm) @@ -175,7 +177,23 @@ wire signed [M4_CONSTS_WID-1:0] tmpstore_view = tmpstore[M4_CONSTS_WID-1:0]; always @ (posedge clk) begin - case (state) + if (!rst_L) begin + state <= WAIT_ON_ARM; + a1 <= 0; + finished <= 0; + mul_arm <= 0; + a2 <= 0; + e_cur <= 0; +`ifdef DEBUG_CONTROL_LOOP_MATH + dt_reg <= 0; + idt_reg <= 0; + epidt_reg <= 0; + ep_reg <= 0; +`endif + add_sat <= 0; + adj_val <= 0; + tmpstore <= 0; + end else case (state) WAIT_ON_ARM: if (arm) begin a1[CONSTS_FRAC-1:0] <= 0; diff --git a/firmware/rtl/control_loop/control_loop_math_sim.cpp b/firmware/rtl/control_loop/control_loop_math_sim.cpp index 3141843..ba284d9 100644 --- a/firmware/rtl/control_loop/control_loop_math_sim.cpp +++ b/firmware/rtl/control_loop/control_loop_math_sim.cpp @@ -67,6 +67,7 @@ static void calculate() { int main(int argc, char **argv) { init(argc, argv); mod->arm = 0; + mod->rst_L = 1; run_clock(); Transfer func = Transfer{150, 0, 2, 1.1, 10, -1}; diff --git a/firmware/rtl/control_loop/control_loop_sim_top.v b/firmware/rtl/control_loop/control_loop_sim_top.v index f77bb3f..2df0c98 100644 --- a/firmware/rtl/control_loop/control_loop_sim_top.v +++ b/firmware/rtl/control_loop/control_loop_sim_top.v @@ -19,6 +19,7 @@ module control_loop_sim_top #( parameter DELAY_WID = 16 )( input clk, + input rst_L, output in_loop, output [DAC_DATA_WID-1:0] curset, @@ -53,6 +54,7 @@ adc_sim #( .PHASE(ADC_PHASE) ) adc ( .clk(clk), + .rst_L(rst_L), .indat(measured_value), .request(request), .fulfilled(fulfilled), @@ -77,6 +79,7 @@ dac_sim #( .PHASE(DAC_PHASE) ) dac ( .clk(clk), + .rst_L(rst_L), .curset(curset), .mosi(dac_mosi), .miso(dac_miso), @@ -105,6 +108,7 @@ control_loop #( .DAC_PHASE(DAC_PHASE) ) cloop ( .clk(clk), + .rst_L(rst_L), .in_loop(in_loop), .dac_mosi(dac_mosi), .dac_miso(dac_miso), diff --git a/firmware/rtl/control_loop/dac_sim.v b/firmware/rtl/control_loop/dac_sim.v index 09659a5..55f9140 100644 --- a/firmware/rtl/control_loop/dac_sim.v +++ b/firmware/rtl/control_loop/dac_sim.v @@ -6,6 +6,7 @@ module dac_sim #( parameter WID_LEN = 5 ) ( input clk, + input rst_L, output reg [DATA_WID-1:0] curset, @@ -23,7 +24,12 @@ wire spi_fin; reg [WID-4-1:0] ctrl_register = 0; always @ (posedge clk) begin - if (spi_fin) begin + if (!rst_L) begin + curset <= 0; + to_master <= 0; + rdy <= 0; + ctrl_register <= 0; + end else if (spi_fin) begin rdy <= 0; case (from_master[WID-1:WID-4]) 4'b1001: begin @@ -56,6 +62,7 @@ spi_slave #( .clk(clk), .sck(sck), .ss_L(ss_L), + .rst_L(rst_L), .miso(miso), .mosi(mosi), .from_master(from_master), diff --git a/firmware/rtl/spi/Makefile b/firmware/rtl/spi/Makefile index 3c47032..7078106 100644 --- a/firmware/rtl/spi/Makefile +++ b/firmware/rtl/spi/Makefile @@ -1,6 +1,7 @@ # Makefile for tests and hardware verification. .PHONY: test clean codegen +include ../common.makefile all: test codegen test: obj_dir/Vspi_switch diff --git a/firmware/rtl/spi/spi_master.v b/firmware/rtl/spi/spi_master.v index b4fe047..82463c2 100644 --- a/firmware/rtl/spi/spi_master.v +++ b/firmware/rtl/spi/spi_master.v @@ -1,4 +1,4 @@ -/* (c) Peter McGoron 2022 v0.2 +/* (c) Peter McGoron 2022 v0.3 * This Source Code Form is subject to the terms of the Mozilla Public * License, v.2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. @@ -30,6 +30,7 @@ spi_master ) ( input clk, + input rst_L, `ifndef SPI_MASTER_NO_READ output reg [WID-1:0] from_slave, input miso, @@ -40,6 +41,7 @@ spi_master `endif output reg sck_wire, output reg finished, + output reg ready_to_arm, input arm ); @@ -134,17 +136,39 @@ task cycle_change(); end endtask +initial ready_to_arm = 1; + always @ (posedge clk) begin - case (state) + if (!rst_L) begin + idle_state(); + finished <= 0; + state <= WAIT_ON_ARM; + ready_to_arm <= 1; +`ifndef SPI_MASTER_NO_READ + from_slave <= 0; +`endif +`ifndef SPI_MASTER_NO_WRITE + send_buf <= 0; +`endif + end else case (state) WAIT_ON_ARM: begin +`ifdef SIMULATION + if (!ready_to_arm) + $error("not ready to arm in wait_on_arm"); +`endif if (!arm) begin idle_state(); finished <= 0; end else begin setup_bits(); + ready_to_arm <= 0; end end ON_CYCLE: begin +`ifdef SIMULATION + if (ready_to_arm) + $error("ready_to_arm while on cycle"); +`endif if (sck) begin // rising edge if (PHASE == 1) begin write_data(); @@ -174,6 +198,10 @@ always @ (posedge clk) begin end end CYCLE_WAIT: begin +`ifdef SIMULATION + if (ready_to_arm) + $error("ready_to_arm while in cycle wait"); +`endif if (timer == CYCLE_HALF_WAIT) begin timer <= 1; cycle_change(); @@ -182,10 +210,15 @@ always @ (posedge clk) begin end end WAIT_FINISHED: begin +`ifdef SIMULATION + if (ready_to_arm) + $error("ready_to_arm while in wait finished"); +`endif finished <= 1; idle_state(); if (!arm) begin state <= WAIT_ON_ARM; + ready_to_arm <= 1; end end endcase diff --git a/firmware/rtl/spi/spi_master_ss_template.v b/firmware/rtl/spi/spi_master_ss_template.v index cd24740..fff9d08 100644 --- a/firmware/rtl/spi/spi_master_ss_template.v +++ b/firmware/rtl/spi/spi_master_ss_template.v @@ -1,3 +1,8 @@ +/* (c) Peter McGoron 2022 v0.3 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v.2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ /* spi master with integrated ability to wait a certain amount of cycles * after activating SS. */ @@ -17,6 +22,7 @@ module `SPI_MASTER_SS_NAME ) ( input clk, + input rst_L, `ifndef SPI_MASTER_NO_READ output [WID-1:0] from_slave, input miso, @@ -27,6 +33,7 @@ module `SPI_MASTER_SS_NAME `endif output sck_wire, output finished, + output ready_to_arm, output ss_L, input arm ); @@ -44,6 +51,7 @@ assign ss_L = !ss; .PHASE(PHASE) ) master ( .clk(clk), + .rst_L(rst_L), `ifndef SPI_MASTER_NO_READ .from_slave(from_slave), .miso(miso), @@ -54,6 +62,7 @@ assign ss_L = !ss; `endif .sck_wire(sck_wire), .finished(finished), + .ready_to_arm(ready_to_arm), .arm(arm_master) ); @@ -70,7 +79,12 @@ task master_arm(); endtask always @ (posedge clk) begin - case (state) + if (!rst_L) begin + state <= WAIT_ON_ARM; + timer <= 0; + arm_master <= 0; + ss <= 0; + end else case (state) WAIT_ON_ARM: begin if (arm) begin timer <= 1; diff --git a/firmware/rtl/spi/spi_slave.v b/firmware/rtl/spi/spi_slave.v index 5ef89af..4628a9f 100644 --- a/firmware/rtl/spi/spi_slave.v +++ b/firmware/rtl/spi/spi_slave.v @@ -1,4 +1,4 @@ -/* (c) Peter McGoron 2022 v0.2 +/* (c) Peter McGoron 2022 v0.3 * This Source Code Form is subject to the terms of the Mozilla Public * License, v.2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. @@ -20,6 +20,7 @@ spi_slave ) ( input clk, + input rst_L, input sck, input ss_L, `ifndef SPI_SLAVE_NO_READ @@ -96,58 +97,69 @@ task check_counter(); endtask always @ (posedge clk) begin - sck_delay <= sck; - ss_delay <= ss; - - case ({ss_delay, ss}) - 2'b01: begin // rising edge of SS + if (!rst_L) begin + sck_delay <= 0; bit_counter <= 0; + ss_delay <= 0; + ready_at_start <= 0; +`ifndef SPI_SLAVE_NO_READ + from_master <= 0; +`endif +`ifndef SPI_SLAVE_NO_WRITE + miso <= 0; + send_buf <= 0; +`endif finished <= 0; err <= 0; - ready_at_start <= rdy; + end else begin + sck_delay <= sck; + ss_delay <= ss; - setup_bits(); - end - 2'b10: begin // falling edge - finished <= ready_at_start; - end - 2'b11: begin - case ({sck_delay, sck}) - 2'b01: begin // rising edge - if (PHASE == 1) begin - write_data(); - end else begin - read_data(); - end + case ({ss_delay, ss}) + 2'b01: begin // rising edge of SS + bit_counter <= 0; + finished <= 0; + err <= 0; + ready_at_start <= rdy; - if (POLARITY == 0) begin - check_counter(); - end + setup_bits(); end 2'b10: begin // falling edge - if (PHASE == 1) begin - read_data(); - end else begin - write_data(); - end - - if (POLARITY == 1) begin - check_counter(); - end + finished <= ready_at_start; end - default: ; - endcase - end - 2'b00: begin - if (!rdy) begin + 2'b11: begin + case ({sck_delay, sck}) + 2'b01: begin // rising edge + if (PHASE == 1) begin + write_data(); + end else begin + read_data(); + end + + if (POLARITY == 0) begin + check_counter(); + end + end + 2'b10: begin // falling edge + if (PHASE == 1) begin + read_data(); + end else begin + write_data(); + end + + if (POLARITY == 1) begin + check_counter(); + end + end + default: ; + endcase + end + 2'b00: if (!rdy) begin finished <= 0; err <= 0; end -`ifndef SPI_SLAVE_NO_WRITE - miso <= 0; -`endif + endcase end - endcase end endmodule diff --git a/firmware/rtl/waveform/Makefile b/firmware/rtl/waveform/Makefile index c9f667e..9093464 100644 --- a/firmware/rtl/waveform/Makefile +++ b/firmware/rtl/waveform/Makefile @@ -26,7 +26,7 @@ obj_dir/Vwaveform_sim.mk: $(waveform_src) verilator --cc --exe -Wall --trace --trace-fst -I../spi \ -CFLAGS -DWORD_AMNT=2048 \ -CFLAGS -DRAM_WID=32 \ - -D VERILATOR_SIMULATION \ + -DVERILATOR_SIMULATION \ $(waveform_src) obj_dir/Vwaveform_sim: obj_dir/Vwaveform_sim.mk $(waveform_src) cd obj_dir && make -f Vwaveform_sim.mk diff --git a/firmware/rtl/waveform/bram_interface.v b/firmware/rtl/waveform/bram_interface.v index 8a2daba..289d875 100644 --- a/firmware/rtl/waveform/bram_interface.v +++ b/firmware/rtl/waveform/bram_interface.v @@ -8,6 +8,7 @@ module bram_interface #( parameter RAM_WORD_INCR = 2 ) ( input clk, + input rst_L, /* autoapproach interface */ output reg [WORD_WID-1:0] word, @@ -35,6 +36,7 @@ initial refresh_finished = 0; initial ram_dma_addr = 0; initial ram_read = 0; +/* TODO: how to initialize? */ reg [WORD_WID-1:0] backing_buffer [WORD_AMNT:0]; localparam WAIT_ON_REFRESH = 0; @@ -42,10 +44,20 @@ localparam READ_LOW_WORD = 1; localparam READ_HIGH_WORD = 2; localparam WAIT_ON_REFRESH_DEASSERT = 3; -reg [1:0] refresh_state = 0; +reg [1:0] refresh_state = WAIT_ON_REFRESH; reg [WORD_AMNT_WID-1:0] word_cntr_refresh = 0; -always @ (posedge clk) case (refresh_state) +always @ (posedge clk) if (!rst_L) begin + word <= 0; + word_last <= 0; + word_ok <= 0; + refresh_finished <= 0; + ram_dma_addr <= 0; + ram_read <= 0; + /* Do not reset backing buffer because that would take too long */ + refresh_state <= WAIT_ON_REFRESH; + word_cntr_refresh <= 0; +end else case (refresh_state) WAIT_ON_REFRESH: if (refresh_start) begin ram_dma_addr <= start_addr; refresh_state <= READ_LOW_WORD; @@ -84,7 +96,7 @@ endcase reg [WORD_AMNT_WID-1:0] auto_cntr = 0; -always @ (posedge clk) if (word_rst) begin +always @ (posedge clk) if (word_rst || !rst_L) begin auto_cntr <= 0; word_ok <= 0; word_last <= 0; diff --git a/firmware/rtl/waveform/bram_interface_sim.cpp b/firmware/rtl/waveform/bram_interface_sim.cpp index 430b1a9..c0074b8 100644 --- a/firmware/rtl/waveform/bram_interface_sim.cpp +++ b/firmware/rtl/waveform/bram_interface_sim.cpp @@ -88,11 +88,14 @@ int main(int argc, char *argv[]) { Verilated::fatalOnError(false); tb = new TB(); + tb->mod.rst_L = 1; printf("test basic read/write\n"); refresh_data(); + printf("\ttest 1\n"); test_aa_read_1(); refresh_data(); + printf("\ttest 2\n"); test_aa_read_1(); printf("test resetting\n"); diff --git a/firmware/rtl/waveform/bram_interface_sim.v b/firmware/rtl/waveform/bram_interface_sim.v index 7286bd0..cec32cd 100644 --- a/firmware/rtl/waveform/bram_interface_sim.v +++ b/firmware/rtl/waveform/bram_interface_sim.v @@ -12,6 +12,7 @@ module bram_interface_sim #( parameter RAM_WORD_INCR = 2 ) ( input clk, + input rst_L, /* autoapproach interface */ output [WORD_WID-1:0] word, @@ -59,6 +60,7 @@ bram_interface #( .RAM_WORD_INCR(RAM_WORD_INCR) ) bram_interface ( .clk(clk), + .rst_L(rst_L), .word(word), .word_next(word_next), .word_last(word_last), diff --git a/firmware/rtl/waveform/waveform.v b/firmware/rtl/waveform/waveform.v index 284e76b..de261c9 100644 --- a/firmware/rtl/waveform/waveform.v +++ b/firmware/rtl/waveform/waveform.v @@ -1,6 +1,5 @@ /* Write a waveform to a DAC. */ -/* TODO: Add reset pin. - * Add "how many values to go" counter. */ +/* TODO: Add "how many values to go" counter. */ module waveform #( parameter DAC_WID = 24, parameter DAC_WID_SIZ = 5, @@ -19,6 +18,7 @@ module waveform #( parameter RAM_WORD_INCR = 2 ) ( input clk, + input rst_L, input arm, input halt_on_finish, /* NOTE: @@ -55,10 +55,10 @@ module waveform #( ); wire [WORD_WID-1:0] word; -reg word_next; +reg word_next = 0; wire word_ok; wire word_last; -reg word_rst; +reg word_rst = 1; bram_interface #( .WORD_WID(WORD_WID), @@ -69,6 +69,7 @@ bram_interface #( .RAM_WORD_INCR(RAM_WORD_INCR) ) bram ( .clk(clk), + .rst_L(rst_L), .word(word), .word_next(word_next), .word_last(word_last), @@ -86,8 +87,9 @@ bram_interface #( ); wire dac_finished; -reg dac_arm; -reg [DAC_WID-1:0] dac_out; +reg dac_arm = 0; +reg [DAC_WID-1:0] dac_out = 0; +wire dac_ready_to_arm_unused; spi_master_ss_no_read #( .WID(DAC_WID), @@ -100,6 +102,8 @@ spi_master_ss_no_read #( .SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ) ) dac_master ( .clk(clk), + .rst_L(rst_L), + .ready_to_arm(dac_ready_to_arm_unused), .mosi(mosi), .sck_wire(sck), .ss_L(ss_L), @@ -119,11 +123,20 @@ reg [TIMER_WID-1:0] wait_timer = 0; assign running = state != WAIT_ON_ARM; -always @ (posedge clk) case (state) +always @ (posedge clk) if (!rst_L) begin + state <= WAIT_ON_ARM; + wait_timer <= 0; + finished <= 0; + word_rst <= 1; + word_next <= 0; + dac_out <= 0; + dac_arm <= 0; +end else case (state) WAIT_ON_ARM: begin finished <= 0; if (arm) begin state <= DO_WAIT; + word_rst <= 0; wait_timer <= time_to_wait; end else begin word_rst <= 1; diff --git a/firmware/rtl/waveform/waveform_sim.cpp b/firmware/rtl/waveform/waveform_sim.cpp index 67a423a..9cc2924 100644 --- a/firmware/rtl/waveform/waveform_sim.cpp +++ b/firmware/rtl/waveform/waveform_sim.cpp @@ -1,3 +1,4 @@ +/* TODO: impleement reset for dma and test both separetely */ #include #include "Vwaveform_sim.h" #include "../testbench.hpp" @@ -65,6 +66,7 @@ int main(int argc, char *argv[]) { tb = new WaveformTestbench(); tb->mod.rdy = 1; + tb->mod.rst_L = 1; tb->refresh_data(); tb->mod.time_to_wait = 10; tb->mod.halt_on_finish = 1; diff --git a/firmware/rtl/waveform/waveform_sim.v b/firmware/rtl/waveform/waveform_sim.v index 3f9fa28..09b4f0b 100644 --- a/firmware/rtl/waveform/waveform_sim.v +++ b/firmware/rtl/waveform/waveform_sim.v @@ -21,6 +21,7 @@ module waveform_sim #( parameter RAM_WORD_INCR = 2 ) ( input clk, + input rst_L, input arm, input halt_on_finish, output waveform_finished, @@ -52,6 +53,7 @@ spi_slave_no_write #( ) slave ( .clk(clk), .sck(sck), + .rst_L(rst_L), .ss_L(ss_L), .mosi(mosi), .from_master(from_master), @@ -101,6 +103,7 @@ waveform #( ) waveform ( .clk(clk), .arm(arm), + .rst_L(rst_L), .halt_on_finish(halt_on_finish), .running(running), .finished(waveform_finished), diff --git a/firmware/soc.py b/firmware/soc.py index 0f781c9..bf97b08 100644 --- a/firmware/soc.py +++ b/firmware/soc.py @@ -26,6 +26,7 @@ io = [ ("adc_conv", 0, Pins("V15 T11 N15 U18 U11 R10 R16 U17"), IOStandard("LVCMOS33")), ("adc_sck", 0, Pins("U16 R12 M16 R17 V16 R11 N16 T18"), IOStandard("LVCMOS33")), ("adc_sdo", 0, Pins("P14 T14 V17 P17 M13 R13 N14 R18"), IOStandard("LVCMOS33")), + ("module_reset", 0, Pins("D9"), IOStandard("LVCMOS33")), ("test_clock", 0, Pins("P18"), IOStandard("LVCMOS33")) ] @@ -121,6 +122,7 @@ class Base(Module, AutoCSR): self._make_csr("cl_finish_cmd", CSRStatus, 1, "Control Loop Command Finished Flag") self.kwargs["i_clk"] = clk + self.kwargs["i_rst_L"] = ~platform.request("module_reset") self.kwargs["i_dac_miso"] = platform.request("dac_miso") self.kwargs["o_dac_mosi"] = platform.request("dac_mosi") self.kwargs["o_dac_sck"] = platform.request("dac_sck") @@ -138,9 +140,8 @@ class Base(Module, AutoCSR): # Clock and Reset Generator # I don't know how this works, I only know that it does. -# TODO: Connect cpu_reset pin to Verilog modules. class _CRG(Module): - def __init__(self, platform, sys_clk_freq, with_dram=True, with_rst=True): + def __init__(self, platform, sys_clk_freq, with_dram, rst_pin): self.rst = Signal() self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_eth = ClockDomain() @@ -151,7 +152,7 @@ class _CRG(Module): # Clk/Rst. clk100 = platform.request("clk100") - rst = ~platform.request("cpu_reset") if with_rst else 0 + rst = ~rst_pin if rst_pin is not None else 0 # PLL. self.submodules.pll = pll = S7PLL(speedgrade=-1) @@ -174,7 +175,8 @@ class CryoSNOM1SoC(SoCCore): def __init__(self, variant): sys_clk_freq = int(100e6) platform = board_spec.Platform(variant=variant, toolchain="f4pga") - self.submodules.crg = _CRG(platform, sys_clk_freq, True) + rst = platform.request("cpu_reset") + self.submodules.crg = _CRG(platform, sys_clk_freq, True, rst) # These source files need to be sorted so that modules # that rely on another module come later. For instance, # `control_loop` depends on `control_loop_math`, so