227 lines
5.3 KiB
Verilog
227 lines
5.3 KiB
Verilog
`timescale 1 ns / 1 ps
|
|
|
|
module ads1299_spi#
|
|
(
|
|
parameter CLK_PERIOD = 10 ,
|
|
parameter CLK_DIV = 2 , // max: 255
|
|
parameter DATA_WIDTH = 8 , // max: 255
|
|
parameter OUTPUT_EDGE = 1 ,
|
|
parameter SAMPLE_EDGE = 0 ,
|
|
parameter NO_OF_SLAVES = 1
|
|
)
|
|
(
|
|
input clk ,
|
|
input rst_n ,
|
|
|
|
input [ 8-1:0] t_cs_n ,
|
|
input [ DATA_WIDTH-1:0] t_tdata ,
|
|
input t_tlast ,
|
|
output reg t_tready ,
|
|
input t_tvalid ,
|
|
|
|
output reg [ DATA_WIDTH-1:0] r_tdata ,
|
|
output reg r_tlast ,
|
|
output reg r_tvalid ,
|
|
|
|
output [NO_OF_SLAVES-1:0] cs ,
|
|
output sclk ,
|
|
output mosi ,
|
|
input miso
|
|
);
|
|
|
|
//*****************************************************************************
|
|
// localparam definition
|
|
//*****************************************************************************
|
|
localparam CNT_POS = 0 ;
|
|
localparam CNT_NEG = CLK_DIV/2 ;
|
|
|
|
localparam IDLE = 4'd0 ;
|
|
localparam TRANS_ST = 4'd1 ;
|
|
localparam END_ST = 4'd2 ;
|
|
|
|
//*****************************************************************************
|
|
// Internal register and wire declarations
|
|
//*****************************************************************************
|
|
reg [ 4-1:0] cstate ;
|
|
reg [ 4-1:0] nstate ;
|
|
|
|
reg [DATA_WIDTH-1:0] tx_data ;
|
|
reg [DATA_WIDTH-1:0] rx_data ;
|
|
reg clk_en ;
|
|
reg [ 9-1:0] cnt ;
|
|
reg sck_pos ;
|
|
reg sck_neg ;
|
|
reg [ 8-1:0] trans_cnt ;
|
|
|
|
reg [ 8-1:0] slv_n ;
|
|
reg [NO_OF_SLAVES-1:0] cs_r ;
|
|
reg sclk_r ;
|
|
|
|
reg [NO_OF_SLAVES-1:0] cs_hold ;
|
|
|
|
//*****************************************************************************
|
|
always@( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n ) cstate <= IDLE;
|
|
else cstate <= nstate;
|
|
end
|
|
|
|
always@( * ) begin
|
|
case ( cstate )
|
|
IDLE:
|
|
if ( t_tvalid )
|
|
nstate <= TRANS_ST;
|
|
else
|
|
nstate <= IDLE;
|
|
TRANS_ST:
|
|
if( (trans_cnt == 0) && sck_neg )
|
|
nstate <= END_ST;
|
|
else
|
|
nstate <= TRANS_ST;
|
|
END_ST:
|
|
nstate <= IDLE;
|
|
default:
|
|
nstate <= IDLE;
|
|
endcase
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if ( !rst_n )
|
|
t_tready <= 1'b0;
|
|
else if ( nstate == IDLE )
|
|
t_tready <= 1'b1;
|
|
else if ( cstate == IDLE && nstate == IDLE )
|
|
t_tready <= 1'b1;
|
|
else
|
|
t_tready <= 1'b0;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if ( !rst_n ) begin
|
|
slv_n <= 0;
|
|
end else if ( cstate == IDLE || nstate == IDLE ) begin
|
|
slv_n <= t_cs_n;
|
|
end
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
cs_hold <= 0;
|
|
else if ( t_tvalid && t_tready && t_tlast )
|
|
cs_hold[slv_n] <= 1'b0;
|
|
else if ( t_tvalid && t_tready )
|
|
cs_hold[slv_n] <= 1'b1;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
cs_r <= {NO_OF_SLAVES{1'b1}};
|
|
else if ( cstate == IDLE || nstate == IDLE )
|
|
cs_r[slv_n] <= ~cs_hold[slv_n];
|
|
else
|
|
cs_r[slv_n] <= 1'b0;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if ( !rst_n ) begin
|
|
tx_data <= 0;
|
|
end else if ( t_tready && t_tvalid ) begin
|
|
tx_data <= t_tdata;
|
|
end
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
clk_en <= 0;
|
|
else if ( ((cstate == IDLE) && (nstate == TRANS_ST)) || ((cstate == TRANS_ST) && (nstate != END_ST)) )
|
|
clk_en <= 1'b1;
|
|
else if ( nstate == END_ST )
|
|
clk_en <= 1'b0;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
cnt <= 0;
|
|
else if ( !clk_en )
|
|
cnt <= 0;
|
|
else if ( cnt == CLK_DIV-1 )
|
|
cnt <= 0;
|
|
else
|
|
cnt <= cnt + 1;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
sck_pos <= 0;
|
|
else if ( clk_en && (cnt == CNT_POS) )
|
|
sck_pos <= 1;
|
|
else
|
|
sck_pos <= 0;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
sck_neg <= 0;
|
|
else if ( clk_en && (cnt == CNT_NEG) )
|
|
sck_neg <= 1;
|
|
else
|
|
sck_neg <= 0;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
sclk_r <= 0;
|
|
else if ( sck_pos )
|
|
sclk_r <= 1'b1;
|
|
else if ( sck_neg )
|
|
sclk_r <= 1'b0;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
trans_cnt <= DATA_WIDTH;
|
|
else if ( cstate == IDLE )
|
|
trans_cnt <= DATA_WIDTH;
|
|
else if ( sck_pos && (trans_cnt != 0) )
|
|
// else if ( sck_neg && (trans_cnt != 0) )
|
|
trans_cnt <= trans_cnt - 1'b1;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n )
|
|
rx_data <= 0;
|
|
// else if ( sck_pos )
|
|
else if ( sck_neg )
|
|
rx_data[trans_cnt] <= miso;
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n ) begin
|
|
r_tvalid <= 1'b0;
|
|
r_tdata <= 0;
|
|
end else if ( (cstate == END_ST)&&(nstate == IDLE) ) begin
|
|
r_tvalid <= 1'b1;
|
|
r_tdata <= rx_data;
|
|
end else begin
|
|
r_tvalid <= 1'b0;
|
|
end
|
|
end
|
|
|
|
always @ ( posedge clk or negedge rst_n ) begin
|
|
if( !rst_n ) begin
|
|
r_tlast <= 1'b0;
|
|
end else if ( (cstate == END_ST)&&(nstate == IDLE) ) begin
|
|
r_tlast <= ~cs_hold[slv_n];
|
|
end else begin
|
|
r_tlast <= 1'b0;
|
|
end
|
|
end
|
|
|
|
//*****************************************************************************
|
|
// Wire assignment
|
|
//*****************************************************************************
|
|
assign cs = cs_r;
|
|
assign sclk = sclk_r;
|
|
assign mosi = (trans_cnt==DATA_WIDTH)? 1'b0:tx_data[trans_cnt];
|
|
|
|
endmodule
|