transferring new controller design
This commit is contained in:
@@ -0,0 +1,338 @@
|
||||
module control #(
|
||||
parameter int unsigned DAC_DATA_WIDTH = 12
|
||||
) (
|
||||
input logic ctrl_clk,
|
||||
input logic dac_clk_in,
|
||||
input logic adc_clk_in,
|
||||
|
||||
input logic rst_n,
|
||||
input logic rst_soft,
|
||||
|
||||
// adc_clk_in domain
|
||||
input logic finish,
|
||||
input logic [159:0] cfg_bus_input,
|
||||
input logic cfg_bus_valid,
|
||||
input logic start,
|
||||
|
||||
// status signals
|
||||
output logic busy,
|
||||
|
||||
// dac_clk_in domain outputs
|
||||
output logic [31:0] dac_pulse_width,
|
||||
output logic [31:0] dac_pulse_period,
|
||||
output logic [DAC_DATA_WIDTH-1:0] dac_pulse_height,
|
||||
output logic [15:0] dac_pulse_num,
|
||||
|
||||
// adc_clk_in domain outputs
|
||||
output logic [31:0] adc_pulse_period,
|
||||
output logic [15:0] adc_pulse_num,
|
||||
output logic [31:0] adc_window_size,
|
||||
|
||||
// pulse outputs
|
||||
output logic dac_start,
|
||||
output logic adc_start,
|
||||
output logic dac_rst,
|
||||
output logic adc_rst
|
||||
);
|
||||
|
||||
// static checks
|
||||
initial begin
|
||||
if (DAC_DATA_WIDTH > 16) begin
|
||||
$error("DAC_DATA_WIDTH must be <= 16");
|
||||
end
|
||||
if (DAC_DATA_WIDTH == 0) begin
|
||||
$error("DAC_DATA_WIDTH must be > 0");
|
||||
end
|
||||
end
|
||||
|
||||
// reset synchronizers: async assert, sync deassert in each domain
|
||||
logic rst_ff1, rst_ff2;
|
||||
logic dac_rst_ff1, dac_rst_ff2;
|
||||
logic adc_rst_ff1, adc_rst_ff2;
|
||||
|
||||
logic ctrl_rst;
|
||||
logic dac_rst_int;
|
||||
logic adc_rst_int;
|
||||
|
||||
always_ff @(posedge ctrl_clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
rst_ff1 <= 1'b1;
|
||||
rst_ff2 <= 1'b1;
|
||||
end else begin
|
||||
rst_ff1 <= 1'b0;
|
||||
rst_ff2 <= rst_ff1;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge dac_clk_in or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dac_rst_ff1 <= 1'b1;
|
||||
dac_rst_ff2 <= 1'b1;
|
||||
end else begin
|
||||
dac_rst_ff1 <= 1'b0;
|
||||
dac_rst_ff2 <= dac_rst_ff1;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge adc_clk_in or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
adc_rst_ff1 <= 1'b1;
|
||||
adc_rst_ff2 <= 1'b1;
|
||||
end else begin
|
||||
adc_rst_ff1 <= 1'b0;
|
||||
adc_rst_ff2 <= adc_rst_ff1;
|
||||
end
|
||||
end
|
||||
|
||||
assign ctrl_rst = rst_ff2;
|
||||
assign dac_rst_int = dac_rst_ff2;
|
||||
assign adc_rst_int = adc_rst_ff2;
|
||||
|
||||
// Pending ACKs for config delivery
|
||||
logic cfg_wait_dac_ack;
|
||||
logic cfg_wait_adc_ack;
|
||||
|
||||
// Event toggles cntrl -> DAC/ADC
|
||||
logic start_toggle;
|
||||
logic rst_toggle;
|
||||
|
||||
// Config request toggles cntrl -> DAC/ADC
|
||||
logic cfg_req_toggle_dac;
|
||||
logic cfg_req_toggle_adc;
|
||||
|
||||
// ACK toggles DAC/ADC -> cntrl
|
||||
logic cfg_ack_toggle_dac;
|
||||
logic cfg_ack_toggle_adc;
|
||||
|
||||
(* ASYNC_REG = "TRUE" *) logic cfg_ack_toggle_dac_meta, cfg_ack_toggle_dac_sync, cfg_ack_toggle_dac_sync_d;
|
||||
(* ASYNC_REG = "TRUE" *) logic cfg_ack_toggle_adc_meta, cfg_ack_toggle_adc_sync, cfg_ack_toggle_adc_sync_d;
|
||||
|
||||
wire cfg_ack_pulse_dac = cfg_ack_toggle_dac_sync ^ cfg_ack_toggle_dac_sync_d;
|
||||
wire cfg_ack_pulse_adc = cfg_ack_toggle_adc_sync ^ cfg_ack_toggle_adc_sync_d;
|
||||
|
||||
always_ff @(posedge ctrl_clk or posedge ctrl_rst) begin
|
||||
if (ctrl_rst) begin
|
||||
cfg_ack_toggle_dac_meta <= 1'b0;
|
||||
cfg_ack_toggle_dac_sync <= 1'b0;
|
||||
cfg_ack_toggle_dac_sync_d <= 1'b0;
|
||||
|
||||
cfg_ack_toggle_adc_meta <= 1'b0;
|
||||
cfg_ack_toggle_adc_sync <= 1'b0;
|
||||
cfg_ack_toggle_adc_sync_d <= 1'b0;
|
||||
end else begin
|
||||
cfg_ack_toggle_dac_meta <= cfg_ack_toggle_dac;
|
||||
cfg_ack_toggle_dac_sync <= cfg_ack_toggle_dac_meta;
|
||||
cfg_ack_toggle_dac_sync_d <= cfg_ack_toggle_dac_sync;
|
||||
|
||||
cfg_ack_toggle_adc_meta <= cfg_ack_toggle_adc;
|
||||
cfg_ack_toggle_adc_sync <= cfg_ack_toggle_adc_meta;
|
||||
cfg_ack_toggle_adc_sync_d <= cfg_ack_toggle_adc_sync;
|
||||
end
|
||||
end
|
||||
|
||||
// finish event: ADC -> cntrl via toggle CDC
|
||||
logic finish_toggle_adc;
|
||||
logic finish_meta, finish_sync, finish_sync_d;
|
||||
|
||||
wire finish_pulse = finish_sync ^ finish_sync_d;
|
||||
|
||||
always_ff @(posedge adc_clk_in or posedge adc_rst_int) begin
|
||||
if (adc_rst_int) begin
|
||||
finish_toggle_adc <= 1'b0;
|
||||
end else if (finish) begin
|
||||
finish_toggle_adc <= ~finish_toggle_adc;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge ctrl_clk or posedge ctrl_rst) begin
|
||||
if (ctrl_rst) begin
|
||||
finish_meta <= 1'b0;
|
||||
finish_sync <= 1'b0;
|
||||
finish_sync_d <= 1'b0;
|
||||
end else begin
|
||||
finish_meta <= finish_toggle_adc;
|
||||
finish_sync <= finish_meta;
|
||||
finish_sync_d <= finish_sync;
|
||||
end
|
||||
end
|
||||
|
||||
logic [159:0] cfg_bus;
|
||||
|
||||
always_ff @(posedge ctrl_clk or posedge ctrl_rst) begin
|
||||
if (ctrl_rst) begin
|
||||
cfg_bus <= '0;
|
||||
busy <= 0;
|
||||
|
||||
start_toggle <= 0;
|
||||
rst_toggle <= 0;
|
||||
|
||||
cfg_req_toggle_dac <= 0;
|
||||
cfg_req_toggle_adc <= 0;
|
||||
|
||||
cfg_wait_dac_ack <= 0;
|
||||
cfg_wait_adc_ack <= 0;
|
||||
end else begin
|
||||
if (finish_pulse) begin
|
||||
busy <= 0;
|
||||
end
|
||||
if (cfg_ack_pulse_dac) begin
|
||||
cfg_wait_dac_ack <= 1'b0;
|
||||
end
|
||||
if (cfg_ack_pulse_adc) begin
|
||||
cfg_wait_adc_ack <= 1'b0;
|
||||
end
|
||||
|
||||
if (cfg_bus_valid && !busy && !cfg_wait_dac_ack && !cfg_wait_adc_ack) begin
|
||||
cfg_bus <= cfg_bus_input;
|
||||
|
||||
cfg_req_toggle_dac <= ~cfg_req_toggle_dac;
|
||||
cfg_req_toggle_adc <= ~cfg_req_toggle_adc;
|
||||
|
||||
cfg_wait_dac_ack <= 1;
|
||||
cfg_wait_adc_ack <= 1;
|
||||
end
|
||||
|
||||
if (start && !busy && !cfg_wait_dac_ack && !cfg_wait_adc_ack) begin
|
||||
start_toggle <= ~start_toggle;
|
||||
busy <= 1;
|
||||
end
|
||||
if (rst_soft) begin
|
||||
rst_toggle <= ~rst_toggle;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
// cntrl -> DAC: start/reset event sync
|
||||
(* ASYNC_REG = "TRUE" *) logic start_meta_dac, start_sync_dac;
|
||||
logic start_sync_dac_d;
|
||||
(* ASYNC_REG = "TRUE" *) logic rst_meta_dac, rst_sync_dac;
|
||||
logic rst_sync_dac_d;
|
||||
|
||||
wire dac_start_pulse = start_sync_dac ^ start_sync_dac_d;
|
||||
wire dac_rst_pulse = rst_sync_dac ^ rst_sync_dac_d;
|
||||
|
||||
always_ff @(posedge dac_clk_in or posedge dac_rst_int) begin
|
||||
if (dac_rst_int) begin
|
||||
start_meta_dac <= 1'b0;
|
||||
start_sync_dac <= 1'b0;
|
||||
start_sync_dac_d <= 1'b0;
|
||||
|
||||
rst_meta_dac <= 1'b0;
|
||||
rst_sync_dac <= 1'b0;
|
||||
rst_sync_dac_d <= 1'b0;
|
||||
|
||||
dac_start <= 1'b0;
|
||||
dac_rst <= 1'b0;
|
||||
end else begin
|
||||
start_meta_dac <= start_toggle;
|
||||
start_sync_dac <= start_meta_dac;
|
||||
start_sync_dac_d <= start_sync_dac;
|
||||
|
||||
rst_meta_dac <= rst_toggle;
|
||||
rst_sync_dac <= rst_meta_dac;
|
||||
rst_sync_dac_d <= rst_sync_dac;
|
||||
|
||||
dac_start <= dac_start_pulse;
|
||||
dac_rst <= dac_rst_pulse;
|
||||
end
|
||||
end
|
||||
|
||||
// cntrl -> ADC: start/reset event sync
|
||||
(* ASYNC_REG = "TRUE" *) logic start_meta_adc, start_sync_adc;
|
||||
logic start_sync_adc_d;
|
||||
(* ASYNC_REG = "TRUE" *) logic rst_meta_adc, rst_sync_adc;
|
||||
logic rst_sync_adc_d;
|
||||
|
||||
wire adc_start_pulse = start_sync_adc ^ start_sync_adc_d;
|
||||
wire adc_rst_pulse = rst_sync_adc ^ rst_sync_adc_d;
|
||||
|
||||
always_ff @(posedge adc_clk_in or posedge adc_rst_int) begin
|
||||
if (adc_rst_int) begin
|
||||
start_meta_adc <= 1'b0;
|
||||
start_sync_adc <= 1'b0;
|
||||
start_sync_adc_d <= 1'b0;
|
||||
|
||||
rst_meta_adc <= 1'b0;
|
||||
rst_sync_adc <= 1'b0;
|
||||
rst_sync_adc_d <= 1'b0;
|
||||
|
||||
adc_start <= 1'b0;
|
||||
adc_rst <= 1'b0;
|
||||
end else begin
|
||||
start_meta_adc <= start_toggle;
|
||||
start_sync_adc <= start_meta_adc;
|
||||
start_sync_adc_d <= start_sync_adc;
|
||||
|
||||
rst_meta_adc <= rst_toggle;
|
||||
rst_sync_adc <= rst_meta_adc;
|
||||
rst_sync_adc_d <= rst_sync_adc;
|
||||
|
||||
adc_start <= adc_start_pulse;
|
||||
adc_rst <= adc_rst_pulse;
|
||||
end
|
||||
end
|
||||
|
||||
// contrl -> DAC config CDC
|
||||
// cfg_bus is kept stable in contrl domain until DAC and ADC both ACK.
|
||||
(* ASYNC_REG = "TRUE" *) logic cfg_req_meta_dac, cfg_req_sync_dac;
|
||||
logic cfg_req_sync_dac_d;
|
||||
wire cfg_req_pulse_dac = cfg_req_sync_dac ^ cfg_req_sync_dac_d;
|
||||
|
||||
always_ff @(posedge dac_clk_in or posedge dac_rst_int) begin
|
||||
if (dac_rst_int) begin
|
||||
cfg_req_meta_dac <= 1'b0;
|
||||
cfg_req_sync_dac <= 1'b0;
|
||||
cfg_req_sync_dac_d<= 1'b0;
|
||||
cfg_ack_toggle_dac<= 1'b0;
|
||||
|
||||
dac_pulse_width <= '0;
|
||||
dac_pulse_period <= '0;
|
||||
dac_pulse_num <= '0;
|
||||
dac_pulse_height <= '0;
|
||||
end else begin
|
||||
cfg_req_meta_dac <= cfg_req_toggle_dac;
|
||||
cfg_req_sync_dac <= cfg_req_meta_dac;
|
||||
cfg_req_sync_dac_d <= cfg_req_sync_dac;
|
||||
|
||||
if (cfg_req_pulse_dac) begin
|
||||
dac_pulse_width <= cfg_bus[31:0];
|
||||
dac_pulse_period <= cfg_bus[63:32];
|
||||
dac_pulse_num <= cfg_bus[79:64];
|
||||
dac_pulse_height <= cfg_bus[80 +: DAC_DATA_WIDTH];
|
||||
|
||||
cfg_ack_toggle_dac <= ~cfg_ack_toggle_dac;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// cntrl -> ADC config CDC
|
||||
logic cfg_req_meta_adc, cfg_req_sync_adc, cfg_req_sync_adc_d;
|
||||
wire cfg_req_pulse_adc = cfg_req_sync_adc ^ cfg_req_sync_adc_d;
|
||||
|
||||
always_ff @(posedge adc_clk_in or posedge adc_rst_int) begin
|
||||
if (adc_rst_int) begin
|
||||
cfg_req_meta_adc <= 1'b0;
|
||||
cfg_req_sync_adc <= 1'b0;
|
||||
cfg_req_sync_adc_d <= 1'b0;
|
||||
cfg_ack_toggle_adc <= 1'b0;
|
||||
|
||||
adc_pulse_period <= '0;
|
||||
adc_pulse_num <= '0;
|
||||
adc_window_size <= '0;
|
||||
end else begin
|
||||
cfg_req_meta_adc <= cfg_req_toggle_adc;
|
||||
cfg_req_sync_adc <= cfg_req_meta_adc;
|
||||
cfg_req_sync_adc_d <= cfg_req_sync_adc;
|
||||
|
||||
if (cfg_req_pulse_adc) begin
|
||||
adc_pulse_period <= cfg_bus[127:96];
|
||||
adc_pulse_num <= cfg_bus[79:64];
|
||||
adc_window_size <= cfg_bus[159:128];
|
||||
|
||||
cfg_ack_toggle_adc <= ~cfg_ack_toggle_adc;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user