reset pins and test clock

This commit is contained in:
Peter McGoron 2023-05-10 14:35:57 -04:00
parent 540612e305
commit 15b8fcbe7e
20 changed files with 319 additions and 136 deletions

View File

@ -43,6 +43,7 @@ m4_define(m4_dac_wires, ⟨
/* Same thing but for ADCs */ /* Same thing but for ADCs */
m4_define(m4_adc_wires, ⟨ m4_define(m4_adc_wires, ⟨
input [$3-1:0] adc_sel_$2,
output adc_finished_$2, output adc_finished_$2,
input adc_arm_$2, input adc_arm_$2,
output [$1-1:0] from_adc_$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) .SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ)
) dac_master_$2 ( ) dac_master_$2 (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.mosi(mosi_port_$2[0]), .mosi(mosi_port_$2[0]),
.miso(miso_port_$2[0]), .miso(miso_port_$2[0]),
.sck_wire(sck_port_$2[0]), .sck_wire(sck_port_$2[0]),
@ -135,6 +137,27 @@ m4_define(m4_dac_switch, ⟨
/* Same thing but for ADCs */ /* Same thing but for ADCs */
m4_define(m4_adc_switch, ⟨ 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 #( spi_master_ss_no_write #(
.WID($1), .WID($1),
.WID_LEN(ADC_WID_SIZ), .WID_LEN(ADC_WID_SIZ),
@ -146,13 +169,21 @@ m4_define(m4_adc_switch, ⟨
.PHASE(ADC_PHASE) .PHASE(ADC_PHASE)
) adc_master_$2 ( ) adc_master_$2 (
.clk(clk), .clk(clk),
.miso(adc_sdo[$2]), .rst_L(rst_L),
.sck_wire(adc_sck[$2]), .miso(adc_sdo_port_$2[0]),
.ss_L(adc_conv_L[$2]), .sck_wire(adc_sck_port_$2[0]),
.ss_L(adc_conv_L_port_$2[0]),
.finished(adc_finished_$2), .finished(adc_finished_$2),
.arm(adc_arm_$2), .arm(adc_arm_$2),
.from_slave(from_adc_$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_WID = 16,
parameter WF_RAM_WORD_INCR = 2, parameter WF_RAM_WORD_INCR = 2,
parameter ADC_PORTS = 1, parameter ADC_PORTS = 2,
m4_define(ADC_PORTS_CONTROL_LOOP, (ADC_PORTS + 1)) m4_define(ADC_PORTS_CONTROL_LOOP, (ADC_PORTS + 1))
parameter ADC_NUM = 8, parameter ADC_NUM = 8,
/* Three types of ADC. For now assume that their electronics /* 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 parameter CL_CYCLE_COUNT_WID = 18
) ( ) (
input clk, input clk,
input rst_L,
output [DAC_NUM-1:0] dac_mosi, output [DAC_NUM-1:0] dac_mosi,
input [DAC_NUM-1:0] dac_miso, 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, 6),
m4_dac_wires(DAC_PORTS, 7), m4_dac_wires(DAC_PORTS, 7),
input [ADC_PORTS_CONTROL_LOOP-1:0] adc_sel_0, 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, 0), m4_adc_wires(ADC_TYPE1_WID, 2, ADC_PORTS),
m4_adc_wires(ADC_TYPE1_WID, 1), m4_adc_wires(ADC_TYPE1_WID, 3, ADC_PORTS),
m4_adc_wires(ADC_TYPE1_WID, 2), m4_adc_wires(ADC_TYPE1_WID, 4, ADC_PORTS),
m4_adc_wires(ADC_TYPE1_WID, 3), m4_adc_wires(ADC_TYPE1_WID, 5, ADC_PORTS),
m4_adc_wires(ADC_TYPE1_WID, 4), m4_adc_wires(ADC_TYPE1_WID, 6, ADC_PORTS),
m4_adc_wires(ADC_TYPE1_WID, 5), m4_adc_wires(ADC_TYPE1_WID, 7, ADC_PORTS),
m4_adc_wires(ADC_TYPE1_WID, 6),
m4_adc_wires(ADC_TYPE1_WID, 7),
output cl_in_loop, output cl_in_loop,
input [M4_CONTROL_LOOP_CMD_WIDTH-1:0] cl_cmd, 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, 6);
m4_dac_switch(DAC_PORTS, 7); 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 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; counter <= 0;
test_clock <= !test_clock; test_clock <= !test_clock;
end else begin end else begin
counter <= counter + 1; counter <= counter + 1;
end end
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) */ m4_adc_switch(ADC_TYPE1_WID, 0, ADC_PORTS_CONTROL_LOOP);
m4_adc_switch(ADC_TYPE1_WID, 1, ADC_PORTS);
wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_conv_L_port_0; m4_adc_switch(ADC_TYPE1_WID, 2, ADC_PORTS);
wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_sdo_port_0; m4_adc_switch(ADC_TYPE1_WID, 3, ADC_PORTS);
wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_sck_port_0; m4_adc_switch(ADC_TYPE1_WID, 4, ADC_PORTS);
wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_mosi_port_0_unassigned; m4_adc_switch(ADC_TYPE1_WID, 5, ADC_PORTS);
wire adc_mosi_unassigned; m4_adc_switch(ADC_TYPE1_WID, 6, ADC_PORTS);
m4_adc_switch(ADC_TYPE1_WID, 7, ADC_PORTS);
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)
);
control_loop #( control_loop #(
.ADC_WID(ADC_TYPE1_WID), .ADC_WID(ADC_TYPE1_WID),
@ -342,14 +367,15 @@ control_loop #(
.DAC_SS_WAIT_SIZ(DAC_SS_WAIT_SIZ) .DAC_SS_WAIT_SIZ(DAC_SS_WAIT_SIZ)
) cl ( ) cl (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.in_loop(cl_in_loop), .in_loop(cl_in_loop),
.dac_mosi(mosi_port_0[2]), .dac_mosi(mosi_port_0[2]),
.dac_miso(miso_port_0[2]), .dac_miso(miso_port_0[2]),
.dac_ss_L(ss_L_port_0[2]), .dac_ss_L(ss_L_port_0[2]),
.dac_sck(sck_port_0[2]), .dac_sck(sck_port_0[2]),
.adc_miso(adc_sdo_port_0[1]), .adc_miso(adc_sdo_port_0[2]),
.adc_conv_L(adc_conv_L_port_0[1]), .adc_conv_L(adc_conv_L_port_0[2]),
.adc_sck(adc_sck_port_0[1]), .adc_sck(adc_sck_port_0[2]),
.cmd(cl_cmd), .cmd(cl_cmd),
.word_in(cl_word_in), .word_in(cl_word_in),
.word_out(cl_word_out), .word_out(cl_word_out),
@ -357,12 +383,4 @@ control_loop #(
.finish_cmd(cl_finish_cmd) .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 endmodule

View File

@ -1,7 +1,7 @@
# Generate verilog from m4 file # 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 %.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 $< > $@ m4 -P $< > $@
%_preprocessed.v: %.v %_preprocessed.v: %.v
verilator -P -E $< > $@ verilator -P -E $< > $@

View File

@ -7,6 +7,7 @@ module adc_sim #(
input clk, input clk,
input [WID-1:0] indat, input [WID-1:0] indat,
input rst_L,
output reg request, output reg request,
input fulfilled, input fulfilled,
output err, output err,
@ -26,7 +27,14 @@ reg rdy = 0;
wire spi_fin; wire spi_fin;
always @ (posedge clk) begin 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; request <= 1;
ss_raised <= 1; ss_raised <= 1;
end else if (ss_raised && !ss) begin end else if (ss_raised && !ss) begin
@ -56,6 +64,7 @@ spi_slave_no_read #(
) spi ( ) spi (
.clk(clk), .clk(clk),
.sck(sck), .sck(sck),
.rst_L(rst_L),
.ss_L(ss_buf_L), .ss_L(ss_buf_L),
.miso(miso), .miso(miso),
.to_master(data), .to_master(data),

View File

@ -41,6 +41,7 @@ m4_define(M4_E_WID, (DAC_DATA_WID + 1))
parameter DAC_SS_WAIT_SIZ = 3 parameter DAC_SS_WAIT_SIZ = 3
) ( ) (
input clk, input clk,
input rst_L,
output in_loop, output in_loop,
output dac_mosi, output dac_mosi,
@ -64,6 +65,7 @@ m4_define(M4_E_WID, (DAC_DATA_WID + 1))
reg dac_arm; reg dac_arm;
reg dac_finished; reg dac_finished;
wire dac_ready_to_arm_unused;
reg [DAC_WID-1:0] to_dac; reg [DAC_WID-1:0] to_dac;
/* verilator lint_off UNUSED */ /* verilator lint_off UNUSED */
@ -80,6 +82,8 @@ spi_master_ss #(
.SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ) .SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ)
) dac_master ( ) dac_master (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.ready_to_arm(dac_ready_to_arm_unused),
.mosi(dac_mosi), .mosi(dac_mosi),
.miso(dac_miso), .miso(dac_miso),
.sck_wire(dac_sck), .sck_wire(dac_sck),
@ -93,6 +97,7 @@ spi_master_ss #(
reg adc_arm; reg adc_arm;
reg adc_finished; reg adc_finished;
wire [ADC_WID-1:0] measured_value; wire [ADC_WID-1:0] measured_value;
wire adc_ready_to_arm_unused;
localparam [3-1:0] DAC_REGISTER = 3'b001; 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) .SS_WAIT_TIMER_LEN(ADC_CONV_WAIT_SIZ)
) adc_master ( ) adc_master (
.clk(clk), .clk(clk),
.ready_to_arm(adc_ready_to_arm_unused),
.rst_L(rst_L),
.arm(adc_arm), .arm(adc_arm),
.from_slave(measured_value), .from_slave(measured_value),
.miso(adc_miso), .miso(adc_miso),
@ -166,6 +173,7 @@ control_loop_math #(
.ADC_TO_DAC({32'b01000001100, 32'b01001001101110100101111000110101}) .ADC_TO_DAC({32'b01000001100, 32'b01001001101110100101111000110101})
) math ( ) math (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.arm(arm_math), .arm(arm_math),
.finished(math_finished), .finished(math_finished),
.setpt(setpt), .setpt(setpt),
@ -228,7 +236,10 @@ reg [DELAY_WID-1:0] timer = 0;
/**** Timing. ****/ /**** Timing. ****/
always @ (posedge clk) begin 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; counting_timer <= 1;
last_timer <= counting_timer; last_timer <= counting_timer;
end else if (running) begin end else if (running) begin
@ -245,7 +256,11 @@ wire write_control = state == CYCLE_START || !running;
reg dirty_bit = 0; reg dirty_bit = 0;
always @ (posedge clk) begin 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) case (cmd)
M4_CONTROL_LOOP_NOOP: M4_CONTROL_LOOP_NOOP:
finish_cmd <= 1; finish_cmd <= 1;
@ -331,7 +346,21 @@ end
assign in_loop = state != INIT_READ_FROM_DAC || running; assign in_loop = state != INIT_READ_FROM_DAC || running;
always @ (posedge clk) begin 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 INIT_READ_FROM_DAC: begin
if (running) begin if (running) begin
to_dac <= {1'b1, DAC_REGISTER, 20'b0}; to_dac <= {1'b1, DAC_REGISTER, 20'b0};

