`timescale 1 ns / 1 ns
module dma_ctrl (
//system
input iclk,
input irst,
//axi_master
output [71:0] dma_data, //{wr_rd,adrs[31:0]}-sop-data-eop
output dma_den,
input dma_ready,
input [71:0] cpld_data,
input cpld_en,
//transform_8b_64b
input [71:0] recomb_data_2sw,
input [71:0] recomb_data_2host,
input [71:0] recomb_data_2arm,
input recomb_den_2sw,
input recomb_den_2host,
input recomb_den_2arm,
//output [2:0] recomb_buf_ready,
//send to ge port
output [71:0] down_data,
output down_den_H,
output down_den_L,
input down_buf_ready_H,
input down_buf_ready_L,
//host_reg
input iline0_en,
input [19:0] iline0_data_baseadrs,
input [19:0] iline0_mesg_baseadrs,
input [19:0] iline0_fpgawr_point_baseadrs,
input [1:0] iline0_depth_define,
input [7:0] iline0_mesg_toutcfg,
input [9:0] iline0_cpu_point,
output [9:0] oline0_fpga_point,
input iline1_en,
input [19:0] iline1_data_baseadrs,
input [19:0] iline1_mesg_baseadrs,
input [19:0] iline1_fpgawr_point_baseadrs,
input [1:0] iline1_depth_define,
input [7:0] iline1_mesg_toutcfg,
input [9:0] iline1_cpu_point,
output [9:0] oline1_fpga_point,
input iline2_en,
input [19:0] iline2_data_baseadrs,
input [19:0] iline2_mesg_baseadrs,
input [19:0] iline2_fpgawr_point_baseadrs,
input [1:0] iline2_depth_define,
input [7:0] iline2_mesg_toutcfg,
input [9:0] iline2_cpu_point,
output [9:0] oline2_fpga_point,
input iline3_en,
input [19:0] iline3_data_baseadrs,
input [19:0] iline3_mesg_baseadrs,
input [19:0] iline3_fpgawr_point_baseadrs,
input [1:0] iline3_depth_define,
input [7:0] iline3_mesg_toutcfg,
input [9:0] iline3_cpu_point,
output [9:0] oline3_fpga_point,
input iline4_en,
input [19:0] iline4_data_baseadrs,
input [19:0] iline4_mesg_baseadrs,
input [19:0] iline4_fpgawr_point_baseadrs,
input [1:0] iline4_depth_define,
input [7:0] iline4_mesg_toutcfg,
input [9:0] iline4_cpu_point,
output [9:0] oline4_fpga_point,
//debug
output reg [31:0] dma_pulse,
output reg [31:0] dma_state
);
// define
// timeout pulse
reg [7:0] time_cycle_cnt;
reg time_1us_pulse;
reg [7:0] line2_msg_tout_cnt;
reg line2_mesg_tout_pulse;
reg [9:0] line2_depth;
// main control FSM
reg [1:0] fsm_dma;
reg [3:0] ch_index;
reg [7:0] fsm_opt_cnt;
wire prepare_ch_sel;
wire done_ch_sel;
// receive transform_8b_64b data
wire [71:0] dataw_dout_line0;
wire [71:0] dataw_dout_line1;
wire [71:0] dataw_dout_line2;
wire [12:0] dataw_hout_line0;
wire [12:0] dataw_hout_line1;
wire [12:0] dataw_hout_line2;
wire [2:0] dataw_rdready;
wire [2:0] datawr_drop_pls;
reg [9:0] line0_dataw_point;
reg [9:0] line1_dataw_point;
reg [9:0] line2_dataw_point;
reg line0_is_full;
reg line1_is_full;
reg line2_is_full;
reg prepare_line0_dataw;
reg prepare_line1_dataw;
reg prepare_line2_dataw;
reg [7:0] dataw_head_len;
reg [10:0] dataw_head_bytecnt;
reg [2:0] dataw_rdden;
reg [2:0] dataw_rdden_d1;
reg [2:0] dataw_rdden_d2;
reg [2:0] dataw_rdden_d3;
reg [2:0] dataw_rdhen;
reg [2:0] dataw_rdhen_d1;
reg [2:0] dataw_rdhen_d2;
reg [2:0] dataw_rdhen_d3;
wire done_line0_dataw;
wire done_line1_dataw;
wire done_line2_dataw;
reg [71:0] mesgw;
reg mesgw_wen;
reg [71:0] dataw_headdata;
reg dataw_headden;
// receive message
reg mesgw_buf_ready;
wire [71:0] mesgw_dout_line2;
wire mesgw_empty_line2;
wire [9:0] mesgw_count_line2;
reg prepare_line0_mesgw;
reg prepare_line1_mesgw;
reg prepare_line2_mesgw;
reg [31:0] line012_mesg_optadrs;
reg [10:0] num_mesgw_bottom;
reg [10:0] num_mesgw_4KB;
reg [10:0] num_mesgw_fifo;
reg [10:0] num_mesgw_act;
reg [10:0] line012_mesgw_optleng;
//read control
reg mesgw_opt_en;
reg [10:0] mesgw_rdcnt;
reg done_line012_mesgw;
reg mesgw_ren;
wire mesgw_headen;
// refresh mesg_wr_point
reg done_line012_mesgw_d1;
reg done_line012_refresh;
reg [9:0] line0_mesgwr_point;
reg [9:0] line1_mesgwr_point;
reg [9:0] line2_mesgwr_point;
reg refresh_line_en_sel;
reg dma_data_refresh_en;
reg [71:0] dma_data_refresh;
// read line-tx message
reg prepare_line3_mesgr;
reg prepare_line4_mesgr;
reg [10:0] num_mesgr_bottom;
reg [10:0] num_mesgr_4KB;
reg [10:0] num_mesgr_linedepth;
reg [10:0] num_mesgr_act;
reg [31:0] line34_mesg_optadrs;
reg [10:0] line34_mesg_optleng;
reg line3_mesg_opten;
reg line4_mesg_opten;
reg [9:0] line3_mesgrd_point;
reg [9:0] line4_mesgrd_point;
reg mesg_rd_ing_line3;
reg mesg_rd_ing_line4;
wire done_line3_mesgr;
wire done_line4_mesgr;
reg mesgr_buf_ready_line3;
reg mesgr_buf_ready_line4;
wire [1:0] cpld_port;
wire [71:0] mesgr_dout_line3;
wire mesgr_empty_line3;
wire [9:0] mesgr_count_line3;
wire [71:0] mesgr_dout_line4;
wire mesgr_empty_line4;
wire [9:0] mesgr_count_line4;
// read line-tx data
reg prepare_line3_datar;
reg prepare_line4_datar;
reg [31:0] line34_data_optadrs;
reg [10:0] line34_data_optleng;
reg line3_data_opten;
reg line4_data_opten;
reg [9:0] line3_datard_point;
reg cplded_line3_datar;
reg [9:0] line4_datard_point;
reg cplded_line4_datar;
reg data_rd_ing_line3;
reg data_rd_ing_line4;
wire done_line3_datar;
wire mesgr_ren_line3;
wire done_line4_datar;
wire mesgr_ren_line4;
reg [71:0] down_data_r;
reg down_den_r_H;
reg down_den_r_L;
// output control
reg [71:0] dma_data_r;
reg dma_den_r;
// main control - FSM
// timeout pulse
always @ (posedge iclk)begin
if(irst)begin
time_cycle_cnt <= 8'b0;
time_1us_pulse <= 1'b0;
line2_msg_tout_cnt <= 8'b0;
line2_mesg_tout_pulse <= 1'b0;
end else begin
time_cycle_cnt <= time_cycle_cnt + 1'b1;
time_1us_pulse <= (time_cycle_cnt==8'hFF)?1'b1:1'b0; //256*5ns=1.2us
if(time_1us_pulse==1'b1)begin
line2_msg_tout_cnt <= (line2_msg_tout_cnt==iline2_mesg_toutcfg)?8'h0:(line2_msg_tout_cnt+1'b1);
end
if(time_1us_pulse==1'b1)begin //default:1.2us*0x80=0.15ms
line2_mesg_tout_pulse <= (line2_msg_tout_cnt==iline2_mesg_toutcfg)?1'b1:1'b0;
end else begin
line2_mesg_tout_pulse <= 1'b0;
end
end
end
//line depth
always @ (posedge iclk)begin
line2_depth <= (iline2_depth_define==2'b11)?10'h3ff:
(iline2_depth_define==2'b10)?10'h1ff:
(iline2_depth_define==2'b01)?10'h0ff:10'h07f;
end
// main control FSM
parameter F_IDLE = 2'h0;
parameter F_OPT = 2'h1;
always @ (posedge iclk)begin
if(irst)begin
fsm_dma <= F_IDLE;
end else begin
case(fsm_dma)
F_IDLE : if(prepare_ch_sel==1'b1 && dma_ready==1'b1)begin
fsm_dma <= F_OPT;
end
F_OPT : if(done_ch_sel==1'b1)begin
fsm_dma <= F_IDLE;
end
default : fsm_dma <= F_IDLE;
endcase
end
end
always @ (posedge iclk)begin
if(irst)begin
ch_index <= 4'b0;
end else begin
if(fsm_dma==F_IDLE && prepare_ch_sel==1'b0)begin
ch_index <= (ch_index==4'h9)?4'b0:(ch_index + 1'b1);
end else if(fsm_dma==F_OPT && done_ch_sel==1'b1)begin
ch_index <= (ch_index==4'h9)?4'b0:(ch_index + 1'b1);
end
end
end
always @ (posedge iclk)begin
if(fsm_dma==F_OPT)begin
fsm_opt_cnt <= (fsm_opt_cnt[7:4]==4'hF)?8'hF0:(fsm_opt_cnt+1'b1);
end else begin
fsm_opt_cnt <= 8'b0;
end
end
assign prepare_ch_sel = (ch_index==4'h0) ? prepare_line0_dataw :
(ch_index==4'h1) ? prepare_line1_dataw :
(ch_index==4'h2) ? prepare_line2_dataw :
(ch_index==4'h3) ? prepare_line0_mesgw :
(ch_index==4'h4) ? prepare_line1_mesgw :
(ch_index==4'h5) ? prepare_line2_mesgw :
(ch_index==4'h6) ? prepare_line3_mesgr :
(ch_index==4'h7) ? prepare_line4_mesgr :
(ch_index==4'h8) ? prepare_line3_datar :
prepare_line4_datar ;
assign done_ch_sel = (ch_index==4'h0) ? done_line0_dataw :
(ch_index==4'h1) ? done_line1_dataw :
(ch_index==4'h2) ? done_line2_dataw :
(ch_index==4'h3) ? done_line012_refresh :
(ch_index==4'h4) ? done_line012_refresh :
(ch_index==4'h5) ? done_line012_refresh :
(ch_index==4'h6) ? done_line3_mesgr :
(ch_index==4'h7) ? done_line4_mesgr :
(ch_index==4'h8) ? done_line3_datar :
done_line4_datar ;
// receive transform_8b_64b data
buf_store_forward_w72 buf_line0(
.sys_clk (iclk),
.sys_rst (irst),
.wrdata (recomb_data_2sw),
.wrdata_eop (recomb_data_2sw[70]),
.wrdata_err (1'b0),
.wrdata_info (2'b0),
.wren (recomb_den_2sw),
.wrready (),
.rddata (dataw_dout_line0),
.rdden (dataw_rdden[0]),
.rdhead (dataw_hout_line0),
.rdhen (dataw_rdhen[0]),
.rdready (dataw_rdready[0]),
.wr_drop_pls (datawr_drop_pls[0])
);
buf_store_forward_w72 buf_line1(
.sys_clk (iclk),
.sys_rst (irst),
.wrdata (recomb_data_2host),
.wrdata_eop (recomb_data_2host[70]),
.wrdata_err (1'b0),
.wrdata_info (2'b0),
.wren (recomb_den_2host),
.wrready (),
.rddata (dataw_dout_line1),
.rdden (dataw_rdden[1]),
.rdhead (dataw_hout_line1),
.rdhen (dataw_rdhen[1]),
.rdready (dataw_rdready[1]),
.wr_drop_pls (datawr_drop_pls[1])
);
buf_store_forward_w72 buf_line2(
.sys_clk (iclk),
.sys_rst (irst),
.wrdata (recomb_data_2arm),
.wrdata_eop (recomb_data_2arm[70]),
.wrdata_err (1'b0),
.wrdata_info (2'b0),
.wren (recomb_den_2arm),
.wrready (),
.rddata (dataw_dout_line2),
.rdden (dataw_rdden[2]),
.rdhead (dataw_hout_line2),
.rdhen (dataw_rdhen[2]),
.rdready (dataw_rdready[2]),
.wr_drop_pls (datawr_drop_pls[2])
);
always @ (posedge iclk)begin
if(iline0_en==1'b0)begin
line0_dataw_point <= 10'b0;
end else if(dataw_rdhen[0])begin
line0_dataw_point <= (line0_dataw_point==line2_depth)?10'b0:(line0_dataw_point+1'b1);
end
if(iline1_en==1'b0)begin
line1_dataw_point <= 10'b0;
end else if(dataw_rdhen[1])begin
line1_dataw_point <= (line1_dataw_point==line2_depth)?10'b0:(line1_dataw_point+1'b1);
end
if(iline2_en==1'b0)begin
line2_dataw_point <= 10'b0;
end else if(dataw_rdhen[2])begin
line2_dataw_point <= (line2_dataw_point==line2_depth)?10'b0:(line2_dataw_point+1'b1);
end
if((line0_dataw_point+1'b1)&line2_depth==iline0_cpu_point)begin
line0_is_full <= 1'b1;
end else begin
line0_is_full <= 1'b0;
end
if((line1_dataw_point+1'b1)&line2_depth==iline1_cpu_point)begin
line1_is_full <= 1'b1;
end else begin
line1_is_full <= 1'b0;
end
if((line2_dataw_point+1'b1)&line2_depth==iline2_cpu_point)begin
line2_is_full <= 1'b1;
end else begin
line2_is_full <= 1'b0;
end
prepare_line0_dataw <= (dataw_rdready[0]==1'b1) & (line0_is_full==1'b0) & (iline0_en==1'b1);
prepare_line1_dataw <= (dataw_rdready[1]==1'b1) & (line1_is_full==1'b0) & (iline1_en==1'b1);
prepare_line2_dataw <= (dataw_rdready[2]==1'b1) & (line2_is_full==1'b0) & (iline2_en==1'b1) & (mesgw_buf_ready==1'b1);
end
always @ (posedge iclk)begin
if(fsm_dma==F_IDLE && ch_index==4'h0)begin
dataw_head_len <= dataw_hout_line0[10:3];
dataw_head_bytecnt <= dataw_hout_line0[10:0]+1'b1;
end else if(fsm_dma==F_IDLE && ch_index==4'h1)begin
dataw_head_len <= dataw_hout_line1[10:3];
dataw_head_bytecnt <= dataw_hout_line1[10:0]+1'b1;
end else if(fsm_dma==F_IDLE && ch_index==4'h2)begin
dataw_head_len <= dataw_hout_line2[10:3];
dataw_head_bytecnt <= dataw_hout_line2[10:0]+1'b1;
end
dataw_rdden[0] <= (fsm_dma==F_OPT) & (fsm_opt_cnt<=dataw_head_len) & (ch_index==4'h0);
dataw_rdden[1] <= (fsm_dma==F_OPT) & (fsm_opt_cnt<=dataw_head_len) & (ch_index==4'h1);
dataw_rdden[2] <= (fsm_dma==F_OPT) & (fsm_opt_cnt<=dataw_head_len) & (ch_index==4'h2);
dataw_rdhen[0] <= (fsm_dma==F_OPT) & (fsm_opt_cnt==dataw_head_len) & (ch_index==4'h0);
dataw_rdhen[1] <= (fsm_dma==F_OPT) & (fsm_opt_cnt==dataw_head_len) & (ch_index==4'h1);
dataw_rdhen[2] <= (fsm_dma==F_OPT) & (fsm_opt_cnt==dataw_head_len) & (ch_index==4'h2);
end
always @ (posedge iclk)begin
dataw_rdden_d1 <= dataw_rdden;
dataw_rdden_d2 <= dataw_rdden_d1;
dataw_rdden_d3 <= dataw_rdden_d2;
dataw_rdhen_d1 <= dataw_rdhen;
dataw_rdhen_d2 <= dataw_rdhen_d1;
dataw_rdhen_d3 <= dataw_rdhen_d2;
end
assign done_line0_dataw = dataw_rdhen_d2[0];
assign done_line1_dataw = dataw_rdhen_d2[1];
assign done_line2_dataw = dataw_rdhen_d2[2];
always @ (posedge iclk)begin
if(ch_index==4'h2 && fsm_dma==F_OPT && fsm_opt_cnt==8'b0)begin
mesgw <= {dataw_head_bytecnt,22'b0,line2_dataw_point[9:0]};
mesgw_wen <= iline2_en;
end else begin
mesgw_wen <= 1'b0;
end
end
always @ (posedge iclk)begin
if(ch_index==4'h0 && fsm_dma==F_OPT && fsm_opt_cnt==8'b0)begin
dataw_headdata[71:70] <= 2'b10;
dataw_headdata[69:43] <= 27&#