`timescale 1 ns / 1 ps module transmit_if# ( parameter SPI_CLK_DIV = 2 , parameter SPI_DATA_WIDTH = 32 , parameter CH_OF_CHIPSET = 16 , parameter CMD_CONVERT = 2'b00 , parameter CMD_EXTEND = 2'b01 , parameter CMD_WRITE = 2'b10 , parameter CMD_READ = 2'b11 , parameter REG_ADDR_MONITOR = 8'd40 ,//Read Only parameter REG_ADDR_POS_CUR = 8'd64 , parameter REG_ADDR_NEG_CUR = 8'd96 ) ( input clk , input rst_n , input trans_round , input trans_pulse , //------------------------------------------ spi direct communication input spi_cmd_valid , input [32-1:0] spi_cmd_data , output reg spi_cmd_ready , output reg spi_res_en , output reg [32-1:0] spi_res , //------------------------------------------ conver/stim stream tx input s_axis_trans_tlast , input [32-1:0] s_axis_trans_tdata , output reg s_axis_trans_tready , input s_axis_trans_tvalid , //------------------------------------------ record stream rx output reg [32-1:0] cnv_res_tdata , output cnv_res_tlast , input cnv_res_tready , output reg cnv_res_tvalid , //------------------------------------------ monitor output reg monitor_data_en , output reg [16-1:0] monitor_data , output reg [16-1:0] stim_state , output reg [32-1:0] stim_stage_code , //------------------------------------------ device spi output cs , output sclk , output mosi , input miso ); //***************************************************************************** // localparam definition //***************************************************************************** localparam SYNC_ST = 4'h0 ; localparam TRANS_ST = 4'h1 ; //***************************************************************************** // Internal register and wire declarations //***************************************************************************** reg [32-1:0] spi_data ; reg spi_data_en ; reg spi_flag ; wire is_empty_cmd ; wire is_stim_cmd ; wire is_cover_cmd ; wire is_cnv_cmd ; wire is_mon_cmd ; wire stim_pol ; wire [ 4-1:0] stim_ch ; wire [ 8-1:0] stim_reg_addr ; wire [32-1:0] stim_cmd ; reg [32-1:0] trans_data ; reg trans_data_en ; reg cnv_valid ; reg cnv_valid_t ; reg cnv_valid_tt ; reg cnv_cover_valid ; reg cnv_cover_valid_t ; reg cnv_cover_valid_tt ; reg [ 6-1:0] cnv_channel ; reg [ 6-1:0] cnv_channel_t ; reg [ 6-1:0] cnv_channel_tt ; reg monitor_flag ; reg monitor_flag_t ; reg monitor_flag_tt ; reg [32-1:0] spi_din_r ; wire spi_rdy ; wire spi_start ; wire [32-1:0] spi_din ; wire spi_done ; wire [32-1:0] spi_dout ; //***************************************************************************** // Instantiation //***************************************************************************** spi_full_duplex_master# ( .CLK_DIV ( SPI_CLK_DIV ), .DATA_WIDTH ( SPI_DATA_WIDTH ) ) u_spi_full_duplex_master ( .clk ( clk ), .rst_n ( rst_n ), .rdy ( spi_rdy ), .start ( spi_start ), .din ( spi_din ), .done ( spi_done ), .dout ( spi_dout ), .cs ( cs ), .sclk ( sclk ), .mosi ( mosi ), .miso ( miso ) ); //***************************************************************************** // Procedural blocks //***************************************************************************** //direct spi always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin spi_cmd_ready <= 1'b0; end else if ( spi_cmd_valid && spi_rdy ) begin spi_cmd_ready <= 1'b1; end else begin spi_cmd_ready <= 1'b0; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin spi_data <= 0; spi_data_en <= 1'b0; end else if ( spi_cmd_valid && spi_rdy ) begin spi_data <= spi_cmd_data; spi_data_en <= 1'b1; end else begin spi_data_en <= 1'b0; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin spi_flag <= 1'b0; end else if ( spi_cmd_valid && spi_rdy ) begin spi_flag <= 1'b1; end else if ( spi_done ) begin spi_flag <= 1'b0; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin spi_res_en <= 1'b0; spi_res <= 0; end else if ( spi_flag && spi_done ) begin spi_res_en <= 1'b1; spi_res <= spi_dout; end else begin spi_res_en <= 1'b0; end end //transmit always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin s_axis_trans_tready <= 1'b0; end else if ( trans_pulse ) begin s_axis_trans_tready <= 1'b1; end else begin s_axis_trans_tready <= 1'b0; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin trans_data <= 0; trans_data_en <= 1'b0; end else if ( s_axis_trans_tvalid && s_axis_trans_tready && (~is_empty_cmd) ) begin trans_data <= (is_stim_cmd)? stim_cmd:s_axis_trans_tdata; trans_data_en <= 1'b1; end else begin trans_data_en <= 1'b0; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin stim_state <= 0; end else if ( trans_data[31:30]==2'b10 && trans_data[23:16]==8'd42 ) begin stim_state <= trans_data[15:0]; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) stim_stage_code <= 0; else if ( s_axis_trans_tvalid && s_axis_trans_tready && is_stim_cmd ) stim_stage_code <= 32'h3E7 + s_axis_trans_tdata[23:20]; end //record flag always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin cnv_valid <= 1'b0; end else if ( s_axis_trans_tvalid && s_axis_trans_tready ) begin cnv_valid <= (is_cnv_cmd)? 1'b1:(is_empty_cmd? cnv_valid:1'b0); end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin cnv_cover_valid <= 1'b0; end else if ( s_axis_trans_tvalid && s_axis_trans_tready ) begin cnv_cover_valid <= (is_cover_cmd)? 1'b1:1'b0; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin cnv_channel <= 1'b0; end else if ( s_axis_trans_tvalid && s_axis_trans_tready ) begin cnv_channel <= (is_cnv_cmd || is_cover_cmd)? {2'b00, s_axis_trans_tdata[19:16]}:cnv_channel; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin cnv_valid_t <= 1'b0; cnv_valid_tt <= 1'b0; cnv_channel_t <= 0; cnv_channel_tt <= 0; cnv_cover_valid_t <= 1'b0; cnv_cover_valid_tt <= 1'b0; end else if ( spi_done ) begin cnv_valid_t <= cnv_valid; cnv_valid_tt <= cnv_valid_t; cnv_channel_t <= cnv_channel; cnv_channel_tt <= cnv_channel_t; cnv_cover_valid_t <= cnv_cover_valid; cnv_cover_valid_tt <= cnv_cover_valid_t; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin cnv_res_tdata <= 0; cnv_res_tvalid <= 1'b0; end else if ( spi_done && (cnv_valid_tt || cnv_cover_valid_tt) ) begin cnv_res_tdata <= cnv_valid_tt? {spi_dout[31:16], cnv_channel_tt, spi_dout[9:1], 1'b0}: {16'd0, cnv_channel_tt, 9'd0, 1'b1}; cnv_res_tvalid <= 1'b1; end else begin cnv_res_tvalid <= 1'b0; end end //monitor always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin monitor_flag <= 1'b0; end else if ( s_axis_trans_tvalid && s_axis_trans_tready ) begin monitor_flag <= (is_mon_cmd)? 1'b1:(is_empty_cmd? monitor_flag:1'b0); end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin monitor_flag_t <= 1'b0; monitor_flag_tt <= 1'b0; end else if ( spi_done ) begin monitor_flag_t <= monitor_flag; monitor_flag_tt <= monitor_flag_t; end end always @ ( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin monitor_data <= 0; monitor_data_en <= 1'b0; end else if ( spi_done && monitor_flag_tt ) begin monitor_data <= spi_dout[15:0]; monitor_data_en <= 1'b1; end else begin monitor_data_en <= 1'b0; end end //spi control always@( * ) begin if ( !rst_n ) spi_din_r <= 0; else if (spi_data_en) spi_din_r <= spi_data; else if (trans_data_en) spi_din_r <= trans_data; else spi_din_r <= spi_din_r; end //***************************************************************************** // Wire assignment //***************************************************************************** assign is_empty_cmd = (s_axis_trans_tdata[31:30]==CMD_EXTEND && s_axis_trans_tdata[24]==1'b0)? 1'b1:1'b0; assign is_stim_cmd = (s_axis_trans_tdata[31:30]==CMD_EXTEND && s_axis_trans_tdata[24]==1'b1)? 1'b1:1'b0; assign is_cover_cmd = (s_axis_trans_tdata[31:30]==CMD_EXTEND && s_axis_trans_tdata[25:24]==2'b11)? 1'b1:1'b0; assign is_cnv_cmd = (s_axis_trans_tdata[31:30]==CMD_CONVERT)? 1'b1:1'b0; assign is_mon_cmd = (s_axis_trans_tdata[31:30]==CMD_READ && s_axis_trans_tdata[23:16]==REG_ADDR_MONITOR)? 1'b1:1'b0; assign stim_pol = s_axis_trans_tdata[26]; assign stim_ch = s_axis_trans_tdata[19:16]; assign stim_reg_addr= stim_pol? (REG_ADDR_NEG_CUR+stim_ch):(REG_ADDR_POS_CUR+stim_ch); assign stim_cmd = {CMD_WRITE, s_axis_trans_tdata[29:28],4'h0,stim_reg_addr,s_axis_trans_tdata[15:0]}; assign spi_start = trans_data_en || spi_data_en; assign spi_din = spi_din_r; assign cnv_res_tlast = 1'b0; endmodule