View File

@ -42,6 +42,7 @@ m4_define(M4_E_WID, (DAC_WID + 1))
) ( ) (
input clk, input clk,
input arm, input arm,
input rst_L,
output reg finished, output reg finished,
input signed [ADC_WID-1:0] setpt, input signed [ADC_WID-1:0] setpt,
@ -86,6 +87,7 @@ boothmul #(
.a1(a1), .a1(a1),
.a2(a2), .a2(a2),
.clk(clk), .clk(clk),
.rst_L(rst_L),
.outn(out_untrunc), .outn(out_untrunc),
.fin(mul_fin), .fin(mul_fin),
.arm(mul_arm) .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 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: WAIT_ON_ARM:
if (arm) begin if (arm) begin
a1[CONSTS_FRAC-1:0] <= 0; a1[CONSTS_FRAC-1:0] <= 0;

View File

@ -67,6 +67,7 @@ static void calculate() {
int main(int argc, char **argv) { int main(int argc, char **argv) {
init(argc, argv); init(argc, argv);
mod->arm = 0; mod->arm = 0;
mod->rst_L = 1;
run_clock(); run_clock();
Transfer func = Transfer{150, 0, 2, 1.1, 10, -1}; Transfer func = Transfer{150, 0, 2, 1.1, 10, -1};

View File

@ -19,6 +19,7 @@ module control_loop_sim_top #(
parameter DELAY_WID = 16 parameter DELAY_WID = 16
)( )(
input clk, input clk,
input rst_L,
output in_loop, output in_loop,
output [DAC_DATA_WID-1:0] curset, output [DAC_DATA_WID-1:0] curset,
@ -53,6 +54,7 @@ adc_sim #(
.PHASE(ADC_PHASE) .PHASE(ADC_PHASE)
) adc ( ) adc (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.indat(measured_value), .indat(measured_value),
.request(request), .request(request),
.fulfilled(fulfilled), .fulfilled(fulfilled),
@ -77,6 +79,7 @@ dac_sim #(
.PHASE(DAC_PHASE) .PHASE(DAC_PHASE)
) dac ( ) dac (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.curset(curset), .curset(curset),
.mosi(dac_mosi), .mosi(dac_mosi),
.miso(dac_miso), .miso(dac_miso),
@ -105,6 +108,7 @@ control_loop #(
.DAC_PHASE(DAC_PHASE) .DAC_PHASE(DAC_PHASE)
) cloop ( ) cloop (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.in_loop(in_loop), .in_loop(in_loop),
.dac_mosi(dac_mosi), .dac_mosi(dac_mosi),
.dac_miso(dac_miso), .dac_miso(dac_miso),

View File

@ -6,6 +6,7 @@ module dac_sim #(
parameter WID_LEN = 5 parameter WID_LEN = 5
) ( ) (
input clk, input clk,
input rst_L,
output reg [DATA_WID-1:0] curset, output reg [DATA_WID-1:0] curset,
@ -23,7 +24,12 @@ wire spi_fin;
reg [WID-4-1:0] ctrl_register = 0; reg [WID-4-1:0] ctrl_register = 0;
always @ (posedge clk) begin 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; rdy <= 0;
case (from_master[WID-1:WID-4]) case (from_master[WID-1:WID-4])
4'b1001: begin 4'b1001: begin
@ -56,6 +62,7 @@ spi_slave #(
.clk(clk), .clk(clk),
.sck(sck), .sck(sck),
.ss_L(ss_L), .ss_L(ss_L),
.rst_L(rst_L),
.miso(miso), .miso(miso),
.mosi(mosi), .mosi(mosi),
.from_master(from_master), .from_master(from_master),

View File

@ -1,6 +1,7 @@
# Makefile for tests and hardware verification. # Makefile for tests and hardware verification.
.PHONY: test clean codegen .PHONY: test clean codegen
include ../common.makefile
all: test codegen all: test codegen
test: obj_dir/Vspi_switch test: obj_dir/Vspi_switch

View File

@ -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 * 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 * 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/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
@ -30,6 +30,7 @@ spi_master
) )
( (
input clk, input clk,
input rst_L,
`ifndef SPI_MASTER_NO_READ `ifndef SPI_MASTER_NO_READ
output reg [WID-1:0] from_slave, output reg [WID-1:0] from_slave,
input miso, input miso,
@ -40,6 +41,7 @@ spi_master
`endif `endif
output reg sck_wire, output reg sck_wire,
output reg finished, output reg finished,
output reg ready_to_arm,
input arm input arm
); );
@ -134,17 +136,39 @@ task cycle_change();
end end
endtask endtask
initial ready_to_arm = 1;
always @ (posedge clk) begin 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 WAIT_ON_ARM: begin
`ifdef SIMULATION
if (!ready_to_arm)
$error("not ready to arm in wait_on_arm");
`endif
if (!arm) begin if (!arm) begin
idle_state(); idle_state();
finished <= 0; finished <= 0;
end else begin end else begin
setup_bits(); setup_bits();
ready_to_arm <= 0;
end end
end end
ON_CYCLE: begin ON_CYCLE: begin
`ifdef SIMULATION
if (ready_to_arm)
$error("ready_to_arm while on cycle");
`endif
if (sck) begin // rising edge if (sck) begin // rising edge
if (PHASE == 1) begin if (PHASE == 1) begin
write_data(); write_data();
@ -174,6 +198,10 @@ always @ (posedge clk) begin
end end
end end
CYCLE_WAIT: begin CYCLE_WAIT: begin
`ifdef SIMULATION
if (ready_to_arm)
$error("ready_to_arm while in cycle wait");
`endif
if (timer == CYCLE_HALF_WAIT) begin if (timer == CYCLE_HALF_WAIT) begin
timer <= 1; timer <= 1;
cycle_change(); cycle_change();
@ -182,10 +210,15 @@ always @ (posedge clk) begin
end end
end end
WAIT_FINISHED: begin WAIT_FINISHED: begin
`ifdef SIMULATION
if (ready_to_arm)
$error("ready_to_arm while in wait finished");
`endif
finished <= 1; finished <= 1;
idle_state(); idle_state();
if (!arm) begin if (!arm) begin
state <= WAIT_ON_ARM; state <= WAIT_ON_ARM;
ready_to_arm <= 1;
end end
end end
endcase endcase

View File

@ -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 /* spi master with integrated ability to wait a certain amount of cycles
* after activating SS. * after activating SS.
*/ */
@ -17,6 +22,7 @@ module `SPI_MASTER_SS_NAME
) )
( (
input clk, input clk,
input rst_L,
`ifndef SPI_MASTER_NO_READ `ifndef SPI_MASTER_NO_READ
output [WID-1:0] from_slave, output [WID-1:0] from_slave,
input miso, input miso,
@ -27,6 +33,7 @@ module `SPI_MASTER_SS_NAME
`endif `endif
output sck_wire, output sck_wire,
output finished, output finished,
output ready_to_arm,
output ss_L, output ss_L,
input arm input arm
); );
@ -44,6 +51,7 @@ assign ss_L = !ss;
.PHASE(PHASE) .PHASE(PHASE)
) master ( ) master (
.clk(clk), .clk(clk),
.rst_L(rst_L),
`ifndef SPI_MASTER_NO_READ `ifndef SPI_MASTER_NO_READ
.from_slave(from_slave), .from_slave(from_slave),
.miso(miso), .miso(miso),
@ -54,6 +62,7 @@ assign ss_L = !ss;
`endif `endif
.sck_wire(sck_wire), .sck_wire(sck_wire),
.finished(finished), .finished(finished),
.ready_to_arm(ready_to_arm),
.arm(arm_master) .arm(arm_master)
); );
@ -70,7 +79,12 @@ task master_arm();
endtask endtask
always @ (posedge clk) begin 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 WAIT_ON_ARM: begin
if (arm) begin if (arm) begin
timer <= 1; timer <= 1;

