`timescale 1 ns / 1 ps module ads1299_arrange# ( parameter CLK_PERIOD = 10 , parameter SPI_DATA_WIDTH = 8 , parameter SPI_TRANS_PERIOD = 2000 , //Unit: ns parameter SPI_RDATAC_PERIOD = 2000 //Unit: ns ) ( input clk , input rst_n , input [ 8-1:0] send_cs_n , input send_enable , input [ 8-1:0] send_length , input [32-1:0] send_data_array , output reg recv_data_en , output [32-1:0] recv_data_array , output reg [ 8-1:0] t_cs_n , output reg [ 8-1:0] t_tdata , output reg t_tlast , input t_tready , output reg t_tvalid , input [ 8-1:0] r_tdata , input r_tlast , input r_tvalid , input rdatac_enable , output reg cnv_start , input cnv_drdy , output upload_round ); //***************************************************************************** // localparam definition //***************************************************************************** localparam T_PERIOD = SPI_TRANS_PERIOD/CLK_PERIOD ; localparam IDLE = 4'd0 ; localparam TRANS_ST = 4'd1 ; localparam WAIT_ST = 4'd2 ; localparam RDATAC_ST = 4'd3 ; localparam REVC_1_ST = 4'd4 ; localparam REVC_2_ST = 4'd5 ; localparam RDATAC_BYTES = 27 ; //***************************************************************************** // Internal register and wire declarations //***************************************************************************** reg [ 4-1:0] cstate ; reg [ 4-1:0] nstate ; reg [16-1:0] time_cnt ; reg [ 8-1:0] t_cnt ; reg [ 8-1:0] r_cnt ; reg [ 4-1:0] cnv_drdy_r ; wire drdy ; wire [ 8-1:0] send_data[3:0] ; reg [ 8-1:0] recv_data[3:0] ; genvar i; //***************************************************************************** // Instantiation //***************************************************************************** //***************************************************************************** // Procedural blocks //***************************************************************************** always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) cnv_drdy_r <= 0; else cnv_drdy_r <= {cnv_drdy_r[2:0], cnv_drdy}; end always@( posedge clk or negedge rst_n ) begin if( !rst_n ) cstate <= IDLE; else cstate <= nstate; end always@( * ) begin case ( cstate ) IDLE: if ( send_enable ) nstate <= TRANS_ST; else if ( rdatac_enable ) nstate <= RDATAC_ST; else nstate <= IDLE; TRANS_ST: nstate <= WAIT_ST; WAIT_ST: if ( time_cnt == 0 ) begin if ( t_cnt == send_length ) nstate <= IDLE; else nstate <= TRANS_ST; end else begin nstate <= WAIT_ST; end RDATAC_ST: if ( ~rdatac_enable ) nstate <= IDLE; else if ( drdy ) nstate <= REVC_1_ST; else nstate <= RDATAC_ST; REVC_1_ST: if ( t_tvalid && t_tready && t_cnt == RDATAC_BYTES-1 ) nstate <= REVC_2_ST; else nstate <= REVC_1_ST; REVC_2_ST: if ( t_tvalid && t_tready && t_cnt == RDATAC_BYTES-1 ) nstate <= RDATAC_ST; else nstate <= REVC_2_ST; default: nstate <= IDLE; endcase end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin t_cnt <= 0; end else if ( (cstate == IDLE && nstate == TRANS_ST) || (cstate == RDATAC_ST && nstate == REVC_1_ST) || (cstate == REVC_1_ST && nstate == REVC_2_ST) ) begin t_cnt <= 0; end else if ( t_tvalid && t_tready ) begin t_cnt <= t_cnt + 1'b1; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin time_cnt <= 0; end else if ( nstate == TRANS_ST ) begin time_cnt <= T_PERIOD - 1'b1; end else if ( time_cnt != 0 ) begin time_cnt <= time_cnt - 1'b1; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin cnv_start <= 1'b0; end else if ( nstate == IDLE ) begin cnv_start <= 1'b0; end else if ( nstate == RDATAC_ST ) begin cnv_start <= 1'b1; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin t_cs_n <= 0; end else if ( cstate == REVC_1_ST ) begin t_cs_n <= 0; end else if ( cstate == REVC_2_ST ) begin t_cs_n <= 1; end else begin t_cs_n <= send_cs_n; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin t_tdata <= 0; t_tvalid <= 1'b0; end else if ( cstate == TRANS_ST ) begin t_tdata <= send_data[t_cnt]; t_tvalid <= 1'b1; end else if ( cstate == REVC_1_ST && nstate == REVC_1_ST ) begin t_tdata <= 0; t_tvalid <= 1'b1; end else if ( cstate == REVC_2_ST && nstate == REVC_2_ST ) begin t_tdata <= 0; t_tvalid <= 1'b1; end else begin t_tvalid <= 1'b0; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin t_tlast <= 1'b0; end else if ( cstate == TRANS_ST && t_cnt == send_length-1 ) begin t_tlast <= 1'b1; end else if ( (cstate == REVC_1_ST || cstate == REVC_2_ST) && t_cnt == RDATAC_BYTES-1 ) begin t_tlast <= 1'b1; end else begin t_tlast <= 1'b0; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin r_cnt <= 0; end else if ( cstate == IDLE ) begin r_cnt <= 0; end else if ( r_tvalid ) begin r_cnt <= r_cnt + 1'b1; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin recv_data[0] <= 0; recv_data[1] <= 0; recv_data[2] <= 0; recv_data[3] <= 0; recv_data_en <= 1'b0; end else if ( r_tvalid ) begin recv_data[r_cnt] <= r_tdata; recv_data_en <= r_tlast; end end //***************************************************************************** // Wire assignment //***************************************************************************** assign drdy = (cnv_drdy_r[3:2]==2'b10)? 1'b1:1'b0; assign upload_round = drdy; //send_data_array generate for(i=0;i<4;i=i+1) begin : mapping assign send_data[i] = send_data_array[8*i+7 : 8*i]; assign recv_data_array[8*i+7 : 8*i] = recv_data[i]; end endgenerate endmodule