上传PL工程

This commit is contained in:
chenmin
2024-10-28 13:14:49 +08:00
parent d9ea3b1c85
commit 25cdd3c44c
3437 changed files with 10334573 additions and 0 deletions
@@ -0,0 +1,241 @@
`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
+193
View File
@@ -0,0 +1,193 @@
`timescale 1 ns / 1 ps
module ads1299_if#
(
parameter SPI_CLK_DIV = 3 ,
parameter SPI_DATA_WIDTH = 8 ,
parameter SPI_SLAVE_QTY = 2 ,
parameter SPI_CNV_BYTES = 3
)
(
input clk ,
input rst_n ,
input upload_enable ,
input upload_round ,
//------------------------------------------ spi direct communication
input [ 8-1:0] t_cs_n ,
input [ 8-1:0] t_tdata ,
input t_tlast ,
output t_tready ,
input t_tvalid ,
output [ 8-1:0] r_tdata ,
output r_tlast ,
output r_tvalid ,
//------------------------------------------ record stream rx
output reg [32-1:0] cnv_res_tdata ,
output reg cnv_res_tlast ,
input cnv_res_tready ,
output reg cnv_res_tvalid ,
//------------------------------------------ device spi
output [SPI_SLAVE_QTY-1:0] cs ,
output sclk ,
output mosi ,
input miso
);
//*****************************************************************************
// localparam definition
//*****************************************************************************
localparam IDLE = 4'h0 ;
localparam UPLOAD_ST = 4'h1 ;
//*****************************************************************************
// Internal register and wire declarations
//*****************************************************************************
wire [ 8-1:0] r_tdata_w ;
wire r_tlast_w ;
wire r_tvalid_w ;
wire [ 8-1:0] res_tdata ;
wire res_tlast ;
wire res_tvalid ;
reg [ 8-1:0] slv_cnt ;
reg [ 8-1:0] r_cnt ;
reg [ 4-1:0] byte_cnt ;
reg [32-1:0] word ;
reg res_tvalid_b ;
reg res_tlast_b ;
reg [ 8-1:0] ch ;
//*****************************************************************************
// Instantiation
//*****************************************************************************
ads1299_spi#
(
.CLK_PERIOD ( 10 ),
.CLK_DIV ( SPI_CLK_DIV ),
.DATA_WIDTH ( SPI_DATA_WIDTH ),
.NO_OF_SLAVES ( SPI_SLAVE_QTY )
)
u_ads1299_spi
(
.clk ( clk ),
.rst_n ( rst_n ),
.t_cs_n ( t_cs_n ),
.t_tdata ( t_tdata ),
.t_tlast ( t_tlast ),
.t_tready ( t_tready ),
.t_tvalid ( t_tvalid ),
.r_tdata ( r_tdata_w ),
.r_tlast ( r_tlast_w ),
.r_tvalid ( r_tvalid_w ),
.cs ( cs ),
.sclk ( sclk ),
.mosi ( mosi ),
.miso ( miso )
);
//*****************************************************************************
// Procedural blocks
//*****************************************************************************
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n ) begin
res_tvalid_b <= 1'b0;
res_tlast_b <= 1'b0;
end else begin
res_tvalid_b <= res_tvalid;
res_tlast_b <= res_tlast;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
r_cnt <= 0;
else if ( upload_round )
r_cnt <= 0;
else if ( res_tvalid && res_tlast )
r_cnt <= 0;
else if ( res_tvalid )
r_cnt <= r_cnt + 1'b1;
end
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
slv_cnt <= 0;
else if ( upload_round )
slv_cnt <= 0;
else if ( res_tvalid && res_tlast )
slv_cnt <= slv_cnt + 1'b1;
end
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
byte_cnt <= 0;
else if ( upload_round || r_cnt<SPI_CNV_BYTES )
byte_cnt <= 0;
else if ( res_tvalid ) begin
if ( byte_cnt == SPI_CNV_BYTES )
byte_cnt <= 1;
else
byte_cnt <= byte_cnt + 1'b1;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
word <= 0;
else if ( res_tvalid )
word <= {8'd0, word[15:0], res_tdata};
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 ( res_tvalid_b && byte_cnt == SPI_CNV_BYTES ) begin
cnv_res_tdata <= {ch, word[23:0]};
cnv_res_tvalid <= 1'b1;
end else if ( cnv_res_tready ) begin
cnv_res_tvalid <= 1'b0;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n ) begin
cnv_res_tlast <= 1'b0;
end else if ( res_tvalid_b && res_tlast_b && slv_cnt == SPI_SLAVE_QTY ) begin
cnv_res_tlast <= res_tlast_b;
end else if ( cnv_res_tready ) begin
cnv_res_tlast <= 1'b0;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
ch <= 0;
else if ( upload_round )
ch <= 0;
else if ( res_tvalid_b && byte_cnt == SPI_CNV_BYTES )
ch <= ch + 1'b1;
end
//*****************************************************************************
// Wire assignment
//*****************************************************************************
assign r_tdata = (~upload_enable)? r_tdata_w :0;
assign r_tlast = (~upload_enable)? r_tlast_w :0;
assign r_tvalid = (~upload_enable)? r_tvalid_w:0;
assign res_tdata = (upload_enable)? r_tdata_w :0;
assign res_tlast = (upload_enable)? r_tlast_w :0;
assign res_tvalid = (upload_enable)? r_tvalid_w:0;
endmodule
@@ -0,0 +1,154 @@
`timescale 1ns/1ps
module ads1299_mod#
(
parameter DATA_WIDTH = 8 ,
parameter WIRE_DELAY = 11
)
(
input cs ,
input sclk ,
input mosi ,
output miso ,
output reg drdy ,
input start
);
//*****************************************************************************
// localparam definition
//*****************************************************************************
localparam T_CLK = 31250 ; //ns
localparam RDATAC = 8'h08 ;
localparam SDATAC = 8'h11 ;
//*****************************************************************************
// Internal register and wire declarations
//*****************************************************************************
reg clk ;
reg rst_n ;
reg [ 8 - 1:0] serial_in ;
reg [ 8 - 1:0] rx_cnt ;
reg [ 8 - 1:0] rx_data ;
reg [ 8 - 1:0] tx_cnt ;
reg [ 8 - 1:0] reg_data ;
reg [ 8 - 1:0] cnv_data ;
reg [ 8 - 1:0] start_t_cnt ;
reg cnv_en ;
reg [ 8 - 1:0] r_cnt ;
//*****************************************************************************
always #( T_CLK/2.0 ) clk = !clk;
initial begin
Initial();
#100 rst_n = 1;
while(1) begin
@ ( posedge cnv_en );
while ( cnv_en ) begin
@ ( posedge clk );
drdy <= cnv_en? 1'b0:1'b1;
@ ( negedge sclk );
drdy <= 1'b1;
end
end
end
initial begin
clk <= 1'b0 ;
rst_n <= 1'b0 ;
drdy <= 1'b1;
end
//RX
always @ ( negedge sclk or negedge rst_n or posedge cs ) begin
if( !rst_n || cs )
rx_cnt <= 0;
else if ( rx_cnt != DATA_WIDTH )
rx_cnt <= rx_cnt + 1'b1;
else
rx_cnt <= 1;
end
always @ ( negedge sclk or negedge rst_n or negedge cs ) begin
if( !rst_n || cs )
serial_in <= 0;
else
serial_in <= {serial_in[6:0], mosi};
end
always @ ( rx_cnt ) begin
if( rx_cnt == 8 )
rx_data <= serial_in;
end
//data
always@( posedge clk or negedge rst_n ) begin
if ( !rst_n )
start_t_cnt <= 0;
else if ( start ) begin
if ( start_t_cnt != 3 )
start_t_cnt <= start_t_cnt + 1'b1;
end else
start_t_cnt <= 0;
end
always@( posedge clk or negedge rst_n ) begin
if ( !rst_n )
cnv_en <= 1'b0;
else if ( start_t_cnt == 3 )
cnv_en <= 1'b1;
else
cnv_en <= 1'b0;
end
always@( posedge sclk or negedge rst_n or posedge cs ) begin
if ( !rst_n )
r_cnt <= 0;
else if ( cs )
r_cnt <= 0;
else
r_cnt <= r_cnt + 1'b1;
end
always@( posedge sclk or negedge rst_n ) begin
if ( !rst_n ) begin
cnv_data <= 0;
end else if ( cnv_en && r_cnt[2:0] == 3'd0 && !cs ) begin
cnv_data <= cnv_data + 1'b1;
end
end
always @ ( negedge cs or negedge rst_n or tx_cnt ) begin
if ( !rst_n )
reg_data <= 8'h55;
else if ( tx_cnt == 7 )
reg_data <= reg_data + 1'b1;
end
//TX
always @ ( posedge sclk or negedge rst_n or posedge cs ) begin
if( !rst_n || cs )
tx_cnt <= DATA_WIDTH;
else if ( tx_cnt != 0 )
tx_cnt <= tx_cnt - 1'b1;
else
tx_cnt <= DATA_WIDTH-1;
end
//*****************************************************************************
// Wire assignment
//*****************************************************************************
assign #17 miso = (tx_cnt == DATA_WIDTH)? 1'b0:( cnv_en? cnv_data[tx_cnt]:reg_data[tx_cnt] );
endmodule
@@ -0,0 +1,226 @@
`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
@@ -0,0 +1,262 @@
`timescale 1 ns / 1 ps
module ads1299_spi#
(
parameter CLK_PERIOD = 10 ,
parameter CLK_DIV = 3 , // max: 255
parameter DATA_WIDTH = 8 , // max: 255
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 = CLK_DIV-1 ;
localparam CNT_NEG = CLK_DIV*2-1 ;
localparam T_SCCS = 2000/CLK_PERIOD ;
localparam T_SCH = 600/CLK_PERIOD ;
localparam IDLE = 4'd0;
localparam TRANS_ST = 4'd1;
localparam SCCS_ST = 4'd2;
localparam CSH_ST = 4'd3;
//*****************************************************************************
// 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_release ;
reg [ 8-1:0] t_sccs_cnt ;
reg [ 8-1:0] t_sch_cnt ;
reg read_flag ;
//*****************************************************************************
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 <= (cs_release[slv_n])? SCCS_ST : IDLE;
else
nstate <= TRANS_ST;
SCCS_ST:
if ( t_sccs_cnt == T_SCCS - 1 )
nstate <= CSH_ST;
else
nstate <= SCCS_ST;
CSH_ST:
if ( t_sch_cnt == T_SCH - 1 )
nstate <= IDLE;
else
nstate <= CSH_ST;
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_release <= 1'b0;
else if ( t_tvalid && t_tready && t_tlast )
cs_release[slv_n] <= 1'b1;
else if ( t_tvalid && t_tready )
cs_release[slv_n] <= 1'b0;
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n )
cs_r <= {NO_OF_SLAVES{1'b1}};
else if ( cstate == TRANS_ST )
cs_r[slv_n] <= 1'b0;
else if ( nstate == CSH_ST )
cs_r[slv_n] <= cs_release[slv_n];
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 != SCCS_ST)) )
clk_en <= 1'b1;
else if ( nstate == SCCS_ST || nstate == IDLE )
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*2-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 && nstate == TRANS_ST )
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) )
trans_cnt <= trans_cnt - 1'b1;
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n )
rx_data <= 0;
else if ( sck_neg )
rx_data[trans_cnt] <= miso;
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n )
read_flag <= 1'b0;
else if ( cstate == TRANS_ST && nstate != TRANS_ST )
read_flag <= 1'b1;
else
read_flag <= 1'b0;
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n ) begin
r_tvalid <= 1'b0;
r_tdata <= 0;
r_tlast <= 1'b0;
end else if ( read_flag ) begin
r_tvalid <= 1'b1;
r_tdata <= rx_data;
r_tlast <= cs_release[slv_n];
end else begin
r_tvalid <= 1'b0;
r_tlast <= 1'b0;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n ) begin
t_sccs_cnt <= 0;
end else if ( cstate != SCCS_ST ) begin
t_sccs_cnt <= 0;
end else begin
t_sccs_cnt <= t_sccs_cnt + 1'b1;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n ) begin
t_sch_cnt <= 0;
end else if ( cstate != CSH_ST ) begin
t_sch_cnt <= 0;
end else begin
t_sch_cnt <= t_sch_cnt + 1'b1;
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
@@ -0,0 +1,116 @@
`timescale 1ns/1ps
module ads1299_spi_tb();
//*****************************************************************************
// Parameter definition
//*****************************************************************************
parameter T_CLK = 20; //ns
//*****************************************************************************
// Internal register and wire declarations
//*****************************************************************************
reg clk ;
reg rst_n ;
reg trans ;
wire rdy ;
reg start ;
reg [32 - 1:0] din ;
wire done ;
wire [32 - 1:0] dout ;
wire cs ;
wire sclk ;
wire mosi ;
wire miso ;
reg [32 - 1:0] data ;
reg [ 8 - 1:0] cnt ;
//GSR GSR(.GSRI(1'b1));
//*****************************************************************************
// Wire assignment
//*****************************************************************************
always #( T_CLK/2.0 ) clk = !clk;
initial begin
Initial();
#100 rst_n = 0;
#100 rst_n = 1;
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n )
trans <= 1'b0 ;
else if (cs) begin
#200 trans <= 1'b1;
#20 trans <= 1'b0;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n ) begin
start <= 1'b0;
din <= 0;
data <= 0;
end else if ( trans ) begin
start <= 1'b1;
din <= 32'hAAAA5555;//$random;
data <= 32'hCCCCAAA5;//$random;
end else
start <= 1'b0;
end
always @ ( negedge sclk or negedge rst_n or posedge cs ) begin
if( !rst_n )
cnt <= 8'd31;
else if( cs )
cnt <= 8'd31;
else if ( cnt != 0 )
cnt <= cnt - 1'b1;
end
assign miso = data[cnt];
//*****************************************************************************
// Task
//*****************************************************************************
task Initial;
begin
clk <= 1'b0 ;
rst_n <= 1'b0 ;
end
endtask
//*****************************************************************************
// Instantiation
//*****************************************************************************
ads1299_spi#
(
.CLK_PERIOD ( 50 ),
.CLK_DIV ( 2 ),
.DATA_WIDTH ( 32 )
)
DUT
(
.clk ( clk ),
.rst_n ( rst_n ),
.rdy ( rdy ),
.start ( start ),
.din ( din ),
.done ( done ),
.dout ( dout ),
.cs ( cs ),
.sclk ( sclk ),
.mosi ( mosi ),
.miso ( miso )
);
endmodule
+151
View File
@@ -0,0 +1,151 @@
`timescale 1 ns / 1 ps
module eeg_config#
(
parameter SPIS_QTY = 4 ,
parameter SPI_DATA_WIDTH = 8
)
(
input clk ,
input rst_n ,
input [13-1:0] bram_addr ,
input bram_clk ,
input [32-1:0] bram_din ,
output reg [32-1:0] bram_dout ,
input bram_en ,
input bram_rst ,
input [ 4-1:0] bram_we ,
//------------------------------------------ eeg
output [32-1:0] eeg_er ,
output [32-1:0] eeg_cr ,
input [32-1:0] eeg_sr ,
output [32*SPIS_QTY-1:0] eeg_tr_array ,
input [32*SPIS_QTY-1:0] eeg_rr_array ,
output reg eeg_sr_r_evt
);
//*****************************************************************************
// localparam definition
//*****************************************************************************
localparam BRAM_ADDR_TEST_RO = 13'h0000;
localparam BRAM_ADDR_TEST_RW = 13'h0004;
localparam BRAM_ADDR_EEG_ER = 13'h0040;
localparam BRAM_ADDR_EEG_CR = 13'h0044;
localparam BRAM_ADDR_EEG_SR = 13'h0048;
localparam BRAM_ADDR_EEG_TR = 13'h0100;
localparam BRAM_ADDR_EEG_RR = 13'h0200;
localparam BRAM_ADDR_EEG_TR_MASK = 13'h1F00;
localparam BRAM_ADDR_EEG_RR_MASK = 13'h1F00;
//*****************************************************************************
// Internal register and wire declarations
//*****************************************************************************
reg [32-1:0] test_data ;
wire bram_wr_valid ;
wire bram_rd_valid ;
reg [32-1:0] eeg_er_r ;
reg [32-1:0] eeg_cr_r ;
reg [32-1:0] eeg_tr_r[SPIS_QTY-1:0] ;
wire [32-1:0] eeg_rr_r[SPIS_QTY-1:0] ;
integer n;
genvar i;
//*****************************************************************************
// Procedural blocks
//*****************************************************************************
//write bram/Set config
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n )
test_data <= 0;
else if ( bram_wr_valid && ( bram_addr == BRAM_ADDR_TEST_RW ) )
test_data <= bram_din;
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n ) begin
eeg_er_r <= 0;
end else if ( bram_wr_valid && ( bram_addr == BRAM_ADDR_EEG_ER ) ) begin
eeg_er_r <= bram_din;
end else begin
eeg_er_r <= 0;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n ) begin
eeg_cr_r <= 0;
end else if ( bram_wr_valid && ( bram_addr == BRAM_ADDR_EEG_CR ) ) begin
eeg_cr_r <= bram_din;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n ) begin
n = 0;
while(n<SPIS_QTY) begin
eeg_tr_r[n] <= 0;
n = n + 1;
end
end else if ( bram_wr_valid && ( (bram_addr & BRAM_ADDR_EEG_TR_MASK) == BRAM_ADDR_EEG_TR ) )
eeg_tr_r[bram_addr[7:2]] <= bram_din;
end
//read bram/Get config
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n ) begin
bram_dout <= 0;
end else if ( bram_rd_valid ) begin
if ( bram_addr == BRAM_ADDR_TEST_RO )
bram_dout <= 32'h12345678;
if ( bram_addr == BRAM_ADDR_TEST_RW )
bram_dout <= test_data;
if ( bram_addr == BRAM_ADDR_EEG_SR ) begin
bram_dout <= eeg_sr;
eeg_sr_r_evt <= 1'b1;
end
if ( (bram_addr & BRAM_ADDR_EEG_RR_MASK) == BRAM_ADDR_EEG_RR )
bram_dout <= eeg_rr_r[bram_addr[7:2]];
end
end
always @ ( posedge clk or negedge rst_n ) begin
if( !rst_n )
eeg_sr_r_evt <= 1'b0;
else if ( bram_wr_valid && ( bram_addr == BRAM_ADDR_EEG_SR ) )
eeg_sr_r_evt <= 1'b1;
else
eeg_sr_r_evt <= 1'b0;
end
//*****************************************************************************
// Continuous assignments
//*****************************************************************************
assign bram_wr_valid = bram_en && (bram_we == 4'hF);
assign bram_rd_valid = bram_en && (bram_we == 4'h0);
generate
for(i=0;i<SPIS_QTY;i=i+1) begin : mapping
assign eeg_tr_array[32*i+31 : 32*i] = eeg_tr_r[i];
assign eeg_rr_r[i] = eeg_rr_array[32*i+31 : 32*i];
end
endgenerate
assign eeg_er = eeg_er_r;
assign eeg_cr = eeg_cr_r;
endmodule
+272
View File
@@ -0,0 +1,272 @@
`timescale 1 ns / 1 ps
module eeg_top#
(
parameter CLK_PERIOD = 10 ,
parameter CHIPSET_QTY = 8 ,
parameter CHIPSET_CH_QTY = 8 ,
parameter SPIS_QTY = 4 ,
parameter SPI_SLAVE_QTY = 2 ,
parameter SPI_CLK_DIV = 3 ,
parameter SPI_DATA_WIDTH = 8 ,
parameter SPI_TRANS_PERIOD = 2000 //Unit: ns
)
(
input clk ,
input rst_n ,
input [13-1:0] bram_addr ,
input bram_clk ,
input [32-1:0] bram_din ,
output [32-1:0] bram_dout ,
input bram_en ,
input bram_rst ,
input [ 4-1:0] bram_we ,
output interrupt ,
output [32-1:0] axis_record_tdata ,
output axis_record_tlast ,
input axis_record_tready ,
output axis_record_tvalid ,
output [CHIPSET_QTY-1:0] cs ,
output [ SPIS_QTY-1:0] sclk ,
output [ SPIS_QTY-1:0] mosi ,
input [ SPIS_QTY-1:0] miso ,
input [ SPIS_QTY-1:0] drdy ,
output start ,
output [ 4-1:0] debug_sig
);
//*****************************************************************************
// localparam definition
//*****************************************************************************
//*****************************************************************************
// Internal register and wire declarations
//*****************************************************************************
wire [32-1:0] eeg_er ;
wire [32-1:0] eeg_cr ;
wire [32-1:0] eeg_sr ;
wire [32*SPIS_QTY-1:0] eeg_tr_array ;
wire [32*SPIS_QTY-1:0] eeg_rr_array ;
wire eeg_sr_r_evt ;
wire [SPI_SLAVE_QTY-1:0] cs_w[SPIS_QTY-1:0] ;
wire send_enable[SPIS_QTY-1:0] ;
wire [ 8-1:0] send_cs_n[SPIS_QTY-1:0] ;
wire [ 8-1:0] send_length[SPIS_QTY-1:0] ;
wire [32-1:0] send_data_array[SPIS_QTY-1:0] ;
wire [32-1:0] recv_data_array[SPIS_QTY-1:0] ;
wire recv_data_en_array[SPIS_QTY-1:0];
wire [ 8-1:0] t_cs_n[SPIS_QTY-1:0] ;
wire [ 8-1:0] t_tdata[SPIS_QTY-1:0] ;
wire t_tlast[SPIS_QTY-1:0] ;
wire t_tready[SPIS_QTY-1:0] ;
wire t_tvalid[SPIS_QTY-1:0] ;
wire [ 8-1:0] r_tdata[SPIS_QTY-1:0] ;
wire r_tlast[SPIS_QTY-1:0] ;
wire r_tvalid[SPIS_QTY-1:0] ;
wire cnv_start[SPIS_QTY-1:0] ;
wire cnv_drdy[SPIS_QTY-1:0] ;
wire upload_round[SPIS_QTY-1:0] ;
//------------------------------------------ record stream rx
wire [32-1:0] cnv_res_tdata[SPIS_QTY-1:0] ;
wire cnv_res_tlast[SPIS_QTY-1:0] ;
wire cnv_res_tready[SPIS_QTY-1:0] ;
wire cnv_res_tvalid[SPIS_QTY-1:0] ;
wire [32*SPIS_QTY-1:0] cnv_res_tdata_array ;
wire [ SPIS_QTY-1:0] cnv_res_tlast_array ;
wire [ SPIS_QTY-1:0] cnv_res_tready_array ;
wire [ SPIS_QTY-1:0] cnv_res_tvalid_array ;
wire record_enable ;
genvar i;
//*****************************************************************************
// Instantiation
//*****************************************************************************
eeg_config#
(
.SPIS_QTY ( 4 ),
.SPI_DATA_WIDTH ( 8 )
)
u_eeg_config
(
.clk ( clk ),
.rst_n ( rst_n ),
.bram_addr ( bram_addr ),
.bram_clk ( bram_clk ),
.bram_din ( bram_din ),
.bram_dout ( bram_dout ),
.bram_en ( bram_en ),
.bram_rst ( bram_rst ),
.bram_we ( bram_we ),
//eeg
.eeg_er ( eeg_er ),
.eeg_cr ( eeg_cr ),
.eeg_sr ( eeg_sr ),
.eeg_tr_array ( eeg_tr_array ),
.eeg_rr_array ( eeg_rr_array ),
.eeg_sr_r_evt ( eeg_sr_r_evt )
);
generate
for(i=0;i<SPIS_QTY;i=i+1) begin : transmit_arrange
ads1299_arrange#
(
.CLK_PERIOD ( 10 ),
.SPI_DATA_WIDTH ( 8 ),
.SPI_TRANS_PERIOD ( SPI_TRANS_PERIOD )
)
u_ads1299_arrange
(
.clk ( clk ),
.rst_n ( rst_n ),
.send_cs_n ( send_cs_n[i] ),
.send_enable ( send_enable[i] ),
.send_length ( send_length[i] ),
.send_data_array ( send_data_array[i] ),
.recv_data_en ( recv_data_en_array[i] ),
.recv_data_array ( recv_data_array[i] ),
.t_cs_n ( t_cs_n[i] ),
.t_tdata ( t_tdata[i] ),
.t_tlast ( t_tlast[i] ),
.t_tready ( t_tready[i] ),
.t_tvalid ( t_tvalid[i] ),
.r_tdata ( r_tdata[i] ),
.r_tlast ( r_tlast[i] ),
.r_tvalid ( r_tvalid[i] ),
.rdatac_enable ( record_enable ),
.cnv_start ( cnv_start[i] ),
.cnv_drdy ( cnv_drdy[0] ),
.upload_round ( upload_round[i] )
);
end
endgenerate
generate
for(i=0;i<SPIS_QTY;i=i+1) begin : trans_if
ads1299_if#
(
.SPI_CLK_DIV ( SPI_CLK_DIV ),
.SPI_DATA_WIDTH ( SPI_DATA_WIDTH ),
.SPI_SLAVE_QTY ( SPI_SLAVE_QTY )
)
u_ads1299_if
(
.clk ( clk ),
.rst_n ( rst_n ),
.upload_enable ( record_enable ),
.upload_round ( upload_round[i] ),
//------------------------------------------ spi direct communication
.t_cs_n ( t_cs_n[i] ),
.t_tdata ( t_tdata[i] ),
.t_tlast ( t_tlast[i] ),
.t_tready ( t_tready[i] ),
.t_tvalid ( t_tvalid[i] ),
.r_tdata ( r_tdata[i] ),
.r_tlast ( r_tlast[i] ),
.r_tvalid ( r_tvalid[i] ),
//------------------------------------------ record stream rx
.cnv_res_tdata ( cnv_res_tdata[i] ),
.cnv_res_tlast ( cnv_res_tlast[i] ),
.cnv_res_tready ( cnv_res_tready[i] ),
.cnv_res_tvalid ( cnv_res_tvalid[i] ),
//------------------------------------------ device spi
.cs ( cs_w[i] ),
.sclk ( sclk[i] ),
.mosi ( mosi[i] ),
.miso ( miso[i] )
);
end
endgenerate
eeg_upload#
(
.CLK_PERIOD ( CLK_PERIOD ),
.CHIPSET_QTY ( SPIS_QTY ),
.CH_OF_CHIPSET ( CHIPSET_CH_QTY*SPI_SLAVE_QTY )
)
u_eeg_upload
(
.clk ( clk ),
.rst_n ( rst_n ),
.trans_round ( upload_round[0] ),
.cnv_res_tdata_array ( cnv_res_tdata_array ),
.cnv_res_tlast_array ( cnv_res_tlast_array ),
.cnv_res_tready_array ( cnv_res_tready_array ),
.cnv_res_tvalid_array ( cnv_res_tvalid_array ),
.axi_str_rxd_tdata ( axis_record_tdata ),
.axi_str_rxd_tlast ( axis_record_tlast ),
.axi_str_rxd_tready ( axis_record_tready ),
.axi_str_rxd_tvalid ( axis_record_tvalid )
);
//*****************************************************************************
// Procedural blocks
//*****************************************************************************
//*****************************************************************************
// Wire assignment
//*****************************************************************************
assign record_enable = eeg_cr[31];
assign start = cnv_start[0];
generate
for(i=0;i<SPIS_QTY;i=i+1) begin : mapping
assign send_enable[i] = eeg_er[i];
assign send_cs_n[i] = {6'd0, eeg_cr[4*i+1:4*i+0]};
assign send_length[i] = {6'd0, eeg_cr[4*i+3:4*i+2]};
assign send_data_array[i] = eeg_tr_array[32*i+31:32*i];
assign eeg_rr_array[32*i+31:32*i] = recv_data_array[i];
assign cs[SPI_SLAVE_QTY*(i+1)-1 : SPI_SLAVE_QTY*i] = cs_w[i];
assign cnv_drdy[i] = drdy[i];
assign cnv_res_tdata_array[32*i+31 : 32*i] = cnv_res_tdata[i];
assign cnv_res_tlast_array[i] = cnv_res_tlast[i];
assign cnv_res_tvalid_array[i] = cnv_res_tvalid[i];
assign cnv_res_tready[i] = cnv_res_tready_array[i];
end
endgenerate
assign interrupt = 1'b0;
assign debug_sig[0] = record_enable;
assign debug_sig[1] = 1'b0;
assign debug_sig[2] = 1'b0;
assign debug_sig[3] = 1'b0;
endmodule
+286
View File
@@ -0,0 +1,286 @@
`timescale 1ns/1ps
module eeg_top_tb();
//*****************************************************************************
// Parameter definition
//*****************************************************************************
localparam T_CLK = 10; //ns
localparam SPIS_QTY = 4;
localparam CHIPSET_QTY = 8;
localparam BRAM_ADDR_TEST_RO = 13'h0000;
localparam BRAM_ADDR_TEST_RW = 13'h0004;
localparam BRAM_ADDR_EEG_ER = 13'h0040;
localparam BRAM_ADDR_EEG_CR = 13'h0044;
localparam BRAM_ADDR_EEG_SR = 13'h0048;
localparam BRAM_ADDR_EEG_TR = 13'h0100;
localparam BRAM_ADDR_EEG_RR = 13'h0200;
localparam BRAM_ADDR_EEG_TR_MASK = 13'h1F00;
localparam BRAM_ADDR_EEG_RR_MASK = 13'h1F00;
//*****************************************************************************
// Internal register and wire declarations
//*****************************************************************************
reg clk ;
reg rst_n ;
reg [13-1:0] bram_eeg_addr ;
reg bram_eeg_clk ;
reg [32-1:0] bram_eeg_din ;
wire [32-1:0] bram_eeg_dout ;
reg bram_eeg_en ;
reg bram_eeg_rst ;
reg [ 4-1:0] bram_eeg_we ;
wire interrupt ;
reg [32-1:0] trigger_tdata ;
reg trigger_tvalid ;
reg [32-1:0] read_data ;
wire [32-1:0] axis_record_tdata ;
wire axis_record_tlast ;
reg axis_record_tready ;
wire axis_record_tvalid ;
wire [CHIPSET_QTY-1:0] cs_w ;
wire [ SPIS_QTY-1:0] sclk_w ;
wire [ SPIS_QTY-1:0] mosi_w ;
wire [ SPIS_QTY-1:0] miso_w ;
wire [ SPIS_QTY-1:0] drdy_w ;
wire start_w ;
wire [CHIPSET_QTY-1:0] cs ;
wire [CHIPSET_QTY-1:0] sclk ;
wire [CHIPSET_QTY-1:0] mosi ;
wire [CHIPSET_QTY-1:0] miso ;
wire [CHIPSET_QTY-1:0] drdy ;
wire [CHIPSET_QTY-1:0] start ;
integer n;
genvar i;
//*****************************************************************************
// Instantiation
//*****************************************************************************
eeg_top#
(
.CLK_PERIOD ( T_CLK )
)
DUT
(
.clk ( clk ),
.rst_n ( rst_n ),
.bram_addr ( bram_eeg_addr ),
.bram_clk ( bram_eeg_clk ),
.bram_din ( bram_eeg_din ),
.bram_dout ( bram_eeg_dout ),
.bram_en ( bram_eeg_en ),
.bram_rst ( bram_eeg_rst ),
.bram_we ( bram_eeg_we ),
.interrupt ( interrupt ),
.trigger_tdata ( trigger_tdata ),
.trigger_tvalid ( trigger_tvalid ),
//------------------------------------------ FIFO: eeg output
.axis_record_tdata ( axis_record_tdata ),
.axis_record_tlast ( axis_record_tlast ),
.axis_record_tready ( axis_record_tready ),
.axis_record_tvalid ( axis_record_tvalid ),
//------------------------------------------ device spi
.cs ( cs_w ),
.sclk ( sclk_w ),
.mosi ( mosi_w ),
.miso ( miso_w ),
.drdy ( drdy_w ),
.start ( start_w )
);
generate
for(i=0; i<CHIPSET_QTY; i=i+1) begin : spi
ads1299_mod u_ads1299_mod
(
.cs ( cs[i] ),
.sclk ( sclk[i] ),
.mosi ( mosi[i] ),
.miso ( miso[i] ),
.drdy ( drdy[i] ),
.start ( start[i] )
);
end
endgenerate
//*****************************************************************************
always #( T_CLK/2.0 ) clk = !clk;
initial begin
Initial();
#100 rst_n = 0;
#100 rst_n = 1;
#100
/*
//SDATAC
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h00, 32'h00000011);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h04, 32'h00000011);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h08, 32'h00000011);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h0C, 32'h00000011);
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_CR, {16'd0, 4'b0100, 4'b0100, 4'b0100, 4'b0100});
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_ER, 32'hF);
#4_000
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_CR, {16'd0, 4'b0101, 4'b0101, 4'b0101, 4'b0101});
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_ER, 32'hF);
#4_000
//READ ID
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h00, 32'h00010020);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h04, 32'h00020020);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h08, 32'h00030020);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h0C, 32'h00040020);
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_CR, {16'd0, 4'b1100, 4'b1100, 4'b1100, 4'b1100});
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_ER, 32'hF);
#10_000
read_bram_eeg(BRAM_ADDR_EEG_RR+4'h0, read_data);
#100
// $stop;
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h00, 32'h00010020);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h04, 32'h00020020);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h08, 32'h00030020);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h0C, 32'h00040020);
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_CR, {16'd0, 4'b1101, 4'b1101, 4'b1101, 4'b1101});
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_ER, 32'hF);
#10_000
//
#7_000
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h00, 32'h00000010);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h04, 32'h00000010);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h08, 32'h00000010);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h0C, 32'h00000010);
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_CR, {16'd0, 4'b0100, 4'b0100, 4'b0100, 4'b0100});
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_ER, 32'hF);
#3_000
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h00, 32'h00000010);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h04, 32'h00000010);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h08, 32'h00000010);
write_bram_eeg(BRAM_ADDR_EEG_TR + 8'h0C, 32'h00000010);
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_CR, {16'd0, 4'b0101, 4'b0101, 4'b0101, 4'b0101});
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_ER, 32'hF);
*/
#3_000
@ ( posedge clk );
write_bram_eeg(BRAM_ADDR_EEG_CR, {1'b1, 15'd10, 16'd0});
// #40_000
// @ ( posedge clk );
// $stop;
end
//*****************************************************************************
// Task
//*****************************************************************************
task Initial;
begin
clk <= 1'b0 ;
rst_n <= 1'b0 ;
bram_eeg_addr <= 0 ;
bram_eeg_clk <= 1'b0 ;
bram_eeg_din <= 0 ;
bram_eeg_en <= 1'b0 ;
bram_eeg_rst <= 1'b0 ;
bram_eeg_we <= 0 ;
trigger_tdata <= 0 ;
trigger_tvalid <= 1'b0 ;
axis_record_tready <= 1'b1;
end
endtask
task read_bram_eeg;
input [12:0] addr;
output [31:0] data;
begin
@ ( posedge clk );
bram_eeg_addr <= addr;
bram_eeg_en <= 1;
bram_eeg_we <= 4'h0;
@ ( posedge clk );
bram_eeg_en <= 0;
@ ( posedge clk );
data <= bram_eeg_dout;
end
endtask
task write_bram_eeg;
input [12:0] addr;
input [31:0] data;
begin
@ ( posedge clk );
bram_eeg_addr <= addr;
bram_eeg_din <= data;
bram_eeg_en <= 1;
bram_eeg_we <= 4'hF;
@ ( posedge clk );
bram_eeg_en <= 0;
bram_eeg_we <= 4'h0;
end
endtask
//*****************************************************************************
// Wire assignment
//*****************************************************************************
generate
for(i=0;i<CHIPSET_QTY;i=i+1) begin : mapping_spi
assign cs[i] = cs_w[i];
assign sclk[i] = sclk_w[i/2];
assign mosi[i] = mosi_w[i/2];
assign start[i] = start_w;
end
endgenerate
generate
for(i=0;i<SPIS_QTY;i=i+1) begin : mapping_reg
assign drdy_w[i] = drdy[2*i];
end
endgenerate
assign miso_w[0] = (~cs_w[0])? miso[0]:((~cs_w[1])? miso[1]:1'bZ);
assign miso_w[1] = (~cs_w[2])? miso[2]:((~cs_w[3])? miso[3]:1'bZ);
assign miso_w[2] = (~cs_w[4])? miso[4]:((~cs_w[5])? miso[5]:1'bZ);
assign miso_w[3] = (~cs_w[6])? miso[6]:((~cs_w[7])? miso[7]:1'bZ);
endmodule
+171
View File
@@ -0,0 +1,171 @@
`timescale 1 ns / 1 ps
module eeg_upload#
(
parameter CLK_PERIOD = 10 ,
parameter CHIPSET_QTY = 4 ,
parameter CH_OF_CHIPSET = 16 ,
parameter TIME_OUT_MS = 5
)
(
input clk ,
input rst_n ,
input trans_round ,
input [32*CHIPSET_QTY-1:0] cnv_res_tdata_array ,
input [ CHIPSET_QTY-1:0] cnv_res_tlast_array ,
output [ CHIPSET_QTY-1:0] cnv_res_tready_array ,
input [ CHIPSET_QTY-1:0] cnv_res_tvalid_array ,
output reg [31:0] axi_str_rxd_tdata ,
output reg axi_str_rxd_tlast ,
input axi_str_rxd_tready ,
output reg axi_str_rxd_tvalid
);
//*****************************************************************************
// localparam definition
//*****************************************************************************
localparam IDLE = 4'd0 ;
localparam READY_ST = 4'd1 ;
localparam SCAN_ST = 4'd2 ;
localparam CLKS = 20 ;
localparam TIME_OUT_CLKS = (TIME_OUT_MS*1000000)/CLK_PERIOD;
//*****************************************************************************
// Internal register and wire declarations
//*****************************************************************************
reg [ 4-1:0] cstate ;
reg [ 4-1:0] nstate ;
wire [32-1:0] cnv_res_tdata[0:CHIPSET_QTY-1] ;
wire cnv_res_tlast[0:CHIPSET_QTY-1] ;
reg cnv_res_tready[0:CHIPSET_QTY-1] ;
wire cnv_res_tvalid[0:CHIPSET_QTY-1] ;
reg [32-1:0] cnv_res_tdata_r[0:CHIPSET_QTY-1] ;
reg cnv_res_tvalid_r[0:CHIPSET_QTY-1] ;
reg [ 8-1:0] scan_cnt ;
reg round_end ;
genvar i;
//*****************************************************************************
generate
for(i=0;i<CHIPSET_QTY;i=i+1) begin : rx_data
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n ) begin
cnv_res_tdata_r[i] <= 0;
cnv_res_tvalid_r[i] <= 1'b0;
end else if ( cnv_res_tready[i] && cnv_res_tvalid[i] ) begin
cnv_res_tdata_r[i] <= cnv_res_tdata[i];
cnv_res_tvalid_r[i] <= cnv_res_tvalid[i];
end
end
end
endgenerate
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
round_end <= 1'b0;
else if ( cnv_res_tready[0] && cnv_res_tvalid[0] && cnv_res_tlast[0] )
round_end <= 1'b1;
else if ( cstate == IDLE )
round_end <= 1'b0;
end
always@( posedge clk or negedge rst_n ) begin
if( !rst_n ) cstate <= IDLE;
else cstate <= nstate;
end
always@( * ) begin
case ( cstate )
IDLE:
if ( trans_round )
nstate <= READY_ST;
else
nstate <= IDLE;
READY_ST:
if ( cnv_res_tvalid_array )
nstate <= SCAN_ST;
else
nstate <= READY_ST;
SCAN_ST:
if ( scan_cnt == CHIPSET_QTY-1 )
nstate <= round_end? IDLE:READY_ST;
else
nstate <= SCAN_ST;
default:
nstate <= IDLE;
endcase
end
generate
for(i=0;i<CHIPSET_QTY;i=i+1) begin : tready
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
cnv_res_tready[i] <= 1'b0;
else if ( cstate == IDLE || (cstate == READY_ST && nstate == READY_ST) )
cnv_res_tready[i] <= 1'b1;
else
cnv_res_tready[i] <= 1'b0;
end
end
endgenerate
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
scan_cnt <= 0;
else if ( cstate == READY_ST )
scan_cnt <= 0;
else if ( cstate == SCAN_ST )
scan_cnt <= scan_cnt + 1'b1;
end
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n ) begin
axi_str_rxd_tvalid <= 1'b0;
axi_str_rxd_tdata <= 0;
end else if ( cstate == SCAN_ST ) begin
axi_str_rxd_tvalid <= cnv_res_tvalid_r[scan_cnt];
axi_str_rxd_tdata <= cnv_res_tdata_r[scan_cnt];
end else begin
axi_str_rxd_tvalid <= 1'b0;
end
end
always @ ( posedge clk or negedge rst_n ) begin
if ( !rst_n )
axi_str_rxd_tlast <= 1'b0;
else if ( cstate == SCAN_ST && (scan_cnt == CHIPSET_QTY-1) && round_end )
axi_str_rxd_tlast <= 1'b1;
else
axi_str_rxd_tlast <= 1'b0;
end
//*****************************************************************************
// Wire assignment
//*****************************************************************************
generate
for(i=0;i<CHIPSET_QTY;i=i+1) begin : unpack_res
assign cnv_res_tdata[i][31:24] = cnv_res_tdata_array[32*i+31 : 32*i+24] + CH_OF_CHIPSET*i;
assign cnv_res_tdata[i][23: 0] = cnv_res_tdata_array[32*i+23 : 32*i+ 0];
assign cnv_res_tlast[i] = cnv_res_tlast_array[i];
assign cnv_res_tvalid[i] = cnv_res_tvalid_array[i];
end
endgenerate
generate
for(i=0;i<CHIPSET_QTY;i=i+1) begin : pack_res
assign cnv_res_tready_array[i] = cnv_res_tready[i];
end
endgenerate
endmodule