initial commit, add dds_par module
This commit is contained in:
@@ -0,0 +1,659 @@
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
// Copyright (C) 2023 Analog Devices, Inc. All rights reserved.
|
||||
//
|
||||
// In this HDL repository, there are many different and unique modules, consisting
|
||||
// of various HDL (Verilog or VHDL) components. The individual modules are
|
||||
// developed independently, and may be accompanied by separate and unique license
|
||||
// terms.
|
||||
//
|
||||
// The user should read each of these license terms, and understand the
|
||||
// freedoms and responsibilities that he or she has by using this source/core.
|
||||
//
|
||||
// This core is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
// A PARTICULAR PURPOSE.
|
||||
//
|
||||
// Redistribution and use of source or resulting binaries, with or without modification
|
||||
// of this file, are permitted under one of the following two license terms:
|
||||
//
|
||||
// 1. The GNU General Public License version 2 as published by the
|
||||
// Free Software Foundation, which can be found in the top level directory
|
||||
// of this repository (LICENSE_GPL2), and also online at:
|
||||
// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
|
||||
//
|
||||
// OR
|
||||
//
|
||||
// 2. An ADI specific BSD license, which can be found in the top level directory
|
||||
// of this repository (LICENSE_ADIBSD), and also on-line at:
|
||||
// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD
|
||||
// This will allow to generate bit files and not release the source code,
|
||||
// as long as it attaches to an ADI device.
|
||||
//
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
|
||||
`timescale 1ns/100ps
|
||||
|
||||
module axi_ad4858_cmos #(
|
||||
|
||||
parameter FPGA_TECHNOLOGY = 0,
|
||||
parameter DELAY_REFCLK_FREQ = 200,
|
||||
parameter IODELAY_ENABLE = 1,
|
||||
parameter IODELAY_GROUP = "dev_if_delay_group",
|
||||
parameter ACTIVE_LANE = 8'b11111111
|
||||
) (
|
||||
|
||||
input rst,
|
||||
input clk,
|
||||
input [ 7:0] adc_enable,
|
||||
input adc_crc_enable,
|
||||
|
||||
// physical interface
|
||||
|
||||
output scki,
|
||||
input scko,
|
||||
input [ 7:0] db_i,
|
||||
input busy,
|
||||
input cnvs,
|
||||
|
||||
// format
|
||||
|
||||
input [ 1:0] packet_format,
|
||||
input oversampling_en,
|
||||
|
||||
// channel interface
|
||||
|
||||
output [255:0] adc_data,
|
||||
output reg adc_valid,
|
||||
output reg crc_error,
|
||||
output [ 7:0] dev_status,
|
||||
|
||||
// delay interface (for IDELAY macros)
|
||||
|
||||
input up_clk,
|
||||
input [ 7:0] up_adc_dld,
|
||||
input [39:0] up_adc_dwdata,
|
||||
output [39:0] up_adc_drdata,
|
||||
input delay_clk,
|
||||
input delay_rst,
|
||||
output delay_locked
|
||||
);
|
||||
|
||||
localparam NEG_EDGE = 1;
|
||||
localparam DW = 32;
|
||||
localparam BW = DW - 1;
|
||||
localparam PACKET_1_BITS = 20;
|
||||
localparam PACKET_2_BITS = 24;
|
||||
localparam PACKET_3_BITS = 32;
|
||||
|
||||
// internal registers
|
||||
|
||||
reg [BW:0] adc_lane_0;
|
||||
reg [BW:0] adc_lane_1;
|
||||
reg [BW:0] adc_lane_2;
|
||||
reg [BW:0] adc_lane_3;
|
||||
reg [BW:0] adc_lane_4;
|
||||
reg [BW:0] adc_lane_5;
|
||||
reg [BW:0] adc_lane_6;
|
||||
reg [BW:0] adc_lane_7;
|
||||
|
||||
reg [ 5:0] data_counter = 6'h0;
|
||||
reg [ 5:0] scki_counter = 6'h0;
|
||||
|
||||
reg scki_i;
|
||||
reg scki_d;
|
||||
|
||||
reg [BW:0] adc_data_store[8:0];
|
||||
reg [BW:0] adc_data_init[7:0];
|
||||
reg adc_valid_init;
|
||||
reg adc_valid_init_d;
|
||||
|
||||
reg [ 8:0] ch_capture;
|
||||
reg [ 8:0] ch_captured;
|
||||
|
||||
reg [ 4:0] adc_ch0_shift;
|
||||
reg [ 4:0] adc_ch1_shift;
|
||||
reg [ 4:0] adc_ch2_shift;
|
||||
reg [ 4:0] adc_ch3_shift;
|
||||
reg [ 4:0] adc_ch4_shift;
|
||||
reg [ 4:0] adc_ch5_shift;
|
||||
reg [ 4:0] adc_ch6_shift;
|
||||
reg [ 4:0] adc_ch7_shift;
|
||||
|
||||
reg [ 4:0] adc_ch0_shift_d;
|
||||
reg [ 4:0] adc_ch1_shift_d;
|
||||
reg [ 4:0] adc_ch2_shift_d;
|
||||
reg [ 4:0] adc_ch3_shift_d;
|
||||
reg [ 4:0] adc_ch4_shift_d;
|
||||
reg [ 4:0] adc_ch5_shift_d;
|
||||
reg [ 4:0] adc_ch6_shift_d;
|
||||
reg [ 4:0] adc_ch7_shift_d;
|
||||
|
||||
reg [ 3:0] lane_0_data = 'd0;
|
||||
reg [ 3:0] lane_1_data = 'd0;
|
||||
reg [ 3:0] lane_2_data = 'd0;
|
||||
reg [ 3:0] lane_3_data = 'd0;
|
||||
reg [ 3:0] lane_4_data = 'd0;
|
||||
reg [ 3:0] lane_5_data = 'd0;
|
||||
reg [ 3:0] lane_6_data = 'd0;
|
||||
reg [ 3:0] lane_7_data = 'd0;
|
||||
reg [ 8:0] ch_data_lock = 'h1ff;
|
||||
|
||||
reg busy_m1;
|
||||
reg busy_m2;
|
||||
reg cnvs_d;
|
||||
reg [31:0] period_cnt;
|
||||
|
||||
reg conversion_quiet_time;
|
||||
reg run_busy_period_cnt;
|
||||
reg [31:0] busy_conversion_cnt;
|
||||
reg [31:0] busy_measure_value;
|
||||
reg start_transfer;
|
||||
|
||||
reg crc_enable_window;
|
||||
reg run_crc;
|
||||
reg run_crc_d;
|
||||
reg [288:0] crc_data_in;
|
||||
reg [15:0] crc_cnt;
|
||||
reg [ 7:0] data_in_byte;
|
||||
|
||||
// internal wires
|
||||
|
||||
wire [ 7:0] db_s;
|
||||
|
||||
wire [31:0] status_and_crc_data;
|
||||
|
||||
wire aquire_data;
|
||||
wire scki_cnt_rst;
|
||||
wire adc_cnvs_redge;
|
||||
wire conversion_completed;
|
||||
wire conversion_quiet_time_s;
|
||||
|
||||
wire [ 5:0] packet_lenght;
|
||||
|
||||
wire crc_reset;
|
||||
wire crc_enable;
|
||||
wire crc_valid;
|
||||
wire [15:0] crc_res;
|
||||
wire [15:0] crc_data_lenght;
|
||||
|
||||
// packet format selection
|
||||
|
||||
assign packet_lenght = packet_format == 2'd0 ? 6'd20 :
|
||||
packet_format == 2'd1 ? 6'd24 : 6'd32;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
busy_m1 <= 1'b0;
|
||||
busy_m2 <= 1'b0;
|
||||
start_transfer <= 1'b0;
|
||||
end else begin
|
||||
busy_m1 <= busy;
|
||||
busy_m2 <= busy_m1;
|
||||
start_transfer <= busy_m2 & !busy_m1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (start_transfer) begin
|
||||
crc_enable_window <= adc_crc_enable;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
scki_counter <= 5'h0;
|
||||
scki_i <= 1'b1;
|
||||
scki_d <= 1'b0;
|
||||
end else begin
|
||||
scki_d <= scki_i;
|
||||
if (aquire_data == 1'b0) begin
|
||||
scki_counter <= 5'h0;
|
||||
scki_i <= 1'b1;
|
||||
end else if (scki_cnt_rst & (scki_d & ~scki_i)) begin // end of a capture
|
||||
scki_counter <= 5'h1;
|
||||
scki_i <= 1'b1;
|
||||
end else if (scki_i == 1'b0) begin
|
||||
scki_counter <= scki_counter + 1;
|
||||
scki_i <= 1'b1;
|
||||
end else if (conversion_quiet_time_s == 1'b1) begin
|
||||
scki_counter <= scki_counter;
|
||||
scki_i <= scki_i;
|
||||
end else begin
|
||||
scki_counter <= scki_counter;
|
||||
scki_i <= ~scki_i;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// busy period counter
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
run_busy_period_cnt <= 1'b0;
|
||||
busy_conversion_cnt <= 'd0;
|
||||
busy_measure_value <= 'd0;
|
||||
end else begin
|
||||
if (cnvs == 1'b1 && busy_m2 == 1'b1) begin
|
||||
run_busy_period_cnt <= 1'b1;
|
||||
end else if (start_transfer == 1'b1) begin
|
||||
run_busy_period_cnt <= 1'b0;
|
||||
end
|
||||
|
||||
if (adc_cnvs_redge == 1'b1) begin
|
||||
busy_conversion_cnt <= 'd0;
|
||||
end else if (start_transfer == 1'b1) begin
|
||||
busy_measure_value <= busy_conversion_cnt;
|
||||
end else if (run_busy_period_cnt == 1'b1) begin
|
||||
busy_conversion_cnt <= busy_conversion_cnt + 'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
period_cnt <= 'd0;
|
||||
cnvs_d <= 'd0;
|
||||
conversion_quiet_time <= 1'b0;
|
||||
end else begin
|
||||
cnvs_d <= cnvs;
|
||||
if (oversampling_en == 1 && adc_cnvs_redge == 1'b1) begin
|
||||
conversion_quiet_time <= 1'b1;
|
||||
end else begin
|
||||
conversion_quiet_time <= conversion_quiet_time & ~conversion_completed;
|
||||
end
|
||||
if (adc_cnvs_redge == 1'b1) begin
|
||||
period_cnt <= 'd0;
|
||||
end else begin
|
||||
period_cnt <= period_cnt + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign conversion_quiet_time_s = (oversampling_en == 1) ? conversion_quiet_time | cnvs : 1'b0;
|
||||
assign conversion_completed = (period_cnt == busy_measure_value) ? 1'b1 : 1'b0;
|
||||
assign adc_cnvs_redge = ~cnvs_d & cnvs;
|
||||
assign scki_cnt_rst = (scki_counter == packet_lenght) ? 1'b1 : 1'b0;
|
||||
assign scki = scki_i | ~aquire_data;
|
||||
|
||||
/*
|
||||
The device sends each channel data on one of the 8 lines.
|
||||
Data is stored in the device in a ring buffer. After the first packet is read
|
||||
and no new conversion is activated if the reading process restarted,
|
||||
the new data on the lines will be from the next index from the ring buffer.
|
||||
e.g For second read process without a conversion start
|
||||
line 0 = channel 1, line 1 = channel 2, line 2 = channel 3; so on and so forth.
|
||||
*/
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (start_transfer) begin
|
||||
lane_0_data <= 4'd0;
|
||||
lane_1_data <= 4'd1;
|
||||
lane_2_data <= 4'd2;
|
||||
lane_3_data <= 4'd3;
|
||||
lane_4_data <= 4'd4;
|
||||
lane_5_data <= 4'd5;
|
||||
lane_6_data <= 4'd6;
|
||||
lane_7_data <= 4'd7;
|
||||
ch_data_lock <= 9'd0;
|
||||
end else if (aquire_data == 1'b1 && (scki_cnt_rst & (~scki_d & scki_i))) begin
|
||||
lane_0_data <= lane_0_data[3] == 1'b1 ? 4'd0 : lane_0_data + 1;
|
||||
lane_1_data <= lane_1_data[3] == 1'b1 ? 4'd0 : lane_1_data + 1;
|
||||
lane_2_data <= lane_2_data[3] == 1'b1 ? 4'd0 : lane_2_data + 1;
|
||||
lane_3_data <= lane_3_data[3] == 1'b1 ? 4'd0 : lane_3_data + 1;
|
||||
lane_4_data <= lane_4_data[3] == 1'b1 ? 4'd0 : lane_4_data + 1;
|
||||
lane_5_data <= lane_5_data[3] == 1'b1 ? 4'd0 : lane_5_data + 1;
|
||||
lane_6_data <= lane_6_data[3] == 1'b1 ? 4'd0 : lane_6_data + 1;
|
||||
lane_7_data <= lane_7_data[3] == 1'b1 ? 4'd0 : lane_7_data + 1;
|
||||
ch_data_lock[lane_0_data[3:0]] <= ACTIVE_LANE[0] ? 1'b1 : ch_data_lock[lane_0_data[2:0]];
|
||||
ch_data_lock[lane_1_data[3:0]] <= ACTIVE_LANE[1] ? 1'b1 : ch_data_lock[lane_1_data[2:0]];
|
||||
ch_data_lock[lane_2_data[3:0]] <= ACTIVE_LANE[2] ? 1'b1 : ch_data_lock[lane_2_data[2:0]];
|
||||
ch_data_lock[lane_3_data[3:0]] <= ACTIVE_LANE[3] ? 1'b1 : ch_data_lock[lane_3_data[2:0]];
|
||||
ch_data_lock[lane_4_data[3:0]] <= ACTIVE_LANE[4] ? 1'b1 : ch_data_lock[lane_4_data[2:0]];
|
||||
ch_data_lock[lane_5_data[3:0]] <= ACTIVE_LANE[5] ? 1'b1 : ch_data_lock[lane_5_data[2:0]];
|
||||
ch_data_lock[lane_6_data[3:0]] <= ACTIVE_LANE[6] ? 1'b1 : ch_data_lock[lane_6_data[2:0]];
|
||||
ch_data_lock[lane_7_data[3:0]] <= ACTIVE_LANE[7] ? 1'b1 : ch_data_lock[lane_7_data[2:0]];
|
||||
end else begin
|
||||
lane_0_data <= lane_0_data;
|
||||
lane_1_data <= lane_1_data;
|
||||
lane_2_data <= lane_2_data;
|
||||
lane_3_data <= lane_3_data;
|
||||
lane_4_data <= lane_4_data;
|
||||
lane_5_data <= lane_5_data;
|
||||
lane_6_data <= lane_6_data;
|
||||
lane_7_data <= lane_7_data;
|
||||
ch_data_lock <= ch_data_lock;
|
||||
end
|
||||
end
|
||||
|
||||
assign aquire_data = ~((ch_data_lock[0] | ~adc_enable[0]) &
|
||||
(ch_data_lock[1] | ~adc_enable[1]) &
|
||||
(ch_data_lock[2] | ~adc_enable[2]) &
|
||||
(ch_data_lock[3] | ~adc_enable[3]) &
|
||||
(ch_data_lock[4] | ~adc_enable[4]) &
|
||||
(ch_data_lock[5] | ~adc_enable[5]) &
|
||||
(ch_data_lock[6] | ~adc_enable[6]) &
|
||||
(ch_data_lock[7] | ~adc_enable[7]) &
|
||||
(ch_data_lock[8] | ~crc_enable_window));
|
||||
|
||||
// capture data
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
if (IODELAY_ENABLE == 1) begin
|
||||
ad_data_in #(
|
||||
.SINGLE_ENDED (1),
|
||||
.DDR_SDR_N (0),
|
||||
.FPGA_TECHNOLOGY (FPGA_TECHNOLOGY),
|
||||
.IODELAY_CTRL (1),
|
||||
.IODELAY_ENABLE (IODELAY_ENABLE),
|
||||
.IODELAY_GROUP (IODELAY_GROUP),
|
||||
.REFCLK_FREQUENCY (DELAY_REFCLK_FREQ)
|
||||
) i_rx_data (
|
||||
.rx_clk (scko),
|
||||
.rx_data_in_p (db_i[0]),
|
||||
.rx_data_in_n (1'd0),
|
||||
.rx_data_p (db_s[0]),
|
||||
.rx_data_n (),
|
||||
.up_clk (up_clk),
|
||||
.up_dld (up_adc_dld[0]),
|
||||
.up_dwdata (up_adc_dwdata[4:0]),
|
||||
.up_drdata (up_adc_drdata[4:0]),
|
||||
.delay_clk (delay_clk),
|
||||
.delay_rst (delay_rst),
|
||||
.delay_locked (delay_locked));
|
||||
end
|
||||
for (i = 1; i < 8; i = i + 1) begin: g_rx_lanes
|
||||
ad_data_in #(
|
||||
.SINGLE_ENDED (1),
|
||||
.DDR_SDR_N (0),
|
||||
.FPGA_TECHNOLOGY (FPGA_TECHNOLOGY),
|
||||
.IODELAY_CTRL (0),
|
||||
.IODELAY_ENABLE (IODELAY_ENABLE),
|
||||
.IODELAY_GROUP (IODELAY_GROUP),
|
||||
.REFCLK_FREQUENCY (DELAY_REFCLK_FREQ)
|
||||
) i_rx_data (
|
||||
.rx_clk (scko),
|
||||
.rx_data_in_p (db_i[i]),
|
||||
.rx_data_in_n (1'd0),
|
||||
.rx_data_p (db_s[i]),
|
||||
.rx_data_n (),
|
||||
.up_clk (up_clk),
|
||||
.up_dld (up_adc_dld[i]),
|
||||
.up_dwdata (up_adc_dwdata[((i*5)+4):(i*5)]),
|
||||
.up_drdata (up_adc_drdata[((i*5)+4):(i*5)]),
|
||||
.delay_clk (delay_clk),
|
||||
.delay_rst (delay_rst),
|
||||
.delay_locked ());
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// the most significant bits of the adc_lane_x will remaind from the
|
||||
// previous sample for packet formats other than 32.
|
||||
|
||||
always @(negedge scko) begin
|
||||
adc_lane_0 <= {adc_lane_0[BW-1:0], db_s[0]};
|
||||
adc_lane_1 <= {adc_lane_1[BW-1:0], db_s[1]};
|
||||
adc_lane_2 <= {adc_lane_2[BW-1:0], db_s[2]};
|
||||
adc_lane_3 <= {adc_lane_3[BW-1:0], db_s[3]};
|
||||
adc_lane_4 <= {adc_lane_4[BW-1:0], db_s[4]};
|
||||
adc_lane_5 <= {adc_lane_5[BW-1:0], db_s[5]};
|
||||
adc_lane_6 <= {adc_lane_6[BW-1:0], db_s[6]};
|
||||
adc_lane_7 <= {adc_lane_7[BW-1:0], db_s[7]};
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_valid_init <= 1'b0;
|
||||
end else begin
|
||||
if (data_counter == packet_lenght && adc_valid_init == 1'b0) begin
|
||||
adc_valid_init <= 1'b1;
|
||||
end else begin
|
||||
adc_valid_init <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_data_init[0] <= 'h0;
|
||||
adc_data_init[1] <= 'h0;
|
||||
adc_data_init[2] <= 'h0;
|
||||
adc_data_init[3] <= 'h0;
|
||||
adc_data_init[4] <= 'h0;
|
||||
adc_data_init[5] <= 'h0;
|
||||
adc_data_init[6] <= 'h0;
|
||||
adc_data_init[7] <= 'h0;
|
||||
data_counter <= 'h0;
|
||||
end else begin
|
||||
data_counter <= scki_counter;
|
||||
if (data_counter == packet_lenght) begin
|
||||
adc_data_init[0] <= adc_lane_0;
|
||||
adc_data_init[1] <= adc_lane_1;
|
||||
adc_data_init[2] <= adc_lane_2;
|
||||
adc_data_init[3] <= adc_lane_3;
|
||||
adc_data_init[4] <= adc_lane_4;
|
||||
adc_data_init[5] <= adc_lane_5;
|
||||
adc_data_init[6] <= adc_lane_6;
|
||||
adc_data_init[7] <= adc_lane_7;
|
||||
end else begin
|
||||
adc_data_init[0] <= adc_data_init[0];
|
||||
adc_data_init[1] <= adc_data_init[1];
|
||||
adc_data_init[2] <= adc_data_init[2];
|
||||
adc_data_init[3] <= adc_data_init[3];
|
||||
adc_data_init[4] <= adc_data_init[4];
|
||||
adc_data_init[5] <= adc_data_init[5];
|
||||
adc_data_init[6] <= adc_data_init[6];
|
||||
adc_data_init[7] <= adc_data_init[7];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1 || adc_valid == 1'b1) begin
|
||||
adc_valid <= 1'b0;
|
||||
adc_valid_init_d <= 1'b0;
|
||||
ch_capture <= 9'd0;
|
||||
ch_captured <= 9'd0;
|
||||
|
||||
adc_ch0_shift <= 4'd0;
|
||||
adc_ch1_shift <= 4'd0;
|
||||
adc_ch2_shift <= 4'd0;
|
||||
adc_ch3_shift <= 4'd0;
|
||||
adc_ch4_shift <= 4'd0;
|
||||
adc_ch5_shift <= 4'd0;
|
||||
adc_ch6_shift <= 4'd0;
|
||||
adc_ch7_shift <= 4'd0;
|
||||
adc_ch0_shift_d <= 4'd0;
|
||||
adc_ch1_shift_d <= 4'd0;
|
||||
adc_ch2_shift_d <= 4'd0;
|
||||
adc_ch3_shift_d <= 4'd0;
|
||||
adc_ch4_shift_d <= 4'd0;
|
||||
adc_ch5_shift_d <= 4'd0;
|
||||
adc_ch6_shift_d <= 4'd0;
|
||||
adc_ch7_shift_d <= 4'd0;
|
||||
end else begin
|
||||
ch_capture <= ch_data_lock;
|
||||
ch_captured <= ch_capture;
|
||||
adc_valid_init_d <= adc_valid_init;
|
||||
|
||||
adc_ch0_shift <= {ACTIVE_LANE[0],lane_0_data};
|
||||
adc_ch1_shift <= {ACTIVE_LANE[1],lane_1_data};
|
||||
adc_ch2_shift <= {ACTIVE_LANE[2],lane_2_data};
|
||||
adc_ch3_shift <= {ACTIVE_LANE[3],lane_3_data};
|
||||
adc_ch4_shift <= {ACTIVE_LANE[4],lane_4_data};
|
||||
adc_ch5_shift <= {ACTIVE_LANE[5],lane_5_data};
|
||||
adc_ch6_shift <= {ACTIVE_LANE[6],lane_6_data};
|
||||
adc_ch7_shift <= {ACTIVE_LANE[7],lane_7_data};
|
||||
adc_ch0_shift_d <= adc_ch0_shift;
|
||||
adc_ch1_shift_d <= adc_ch1_shift;
|
||||
adc_ch2_shift_d <= adc_ch2_shift;
|
||||
adc_ch3_shift_d <= adc_ch3_shift;
|
||||
adc_ch4_shift_d <= adc_ch4_shift;
|
||||
adc_ch5_shift_d <= adc_ch5_shift;
|
||||
adc_ch6_shift_d <= adc_ch6_shift;
|
||||
adc_ch7_shift_d <= adc_ch7_shift;
|
||||
adc_valid <= adc_valid_init_d &
|
||||
(ch_captured[0] | ~adc_enable[0]) &
|
||||
(ch_captured[1] | ~adc_enable[1]) &
|
||||
(ch_captured[2] | ~adc_enable[2]) &
|
||||
(ch_captured[3] | ~adc_enable[3]) &
|
||||
(ch_captured[4] | ~adc_enable[4]) &
|
||||
(ch_captured[5] | ~adc_enable[5]) &
|
||||
(ch_captured[6] | ~adc_enable[6]) &
|
||||
(ch_captured[7] | ~adc_enable[7]) &
|
||||
(ch_captured[8] | ~crc_enable_window);
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1'b1) begin
|
||||
adc_data_store[0] <= 'd0;
|
||||
adc_data_store[1] <= 'd0;
|
||||
adc_data_store[2] <= 'd0;
|
||||
adc_data_store[3] <= 'd0;
|
||||
adc_data_store[4] <= 'd0;
|
||||
adc_data_store[5] <= 'd0;
|
||||
adc_data_store[6] <= 'd0;
|
||||
adc_data_store[7] <= 'd0;
|
||||
adc_data_store[8] <= 'd0;
|
||||
end else begin
|
||||
if (!adc_valid_init_d & adc_valid_init) begin
|
||||
if (adc_ch0_shift_d[4] == 1'b1) begin
|
||||
adc_data_store[adc_ch0_shift_d[3:0]] <= adc_data_init[0];
|
||||
end
|
||||
if (adc_ch1_shift_d[4] == 1'b1) begin
|
||||
adc_data_store[adc_ch1_shift_d[3:0]] <= adc_data_init[1];
|
||||
end
|
||||
if (adc_ch2_shift_d[4] == 1'b1) begin
|
||||
adc_data_store[adc_ch2_shift_d[3:0]] <= adc_data_init[2];
|
||||
end
|
||||
if (adc_ch3_shift_d[4] == 1'b1) begin
|
||||
adc_data_store[adc_ch3_shift_d[3:0]] <= adc_data_init[3];
|
||||
end
|
||||
if (adc_ch4_shift_d[4] == 1'b1) begin
|
||||
adc_data_store[adc_ch4_shift_d[3:0]] <= adc_data_init[4];
|
||||
end
|
||||
if (adc_ch5_shift_d[4] == 1'b1) begin
|
||||
adc_data_store[adc_ch5_shift_d[3:0]] <= adc_data_init[5];
|
||||
end
|
||||
if (adc_ch6_shift_d[4] == 1'b1) begin
|
||||
adc_data_store[adc_ch6_shift_d[3:0]] <= adc_data_init[6];
|
||||
end
|
||||
if (adc_ch7_shift_d[4] == 1'b1) begin
|
||||
adc_data_store[adc_ch7_shift_d[3:0]] <= adc_data_init[7];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign dev_status = packet_format == 0 ? adc_data_store[8][23:16] << 4 :
|
||||
adc_data_store[8][23:16];
|
||||
assign crc_data = adc_data_store[8][15:0];
|
||||
assign adc_data = {adc_data_store[7],
|
||||
adc_data_store[6],
|
||||
adc_data_store[5],
|
||||
adc_data_store[4],
|
||||
adc_data_store[3],
|
||||
adc_data_store[2],
|
||||
adc_data_store[1],
|
||||
adc_data_store[0]};
|
||||
|
||||
// CRC checker logic
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst == 1) begin
|
||||
crc_data_in <= 0;
|
||||
end else begin
|
||||
if (adc_valid == 1) begin
|
||||
if (packet_format == 0) begin
|
||||
crc_data_in <= {104'd0,
|
||||
adc_data_store[0][19:0],
|
||||
adc_data_store[1][19:0],
|
||||
adc_data_store[2][19:0],
|
||||
adc_data_store[3][19:0],
|
||||
adc_data_store[4][19:0],
|
||||
adc_data_store[5][19:0],
|
||||
adc_data_store[6][19:0],
|
||||
adc_data_store[7][19:0],
|
||||
adc_data_store[8][19:0],
|
||||
4'd0};
|
||||
end else if (packet_format == 1) begin
|
||||
crc_data_in <= {72'd0,
|
||||
adc_data_store[0][23:0],
|
||||
adc_data_store[1][23:0],
|
||||
adc_data_store[2][23:0],
|
||||
adc_data_store[3][23:0],
|
||||
adc_data_store[4][23:0],
|
||||
adc_data_store[5][23:0],
|
||||
adc_data_store[6][23:0],
|
||||
adc_data_store[7][23:0],
|
||||
adc_data_store[8][23:0]};
|
||||
end else begin
|
||||
crc_data_in <= {adc_data_store[0],
|
||||
adc_data_store[1],
|
||||
adc_data_store[2],
|
||||
adc_data_store[3],
|
||||
adc_data_store[4],
|
||||
adc_data_store[5],
|
||||
adc_data_store[6],
|
||||
adc_data_store[7],
|
||||
adc_data_store[8]};
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// As an optimization, a crc checker with 8 parallel operations per clk cycle
|
||||
// will be used for all packet formats.
|
||||
// The channel plus status and crc data will be feed in byte packets to the
|
||||
// crc checker.
|
||||
// When packet_format is 20 bits, 20x8+20(st and crc) = 180 which is not a
|
||||
// multiple of 8. So, we will feed 184 bits, which is a multiple of 8.
|
||||
// First extra 4 bits entering the checker being 0, will not affect the result
|
||||
// since the initial value of the LFSR is 0x0000.
|
||||
assign crc_data_lenght = packet_format == 2'd0 ? 16'd176 : // 184-8
|
||||
packet_format == 2'd1 ? 16'd208 : 16'd280;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (crc_enable_window == 0 || adc_valid == 1) begin
|
||||
crc_cnt <= crc_data_lenght;
|
||||
data_in_byte <= 0;
|
||||
run_crc <= adc_valid;
|
||||
end else begin
|
||||
if (run_crc == 1'b1) begin
|
||||
if (crc_cnt == 0) begin
|
||||
run_crc <= 1'b0;
|
||||
end else begin
|
||||
crc_cnt <= crc_cnt - 8;
|
||||
end
|
||||
data_in_byte <= crc_data_in[crc_cnt +: 8];
|
||||
end else begin
|
||||
end
|
||||
end
|
||||
// the counter is initialized with n-1 to accommodate the byte shifter
|
||||
run_crc_d <= run_crc;
|
||||
end
|
||||
|
||||
assign crc_reset = adc_valid;
|
||||
assign crc_enable = run_crc | run_crc_d;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (crc_valid == 1) begin
|
||||
if (crc_res == 16'd0) begin
|
||||
crc_error <= 1'd0;
|
||||
end else begin
|
||||
crc_error <= 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
axi_ad4858_crc i_ad4858_crc_8 (
|
||||
.rst (crc_reset),
|
||||
.clk (clk),
|
||||
.crc_en (crc_enable),
|
||||
.d_in (data_in_byte),
|
||||
.crc_valid (crc_valid),
|
||||
.crc_res (crc_res));
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user