Files
BSI-901-fpga-software/c64_pro.srcs/sources_1/rtl/rhs2116/transmit_if.v
T
2024-10-28 13:14:49 +08:00

339 lines
9.4 KiB
Verilog

`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