View File

@ -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 * 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 * 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/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
@ -20,6 +20,7 @@ spi_slave
) )
( (
input clk, input clk,
input rst_L,
input sck, input sck,
input ss_L, input ss_L,
`ifndef SPI_SLAVE_NO_READ `ifndef SPI_SLAVE_NO_READ
@ -96,58 +97,69 @@ task check_counter();
endtask endtask
always @ (posedge clk) begin always @ (posedge clk) begin
sck_delay <= sck; if (!rst_L) begin
ss_delay <= ss; sck_delay <= 0;
case ({ss_delay, ss})
2'b01: begin // rising edge of SS
bit_counter <= 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; finished <= 0;
err <= 0; err <= 0;
ready_at_start <= rdy; end else begin
sck_delay <= sck;
ss_delay <= ss;
setup_bits(); case ({ss_delay, ss})
end 2'b01: begin // rising edge of SS
2'b10: begin // falling edge bit_counter <= 0;
finished <= ready_at_start; finished <= 0;
end err <= 0;
2'b11: begin ready_at_start <= rdy;
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 setup_bits();
check_counter();
end
end end
2'b10: begin // falling edge 2'b10: begin // falling edge
if (PHASE == 1) begin finished <= ready_at_start;
read_data();
end else begin
write_data();
end
if (POLARITY == 1) begin
check_counter();
end
end end
default: ; 2'b11: begin
endcase case ({sck_delay, sck})
end 2'b01: begin // rising edge
2'b00: begin if (PHASE == 1) begin
if (!rdy) 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; finished <= 0;
err <= 0; err <= 0;
end end
`ifndef SPI_SLAVE_NO_WRITE endcase
miso <= 0;
`endif
end end
endcase
end end
endmodule endmodule

View File

@ -26,7 +26,7 @@ obj_dir/Vwaveform_sim.mk: $(waveform_src)
verilator --cc --exe -Wall --trace --trace-fst -I../spi \ verilator --cc --exe -Wall --trace --trace-fst -I../spi \
-CFLAGS -DWORD_AMNT=2048 \ -CFLAGS -DWORD_AMNT=2048 \
-CFLAGS -DRAM_WID=32 \ -CFLAGS -DRAM_WID=32 \
-D VERILATOR_SIMULATION \ -DVERILATOR_SIMULATION \
$(waveform_src) $(waveform_src)
obj_dir/Vwaveform_sim: obj_dir/Vwaveform_sim.mk $(waveform_src) obj_dir/Vwaveform_sim: obj_dir/Vwaveform_sim.mk $(waveform_src)
cd obj_dir && make -f Vwaveform_sim.mk cd obj_dir && make -f Vwaveform_sim.mk

View File

@ -8,6 +8,7 @@ module bram_interface #(
parameter RAM_WORD_INCR = 2 parameter RAM_WORD_INCR = 2
) ( ) (
input clk, input clk,
input rst_L,
/* autoapproach interface */ /* autoapproach interface */
output reg [WORD_WID-1:0] word, output reg [WORD_WID-1:0] word,
@ -35,6 +36,7 @@ initial refresh_finished = 0;
initial ram_dma_addr = 0; initial ram_dma_addr = 0;
initial ram_read = 0; initial ram_read = 0;
/* TODO: how to initialize? */
reg [WORD_WID-1:0] backing_buffer [WORD_AMNT:0]; reg [WORD_WID-1:0] backing_buffer [WORD_AMNT:0];
localparam WAIT_ON_REFRESH = 0; localparam WAIT_ON_REFRESH = 0;
@ -42,10 +44,20 @@ localparam READ_LOW_WORD = 1;
localparam READ_HIGH_WORD = 2; localparam READ_HIGH_WORD = 2;
localparam WAIT_ON_REFRESH_DEASSERT = 3; 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; 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 WAIT_ON_REFRESH: if (refresh_start) begin
ram_dma_addr <= start_addr; ram_dma_addr <= start_addr;
refresh_state <= READ_LOW_WORD; refresh_state <= READ_LOW_WORD;
@ -84,7 +96,7 @@ endcase
reg [WORD_AMNT_WID-1:0] auto_cntr = 0; 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; auto_cntr <= 0;
word_ok <= 0; word_ok <= 0;
word_last <= 0; word_last <= 0;

View File

@ -88,11 +88,14 @@ int main(int argc, char *argv[]) {
Verilated::fatalOnError(false); Verilated::fatalOnError(false);
tb = new TB<Vbram_interface_sim>(); tb = new TB<Vbram_interface_sim>();
tb->mod.rst_L = 1;
printf("test basic read/write\n"); printf("test basic read/write\n");
refresh_data(); refresh_data();
printf("\ttest 1\n");
test_aa_read_1(); test_aa_read_1();
refresh_data(); refresh_data();
printf("\ttest 2\n");
test_aa_read_1(); test_aa_read_1();
printf("test resetting\n"); printf("test resetting\n");

View File

@ -12,6 +12,7 @@ module bram_interface_sim #(
parameter RAM_WORD_INCR = 2 parameter RAM_WORD_INCR = 2
) ( ) (
input clk, input clk,
input rst_L,
/* autoapproach interface */ /* autoapproach interface */
output [WORD_WID-1:0] word, output [WORD_WID-1:0] word,
@ -59,6 +60,7 @@ bram_interface #(
.RAM_WORD_INCR(RAM_WORD_INCR) .RAM_WORD_INCR(RAM_WORD_INCR)
) bram_interface ( ) bram_interface (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.word(word), .word(word),
.word_next(word_next), .word_next(word_next),
.word_last(word_last), .word_last(word_last),

View File

@ -1,6 +1,5 @@
/* Write a waveform to a DAC. */ /* Write a waveform to a DAC. */
/* TODO: Add reset pin. /* TODO: Add "how many values to go" counter. */
* Add "how many values to go" counter. */
module waveform #( module waveform #(
parameter DAC_WID = 24, parameter DAC_WID = 24,
parameter DAC_WID_SIZ = 5, parameter DAC_WID_SIZ = 5,
@ -19,6 +18,7 @@ module waveform #(
parameter RAM_WORD_INCR = 2 parameter RAM_WORD_INCR = 2
) ( ) (
input clk, input clk,
input rst_L,
input arm, input arm,
input halt_on_finish, input halt_on_finish,
/* NOTE: /* NOTE:
@ -55,10 +55,10 @@ module waveform #(
); );
wire [WORD_WID-1:0] word; wire [WORD_WID-1:0] word;
reg word_next; reg word_next = 0;
wire word_ok; wire word_ok;
wire word_last; wire word_last;
reg word_rst; reg word_rst = 1;
bram_interface #( bram_interface #(
.WORD_WID(WORD_WID), .WORD_WID(WORD_WID),
@ -69,6 +69,7 @@ bram_interface #(
.RAM_WORD_INCR(RAM_WORD_INCR) .RAM_WORD_INCR(RAM_WORD_INCR)
) bram ( ) bram (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.word(word), .word(word),
.word_next(word_next), .word_next(word_next),
.word_last(word_last), .word_last(word_last),
@ -86,8 +87,9 @@ bram_interface #(
); );
wire dac_finished; wire dac_finished;
reg dac_arm; reg dac_arm = 0;
reg [DAC_WID-1:0] dac_out; reg [DAC_WID-1:0] dac_out = 0;
wire dac_ready_to_arm_unused;
spi_master_ss_no_read #( spi_master_ss_no_read #(
.WID(DAC_WID), .WID(DAC_WID),
@ -100,6 +102,8 @@ spi_master_ss_no_read #(
.SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ) .SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ)
) dac_master ( ) dac_master (
.clk(clk), .clk(clk),
.rst_L(rst_L),
.ready_to_arm(dac_ready_to_arm_unused),
.mosi(mosi), .mosi(mosi),
.sck_wire(sck), .sck_wire(sck),
.ss_L(ss_L), .ss_L(ss_L),
@ -119,11 +123,20 @@ reg [TIMER_WID-1:0] wait_timer = 0;
assign running = state != WAIT_ON_ARM; 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 WAIT_ON_ARM: begin
finished <= 0; finished <= 0;
if (arm) begin if (arm) begin
state <= DO_WAIT; state <= DO_WAIT;
word_rst <= 0;
wait_timer <= time_to_wait; wait_timer <= time_to_wait;
end else begin end else begin
word_rst <= 1; word_rst <= 1;

View File

@ -1,3 +1,4 @@
/* TODO: impleement reset for dma and test both separetely */
#include <vector> #include <vector>
#include "Vwaveform_sim.h" #include "Vwaveform_sim.h"
#include "../testbench.hpp" #include "../testbench.hpp"
@ -65,6 +66,7 @@ int main(int argc, char *argv[]) {
tb = new WaveformTestbench(); tb = new WaveformTestbench();
tb->mod.rdy = 1; tb->mod.rdy = 1;
tb->mod.rst_L = 1;
tb->refresh_data(); tb->refresh_data();
tb->mod.time_to_wait = 10; tb->mod.time_to_wait = 10;
tb->mod.halt_on_finish = 1; tb->mod.halt_on_finish = 1;

View File

@ -21,6 +21,7 @@ module waveform_sim #(
parameter RAM_WORD_INCR = 2 parameter RAM_WORD_INCR = 2
) ( ) (
input clk, input clk,
input rst_L,
input arm, input arm,
input halt_on_finish, input halt_on_finish,
output waveform_finished, output waveform_finished,
@ -52,6 +53,7 @@ spi_slave_no_write #(
) slave ( ) slave (
.clk(clk), .clk(clk),
.sck(sck), .sck(sck),
.rst_L(rst_L),
.ss_L(ss_L), .ss_L(ss_L),
.mosi(mosi), .mosi(mosi),
.from_master(from_master), .from_master(from_master),
@ -101,6 +103,7 @@ waveform #(
) waveform ( ) waveform (
.clk(clk), .clk(clk),
.arm(arm), .arm(arm),
.rst_L(rst_L),
.halt_on_finish(halt_on_finish), .halt_on_finish(halt_on_finish),
.running(running), .running(running),
.finished(waveform_finished), .finished(waveform_finished),

View File

@ -26,6 +26,7 @@ io = [
("adc_conv", 0, Pins("V15 T11 N15 U18 U11 R10 R16 U17"), IOStandard("LVCMOS33")), ("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_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")), ("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")) ("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._make_csr("cl_finish_cmd", CSRStatus, 1, "Control Loop Command Finished Flag")
self.kwargs["i_clk"] = clk 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["i_dac_miso"] = platform.request("dac_miso")
self.kwargs["o_dac_mosi"] = platform.request("dac_mosi") self.kwargs["o_dac_mosi"] = platform.request("dac_mosi")
self.kwargs["o_dac_sck"] = platform.request("dac_sck") self.kwargs["o_dac_sck"] = platform.request("dac_sck")
@ -138,9 +140,8 @@ class Base(Module, AutoCSR):
# Clock and Reset Generator # Clock and Reset Generator
# I don't know how this works, I only know that it does. # I don't know how this works, I only know that it does.
# TODO: Connect cpu_reset pin to Verilog modules.
class _CRG(Module): 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.rst = Signal()
self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys = ClockDomain()
self.clock_domains.cd_eth = ClockDomain() self.clock_domains.cd_eth = ClockDomain()
@ -151,7 +152,7 @@ class _CRG(Module):
# Clk/Rst. # Clk/Rst.
clk100 = platform.request("clk100") 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. # PLL.
self.submodules.pll = pll = S7PLL(speedgrade=-1) self.submodules.pll = pll = S7PLL(speedgrade=-1)
@ -174,7 +175,8 @@ class CryoSNOM1SoC(SoCCore):
def __init__(self, variant): def __init__(self, variant):
sys_clk_freq = int(100e6) sys_clk_freq = int(100e6)
platform = board_spec.Platform(variant=variant, toolchain="f4pga") 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 # These source files need to be sorted so that modules
# that rely on another module come later. For instance, # that rely on another module come later. For instance,
# `control_loop` depends on `control_loop_math`, so # `control_loop` depends on `control_loop_math`, so