module ad7606_serial( input i_clk , input i_rst , input i_en , input i_din_a , input i_din_b , input i_busy , output reg [15:0] o_dout_0, output reg [15:0] o_dout_1, output reg [15:0] o_dout_2, output reg [15:0] o_dout_3, output reg [15:0] o_dout_4, output reg [15:0] o_dout_5, output reg [15:0] o_dout_6, output reg [15:0] o_dout_7, output reg o_dvld , output reg o_cs , output reg o_sclk , output reg [1:0] o_convst, output [2:0] o_os , output o_rst , output o_range );
assign o_os = 3'b000 ;
assign o_rst = 0 ;
assign o_range = 1 ;
localparam S_IDLE = 6'b000001 , S_CVST = 6'b000010 , S_BUSY = 6'b000100 , S_CSEL = 6'b001000 , S_RECV = 6'b010000 , S_DONE = 6'b100000 ;
reg [5:0] r_cstate;
reg [5:0] r_nstate;
reg r_cvst_flag;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_cvst_flag <= 'b0;
else if(r_cstate == S_CVST) r_cvst_flag <= 'b1;
else r_cvst_flag <= 'b0;
end
reg r_busy_d0;
reg r_busy_d1;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) begin
r_busy_d0 <= 'b0;
r_busy_d1 <= 'b0;
end
else begin
r_busy_d0 <= i_busy ;
r_busy_d1 <= r_busy_d0 ;
end
end
reg [1:0] r_clk_cnt;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_clk_cnt <= 'd0;
else if(r_cstate == S_RECV) r_clk_cnt <= r_clk_cnt + 1;
else r_clk_cnt <= 'd0;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) o_convst <= 2'b11;
else if(r_cstate == S_CVST) o_convst <= 2'b00;
else o_convst <= 2'b11;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) o_cs <= 'b1;
else if(r_cstate == S_DONE) o_cs <= 'b1;
else if(r_cstate == S_CSEL) o_cs <= 'b0;
else o_cs <= o_cs;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) o_sclk <= 'b1;
else if(r_cstate == S_RECV) o_sclk <= r_clk_cnt[0] ? ~o_sclk : o_sclk;
else o_sclk <= 'b1;
end
reg [15:0] r_rxdata_a;
reg [15:0] r_rxdata_b;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) begin
r_rxdata_a <= 'd0;
r_rxdata_b <= 'd0;
end
else if(r_cstate == S_RECV) begin
if(r_clk_cnt == 2'b11) begin
r_rxdata_a <= {r_rxdata_a[14:0], i_din_a};
r_rxdata_b <= {r_rxdata_b[14:0], i_din_b};
end
else begin
r_rxdata_a <= r_rxdata_a;
r_rxdata_b <= r_rxdata_b;
end
end
else begin
r_rxdata_a <= 'd0;
r_rxdata_b <= 'd0;
end
end
reg [3:0] r_bit_cnt ;
reg [1:0] r_ch_cnt ;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_bit_cnt <= 'd0;
else if(r_cstate == S_RECV) r_bit_cnt <= r_clk_cnt == 2'b11 ? r_bit_cnt + 1 : r_bit_cnt;
else r_bit_cnt <= 'd0;
end
wire w_rxdone ;
wire w_cycdone ;
assign w_rxdone = r_clk_cnt == 2'b11 & r_bit_cnt == 4'b1111;
assign w_cycdone= r_ch_cnt == 2'b11 & w_rxdone ;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_ch_cnt <= 'd0;
else if(r_cstate == S_RECV) if(w_rxdone) r_ch_cnt <= r_ch_cnt + 1;
else r_ch_cnt <= r_ch_cnt;
else r_ch_cnt <= 'd0;
end
reg [1:0] r_ch_cnt_d ;
reg r_rxdone ;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) begin
r_ch_cnt_d <= 'd0;
r_rxdone <= 'd0;
end
else begin
r_ch_cnt_d <= r_ch_cnt;
r_rxdone <= w_rxdone;
end
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) begin
o_dvld <= 'b0;
o_dout_0 <= 'd0;
o_dout_1 <= 'd0;
o_dout_2 <= 'd0;
o_dout_3 <= 'd0;
o_dout_4 <= 'd0;
o_dout_5 <= 'd0;
o_dout_6 <= 'd0;
o_dout_7 <= 'd0;
end
else if(r_rxdone) begin
o_dvld <= 'b1;
case(r_ch_cnt_d)
0: begin o_dout_0 <= r_rxdata_a ; o_dout_1 <= o_dout_1 ; o_dout_2 <= o_dout_2 ; o_dout_3 <= o_dout_3 ; o_dout_4 <= r_rxdata_b ; o_dout_5 <= o_dout_5 ; o_dout_6 <= o_dout_6 ; o_dout_7 <= o_dout_7 ; end
1: begin o_dout_0 <= o_dout_0 ; o_dout_1 <= r_rxdata_a ; o_dout_2 <= o_dout_2 ; o_dout_3 <= o_dout_3 ; o_dout_4 <= o_dout_4 ; o_dout_5 <= r_rxdata_b ; o_dout_6 <= o_dout_6 ; o_dout_7 <= o_dout_7 ; end
2: begin o_dout_0 <= o_dout_0 ; o_dout_1 <= o_dout_1 ; o_dout_2 <= r_rxdata_a ; o_dout_3 <= o_dout_3 ; o_dout_4 <= o_dout_4 ; o_dout_5 <= o_dout_5 ; o_dout_6 <= r_rxdata_b ; o_dout_7 <= o_dout_7 ; end
3: begin o_dout_0 <= o_dout_0 ; o_dout_1 <= o_dout_1 ; o_dout_2 <= o_dout_2 ; o_dout_3 <= r_rxdata_a ; o_dout_4 <= o_dout_4 ; o_dout_5 <= o_dout_5 ; o_dout_6 <= o_dout_6 ; o_dout_7 <= r_rxdata_b ; end
default: begin o_dout_0 <= o_dout_0; o_dout_1 <= o_dout_1; o_dout_2 <= o_dout_2; o_dout_3 <= o_dout_3; o_dout_4 <= o_dout_4; o_dout_5 <= o_dout_5; o_dout_6 <= o_dout_6; o_dout_7 <= o_dout_7; end
endcase
end
else begin
o_dvld <= 'b0;
o_dout_0 <= o_dout_0;
o_dout_1 <= o_dout_1;
o_dout_2 <= o_dout_2;
o_dout_3 <= o_dout_3;
o_dout_4 <= o_dout_4;
o_dout_5 <= o_dout_5;
o_dout_6 <= o_dout_6;
o_dout_7 <= o_dout_7;
end
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_cstate <= S_IDLE;
else r_cstate <= r_nstate;
end
always@(*) begin
case(r_cstate)
S_IDLE: r_nstate = i_en ? S_CVST : S_IDLE;
S_CVST: r_nstate = r_cvst_flag ? S_BUSY : S_CVST;
S_BUSY: r_nstate = {r_busy_d0,r_busy_d1} == 2'b01 ? S_CSEL : S_BUSY;
S_CSEL: r_nstate = S_RECV;
S_RECV: r_nstate = w_cycdone ? S_DONE : S_RECV;
S_DONE: r_nstate = S_IDLE;
default:r_nstate = S_IDLE;
endcase
end
endmodule
`timescale 1ns / 1ps
module ad7606_parallel#( parameter CH_UESD = 8 , parameter CLK_PERIOD = 20 )( input i_clk , input i_rst , input i_en , input [15:0] i_din , input i_busy , output reg [15:0] o_dout_0, output reg [15:0] o_dout_1, output reg [15:0] o_dout_2, output reg [15:0] o_dout_3, output reg [15:0] o_dout_4, output reg [15:0] o_dout_5, output reg [15:0] o_dout_6, output reg [15:0] o_dout_7, output reg o_dvld , output reg o_cs , output reg o_rd , output reg [1:0] o_convst, output [2:0] o_os , output reg o_rst , output o_range );
wire [3:0] w_ch_used;
generate
if(CH_UESD > 0 && CH_UESD < 9) assign w_ch_used = CH_UESD;
else assign w_ch_used = 8;
endgenerate
assign o_os = 3'b000 ;
assign o_range = 1'b0 ;//1:+-10v;0:+-5v
localparam RST_TMIN = 50 + 20, CVST_TMIN = 25 + 20, RDP_TMIN = 15 + 20,// 高电平
RDN_TMIN = 21 + 20;// 低电平,一般 3.3V 以上供电 21ns,5V 供电 16ns
wire [7:0] w_rstTmin ;
wire [7:0] w_cvstTmin ;
wire [7:0] w_rdpTmin ;
wire [7:0] w_rdnTmin ;
generate
assign w_rstTmin = RST_TMIN > CLK_PERIOD ? RST_TMIN - CLK_PERIOD : 0;
assign w_cvstTmin= CVST_TMIN > CLK_PERIOD ? CVST_TMIN - CLK_PERIOD : 0;
assign w_rdpTmin = RDP_TMIN > CLK_PERIOD ? RDP_TMIN - CLK_PERIOD : 0;
assign w_rdnTmin = RDN_TMIN > CLK_PERIOD ? RDN_TMIN - CLK_PERIOD : 0;
endgenerate
reg [7:0] r_rstTime ;
reg [7:0] r_cvstTime ;
reg [7:0] r_rdpTime ;
reg [7:0] r_rdnTime ;
localparam S_IDLE = 8'b00000001, S_RST = 8'b00000010, S_CVST = 8'b00000100, S_BUSY = 8'b00001000, S_CSEL = 8'b00010000, S_RDN = 8'b00100000, S_RDP = 8'b01000000, S_DONE = 8'b10000000;
reg [7:0] r_cstate ;
reg [7:0] r_nstate ;
reg r_rst_done ; // rst start
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_rst_done <= 1'b0;
else if(!i_en) r_rst_done <= 1'b0;
else if(r_cstate == S_RST) r_rst_done <= 1'b1;
else r_rst_done <= r_rst_done;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_rstTime <= 0;
else if(r_cstate == S_RST) r_rstTime <= r_rstTime + CLK_PERIOD;
else r_rstTime <= 0;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) o_rst <= 1'b0;
else if(r_cstate == S_RST) o_rst <= 1'b1;
else o_rst <= 1'b0;
end // rst end
// cvst start
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_cvstTime <= 0;
else if(r_cstate == S_CVST) r_cvstTime <= r_cvstTime + CLK_PERIOD;
else r_cvstTime <= 0;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) o_convst <= 2'b11;
else if(r_cstate == S_CVST) o_convst <= 2'b00;
else o_convst <= 2'b11;
end // cvst end
// busy start
reg [1:0] r_busyEdge ;
always@(posedge i_clk) begin
r_busyEdge[0] <= i_busy;
r_busyEdge[1] <= r_busyEdge[0];
end
wire w_nedge_busy;
assign w_nedge_busy = r_busyEdge == 2'b10; // busy end
// cs start
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) o_cs <= 1'b1;
else if(r_cstate == S_DONE) o_cs <= 1'b1;
else if(r_cstate == S_CSEL) o_cs <= 1'b0;
else o_cs <= o_cs;
end // cs end
// read start
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_rdpTime <= 0;
else if(r_cstate == S_RDP) r_rdpTime <= r_rdpTime + CLK_PERIOD;
else r_rdpTime <= 0;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_rdnTime <= 0;
else if(r_cstate == S_RDN) r_rdnTime <= r_rdnTime + CLK_PERIOD;
else r_rdnTime <= 0;
end
task DOUT;
input [15:0] ch0;
input [15:0] ch1;
input [15:0] ch2;
input [15:0] ch3;
input [15:0] ch4;
input [15:0] ch5;
input [15:0] ch6;
input [15:0] ch7;
begin
o_dout_0 <= ch0;
o_dout_1 <= ch1;
o_dout_2 <= ch2;
o_dout_3 <= ch3;
o_dout_4 <= ch4;
o_dout_5 <= ch5;
o_dout_6 <= ch6;
o_dout_7 <= ch7;
end
endtask
reg [3:0] r_ch_cnt ;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) DOUT(0,0,0,0,0,0,0,0);
else if(r_cstate == S_RDP) case(r_ch_cnt)
0: DOUT(i_din,o_dout_1,o_dout_2,o_dout_3,o_dout_4,o_dout_5,o_dout_6,o_dout_7);
1: DOUT(o_dout_0,i_din,o_dout_2,o_dout_3,o_dout_4,o_dout_5,o_dout_6,o_dout_7);
2: DOUT(o_dout_0,o_dout_1,i_din,o_dout_3,o_dout_4,o_dout_5,o_dout_6,o_dout_7);
3: DOUT(o_dout_0,o_dout_1,o_dout_2,i_din,o_dout_4,o_dout_5,o_dout_6,o_dout_7);
4: DOUT(o_dout_0,o_dout_1,o_dout_2,o_dout_3,i_din,o_dout_5,o_dout_6,o_dout_7);
5: DOUT(o_dout_0,o_dout_1,o_dout_2,o_dout_3,o_dout_4,i_din,o_dout_6,o_dout_7);
6: DOUT(o_dout_0,o_dout_1,o_dout_2,o_dout_3,o_dout_4,o_dout_5,i_din,o_dout_7);
7: DOUT(o_dout_0,o_dout_1,o_dout_2,o_dout_3,o_dout_4,o_dout_5,o_dout_6,i_din);
default:DOUT(o_dout_0,o_dout_1,o_dout_2,o_dout_3, o_dout_4,o_dout_5,o_dout_6,o_dout_7);
endcase
else DOUT(o_dout_0,o_dout_1,o_dout_2,o_dout_3, o_dout_4,o_dout_5,o_dout_6,o_dout_7);
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_ch_cnt <= 'd0;
else if(r_cstate == S_IDLE) r_ch_cnt <= 'd0;
else if(r_cstate == S_RDP & r_nstate == S_RDN) r_ch_cnt <= r_ch_cnt + 1;
else r_ch_cnt <= r_ch_cnt;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) o_rd <= 1'b1;
else if(r_cstate == S_RDP) o_rd <= 1'b1;
else if(r_cstate == S_RDN) o_rd <= 1'b0;
else o_rd <= o_rd;
end // read end
// done start
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) o_dvld <= 1'b0;
else if(r_cstate == S_DONE) o_dvld <= 1'b1;
else o_dvld <= 1'b0;
end // done end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) r_cstate <= S_IDLE;
else r_cstate <= r_nstate;
end
always@(*) begin
if(i_rst) r_nstate = S_IDLE;
else case(r_cstate)
S_IDLE: r_nstate = i_en ? (r_rst_done ? S_CVST : S_RST) : S_IDLE;
S_RST: r_nstate = (r_rstTime >= w_rstTmin) ? S_CVST : S_RST;
S_CVST: r_nstate = (r_cvstTime >= w_cvstTmin) ? S_BUSY : S_CVST;
S_BUSY: r_nstate = w_nedge_busy ? S_CSEL : S_BUSY;
S_CSEL: r_nstate = S_RDN;
S_RDN: r_nstate = (r_rdnTime >= w_rdnTmin) ? S_RDP : S_RDN;
S_RDP: r_nstate = (r_rdpTime >= w_rdpTmin) ? (r_ch_cnt >= w_ch_used ? S_DONE : S_RDN) : S_RDP;
S_DONE: r_nstate = S_IDLE;
default:r_nstate = S_IDLE;
endcase
end
ila_ad ila ( .clk (i_clk ), // input wire clk
.probe0 (i_en ), // input wire [0:0] probe0
.probe1 (r_rstTime ), // input wire [7:0] probe1
.probe2 (r_cvstTime ), // input wire [7:0] probe2
.probe3 (r_rdnTime ), // input wire [7:0] probe3
.probe4 (r_rdpTime ), // input wire [7:0] probe4
.probe5 (r_cstate ), // input wire [7:0] probe5
.probe6 (o_convst ), // input wire [1:0] probe6
.probe7 (w_nedge_busy ), // input wire [0:0] probe7
.probe8 (o_cs ), // input wire [0:0] probe8
.probe9 (i_busy ), // input wire [0:0] probe9
.probe10(o_rd ), // input wire [0:0] probe10
.probe11(o_rst ), // input wire [0:0] probe11
.probe12(r_ch_cnt ), // input wire [7:0] probe12
.probe13(i_din ), // input wire [15:0] probe13
.probe14(o_dout_0 ) // input wire [15:0] probe14
);
endmodule
module para_testTop( input i_clk , input i_rst_n , input [15:0] i_din , input i_busy , output o_cs , output o_rd , output [1:0] o_convst, output [2:0] o_os , output o_rst , output o_range );
wire w_clk200m ;
wire w_clk200m_lked ;
mmcm_200m mmcm_200m ( .clk_out1 (w_clk200m ), .resetn (i_rst_n ), .locked (w_clk200m_lked ), .clk_in1 (i_clk ) );
wire [15:0] w_dataCh0;
wire w_ad_ovld;
reg [15:0] r_dataCh0;
always@(posedge w_clk200m or negedge w_clk200m_lked) begin
if(~w_clk200m_lked) r_dataCh0 <= 'd0;
else if(w_ad_ovld) r_dataCh0 <= w_dataCh0;
else r_dataCh0 <= r_dataCh0;
end
ad7606_parallel#( .CH_UESD (1 ), .CLK_PERIOD (5 )) ad_u(
.i_clk (w_clk200m ),
.i_rst (~w_clk200m_lked ),
.i_en (1'b1 ),
.i_din (i_din ),
.i_busy (i_busy ),
.o_dout_0 (w_dataCh0 ),
.o_dout_1 (),
.o_dout_2 (),
.o_dout_3 (),
.o_dout_4 (),
.o_dout_5 (),
.o_dout_6 (),
.o_dout_7 (),
.o_dvld (w_ad_ovld ),
.o_cs (o_cs ),
.o_rd (o_rd ),
.o_convst (o_convst ),
.o_os (o_os ),
.o_rst (o_rst ),
.o_range (o_range )
);
ila_parap ila ( .clk (w_clk200m ), // input wire clk
.probe0 (i_din ), // input wire [15:0] probe0
.probe1 (o_cs ), // input wire [0:0] probe1
.probe2 (o_range ), // input wire [0:0] probe2
.probe3 (o_convst ), // input wire [1:0] probe3
.probe4 (o_os ), // input wire [2:0] probe4
.probe5 (o_rd ), // input wire [0:0] probe5
.probe6 (w_ad_ovld ), // input wire [0:0] probe6
.probe7 (r_dataCh0 ), // input wire [15:0] probe7
.probe8 (o_rst ), // input wire [0:0] probe8
.probe9 (i_busy ) // input wire [0:0] probe9
);
endmodule
module top( input i_clk , input i_rst_n , input i_busy , input i_din_a , input i_din_b , output [1:0] o_convst , output [2:0] o_os , output o_range , output o_rst , output o_cs , output o_sclk , output [13:0] o_da_ch0 , output [13:0] o_da_ch1 , output o_da_clk0 , output o_da_clk1 , output o_da_wr0 , output o_da_wr1 );
wire [15:0] w_dout0 ;
wire [15:0] w_dout1 ;
wire [15:0] w_dout2 ;
wire [15:0] w_dout3 ;
wire w_dvld ;
reg [15:0] r_clk_cnt ;
reg [15:0] r_samp_data0;
reg [15:0] r_samp_data1;
reg r_samp_vld ;
always@(posedge i_clk or negedge i_rst_n) begin
if(~i_rst_n) r_clk_cnt <= 'd0;
else if(r_clk_cnt < 100) r_clk_cnt <= r_clk_cnt + 1;
else r_clk_cnt <= 'd0;
end
always@(posedge i_clk or negedge i_rst_n) begin
if(~i_rst_n) begin
r_samp_vld <= 'b0;
r_samp_data0<= 'd0;
r_samp_data1<= 'd0;
end
else if(r_clk_cnt == 100) begin
r_samp_vld <= 'b1 ;
r_samp_data0<= w_dout0 ;
r_samp_data1<= w_dout1 ;
end
else begin
r_samp_vld <= 'b0 ;
r_samp_data0<= r_samp_data0 ;
r_samp_data1<= r_samp_data1 ;
end
end
wire [15:0] w_samp_data0;
wire [15:0] w_samp_data1;
assign w_samp_data0= $signed(r_samp_data0) + $signed(16'h7fff) ;
assign w_samp_data1= $signed(r_samp_data1) + $signed(16'h7fff) ;
assign o_da_ch0 = w_samp_data0[15-:14] ;
assign o_da_ch1 = w_samp_data1[15-:14] ;
assign o_da_clk0 = i_clk ;
assign o_da_clk1 = i_clk ;
assign o_da_wr0 = r_samp_vld ;
assign o_da_wr1 = r_samp_vld ;
ad7606_serial ad7606_serial_u (
.i_clk (i_clk ),
.i_rst (~i_rst_n ),
.i_en (1 ),
.i_din_a (i_din_a ),
.i_din_b (i_din_b ),
.i_busy (i_busy ),
.o_dout_0(w_dout0 ),
.o_dout_1(w_dout1 ),
.o_dout_2(w_dout2 ),
.o_dout_3(w_dout3 ),
.o_dout_4(),
.o_dout_5(),
.o_dout_6(),
.o_dout_7(),
.o_dvld (w_dvld ),
.o_cs (o_cs ),
.o_sclk (o_sclk ),
.o_os (o_os ),
.o_convst(o_convst ),
.o_rst (o_rst ),
.o_range (o_range )
);
ila_top ila_top ( .clk (i_clk ), // input wire clk
.probe0 (o_cs ), // input wire [0:0] probe0
.probe1 (o_sclk ), // input wire [0:0] probe1
.probe2 (i_busy ), // input wire [0:0] probe2
.probe3 (i_din_a ), // input wire [0:0] probe3
.probe4 (r_samp_data0), // input wire [14:0] probe4
.probe5 (r_samp_vld ), // input wire [0:0] probe5
.probe6 (o_convst ), // input wire [1:0] probe6
.probe7 (o_da_ch0 )
);
endmodule