Commit 1aebe5e1 authored by Alexey Grebenkin's avatar Alexey Grebenkin

Complete host intermediate commit, pre-testing

parent be827c35
......@@ -40,7 +40,73 @@ module dma_regs #(
input wire [3:0] bram_wstb,
input wire bram_wen,
input wire bram_ren,
input wire bram_regen
input wire bram_regen,
// tmp to cmd control
output wire cmd_val_out,
output wire [31:0] cmd_out,
// tmp to shadow registers
output wire [31:0] sh_data, // write data
output wire sh_data_val, // write strobe
output wire sh_data_strobe, // read strobe
output wire [15:0] sh_feature,
output wire sh_feature_val,
output wire [23:0] sh_lba_lo,
output wire sh_lba_lo_val,
output wire [23:0] sh_lba_hi,
output wire sh_lba_hi_val,
output wire [15:0] sh_count,
output wire sh_count_val,
output wire [7:0] sh_command,
output wire sh_command_val,
output wire [7:0] sh_dev,
output wire sh_dev_val,
output wire [7:0] sh_control,
output wire sh_control_val,
output wire [31:0] sh_dma_id_lo
output wire sh_dma_id_lo_val,
output wire [31:0] sh_dma_id_hi,
output wire sh_dma_id_hi_val,
output wire [31:0] sh_buf_off,
output wire sh_buf_off_val,
output wire [31:0] sh_dma_cnt,
output wire sh_dma_cnt_val,
output wire [31:0] sh_tran_cnt,
output wire sh_tran_cnt_val,
output wire sh_autoact,
output wire sh_autoact_val,
output wire sh_inter,
output wire sh_inter_val,
output wire [3:0] sh_port,
output wire sh_port_val,
output wire sh_notif,
output wire sh_notif_val,
output wire sh_dir,
output wire sh_dir_val,
// inputs from sh registers
input wire sh_data_val_in,
input wire [31:0] sh_data_in,
input wire [7:0] sh_control_in,
input wire [15:0] sh_feature_in,
input wire [47:0] sh_lba_in,
input wire [15:0] sh_count_in,
input wire [7:0] sh_command_in,
input wire [7:0] sh_err_in,
input wire [7:0] sh_status_in,
input wire [7:0] sh_estatus_in, // E_Status
input wire [7:0] sh_dev_in,
input wire [3:0] sh_port_in,
input wire sh_inter_in,
input wire sh_dir_in,
input wire [63:0] sh_dma_id_in,
input wire [31:0] sh_dma_off_in,
input wire [31:0] sh_dma_cnt_in,
input wire [15:0] sh_tran_cnt_in, // Transfer Count
input wire sh_notif_in,
input wire sh_autoact_in
// inputs from cmd control
input wire [31:0] cmd_in
);
//reg [32*REGISTERS_CNT - 1:0] mem;
/*
......@@ -86,7 +152,7 @@ pulse_cross_clock dma_start_pulse(
.busy ()
);
assign dma_start_aclk = bram_wen & (bram_waddr[3:0] == 4'h4) & |wdata;
assign dma_start_aclk = bram_wen & (bram_waddr[7:0] == 8'hf4) & |wdata;
assign wdata = bram_wdata[31:0] & {{8{bram_wstb[3]}}, {8{bram_wstb[2]}}, {8{bram_wstb[1]}}, {8{bram_wstb[0]}}};
always @ (posedge ACLK)
......@@ -99,27 +165,94 @@ assign dma_type = |reg0c;
always @ (posedge ACLK)
begin
reg00 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h0) ? wdata : reg00;
reg04 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h1) ? wdata : reg04;
reg08 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h2) ? wdata : reg08;
reg0c <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h3) ? wdata : reg0c;
reg00 <= rst ? 32'h0 : bram_wen & (bram_waddr[7:0] == 8'hf0) ? wdata : reg00;
reg04 <= rst ? 32'h0 : bram_wen & (bram_waddr[7:0] == 8'hf1) ? wdata : reg04;
reg08 <= rst ? 32'h0 : bram_wen & (bram_waddr[7:0] == 8'hf2) ? wdata : reg08;
reg0c <= rst ? 32'h0 : bram_wen & (bram_waddr[7:0] == 8'hf3) ? wdata : reg0c;
reg10 <= rst ? 32'h0 : dma_start_aclk ? 32'h0 : dma_done_aclk ? 32'hffffffff : reg10; // status reg
reg14 <= rst ? 32'h0 : dma_done_aclk ? reg00 : reg14;
end
// writes to shadow registers:
assign sh_data_val = bram_wen & (bram_waddr[7:0] == 8'h0);
assign sh_feature_val = bram_wen & (bram_waddr[7:0] == 8'h1);
assign sh_lba_lo_val = bram_wen & (bram_waddr[7:0] == 8'h2);
assign sh_lba_hi_val = bram_wen & (bram_waddr[7:0] == 8'h3);
assign sh_count_val = bram_wen & (bram_waddr[7:0] == 8'h4);
assign sh_command_val = bram_wen & (bram_waddr[7:0] == 8'h5);
assign sh_dev_val = bram_wen & (bram_waddr[7:0] == 8'h6);
assign sh_control_val = bram_wen & (bram_waddr[7:0] == 8'h7);
assign sh_dma_id_lo_val = bram_wen & (bram_waddr[7:0] == 8'h8);
assign sh_dma_id_hi_val = bram_wen & (bram_waddr[7:0] == 8'h9);
assign sh_buf_off_val = bram_wen & (bram_waddr[7:0] == 8'ha);
assign sh_tran_cnt_val = bram_wen & (bram_waddr[7:0] == 8'hb);
assign sh_autoact_val = bram_wen & (bram_waddr[7:0] == 8'hc);
assign sh_inter_val = bram_wen & (bram_waddr[7:0] == 8'hd);
assign sh_dir_val = bram_wen & (bram_waddr[7:0] == 8'he);
assign cmd_val_out = bram_wen & (bram_waddr[7:0] == 8'hf);
assign sh_port = bram_wen & (bram_waddr[7:0] == 8'h13);
assign sh_dma_cnt_val = bram_wen & (bram_waddr[7:0] == 8'h14);
assign sh_notif_val = bram_wen & (bram_waddr[7:0] == 8'h15);
assign sh_data = wdata;
assign sh_feature = wdata;
assign sh_lba_lo = wdata;
assign sh_lba_hi = wdata;
assign sh_count = wdata;
assign sh_command = wdata;
assign sh_dev = wdata;
assign sh_control = wdata;
assign sh_dma_id_lo = wdata;
assign sh_dma_id_hi = wdata;
assign sh_buf_off = wdata;
assign sh_tran_cnt = wdata;
assign sh_autoact = wdata;
assign sh_inter = wdata;
assign sh_dir = wdata;
assign sh_port = wdata;
assign sh_notif = wdata;
assign sh_dma_cnt = wdata;
assign cmd_out = wdata;
assign sh_data_strobe = bram_regen & bram_raddr_r == 8'h00;
// read from registers. Interface's protocol assumes returning data with a delay
reg [3:0] bram_raddr_r;
reg [7:0] bram_raddr_r;
reg [31:0] bram_rdata_r;
always @ (posedge ACLK) begin
bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r;
bram_raddr_r <= bram_ren ? bram_raddr[7:0] : bram_raddr_r;
bram_rdata_r <= ~bram_regen ? bram_rdata_r :
bram_raddr_r == 4'h0 ? reg00 :
bram_raddr_r == 4'h1 ? reg04 :
bram_raddr_r == 4'h2 ? reg08 :
bram_raddr_r == 4'h3 ? reg0c :
bram_raddr_r == 4'h4 ? reg10 :
bram_raddr_r == 4'h5 ? reg14 :
32'hd34db33f;
bram_raddr_r == 8'hf0 ? reg00 :
bram_raddr_r == 8'hf1 ? reg04 :
bram_raddr_r == 8'hf2 ? reg08 :
bram_raddr_r == 8'hf3 ? reg0c :
bram_raddr_r == 8'hf4 ? reg10 :
bram_raddr_r == 8'hf5 ? reg14 :
bram_raddr_r == 8'h00 ? sh_data_in :
bram_raddr_r == 8'h01 ? sh_feature_in :
bram_raddr_r == 8'h02 ? sh_lba_in[23:0] :
bram_raddr_r == 8'h03 ? sh_lba_in[47:24] :
bram_raddr_r == 8'h04 ? sh_count_in :
bram_raddr_r == 8'h05 ? sh_command_in :
bram_raddr_r == 8'h06 ? sh_dev_in :
bram_raddr_r == 8'h07 ? sh_control_in :
bram_raddr_r == 8'h08 ? sh_dma_id_in[31:0] :
bram_raddr_r == 8'h09 ? sh_dma_id_in[63:32] :
bram_raddr_r == 8'h0a ? sh_dma_off_in :
bram_raddr_r == 8'h0b ? sh_tran_cnt_in : // Transfer Count
bram_raddr_r == 8'h0c ? sh_autoact_in :
bram_raddr_r == 8'h0d ? sh_inter_in :
bram_raddr_r == 8'h0e ? sh_dir_in :
bram_raddr_r == 8'h0f ? cmd_in :
bram_raddr_r == 8'h10 ? sh_err_in :
bram_raddr_r == 8'h11 ? sh_status_in :
bram_raddr_r == 8'h12 ? sh_estatus_in : // E_Status
bram_raddr_r == 8'h13 ? sh_port_in :
bram_raddr_r == 8'h14 ? sh_dma_cnt_in :
bram_raddr_r == 8'h15 ? sh_notif_in :
32'hd34db33f;
end
assign bram_rdata = bram_rdata_r;
......
/*******************************************************************************
* Module: command
* Date: 2015-07-11
* Author: Alexey
* Description: sata command layer temporary implementation
*
* Copyright (c) 2015 Elphel, Inc.
* command.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* command.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
/*
* For testing purposes almost neat, manually-controlled
*/
module command(
input rst,
input clk,
// tl cmd iface
output wire [2:0] cmd_type,
output wire cmd_val,
output wire [3:0] cmd_port,
input wire cmd_busy,
input wire cmd_done_good,
input wire cmd_done_bad,
// temporary TODO
input wire [31:0] al_cmd_in, // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good, cmd_busy}
input wire al_cmd_val_in,
output wire [31:0] al_cmd_out, // same
// data from tl
input wire [31:0] tl_data_in,
input wire tl_data_val_in,
input wire tl_data_last_in,
output wire tl_data_busy_out,
// to tl
output wire [31:0] tl_data_out,
output wire tl_data_last_out,
output wire tl_data_val_out,
input wire tl_data_strobe_in,
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
input wire [31:0] al_sh_data_in, // write data
input wire al_sh_data_val_in, // write strobe
input wire al_sh_data_strobe_in, // read strobe
input wire [15:0] al_sh_feature_in,
input wire al_sh_feature_val_in,
input wire [23:0] al_sh_lba_lo_in,
input wire al_sh_lba_lo_val_in,
input wire [23:0] al_sh_lba_hi_in,
input wire al_sh_lba_hi_val_in,
input wire [15:0] al_sh_count_in,
input wire al_sh_count_val_in,
input wire [7:0] al_sh_command_in,
input wire al_sh_command_val_in,
input wire [7:0] al_sh_dev_in,
input wire al_sh_dev_val_in,
input wire [7:0] al_sh_control_in,
input wire al_sh_control_val_in,
input wire [31:0] al_sh_dma_id_lo_in,
input wire al_sh_dma_id_lo_val_in,
input wire [31:0] al_sh_dma_id_hi_in,
input wire al_sh_dma_id_hi_val_in,
input wire [31:0] al_sh_buf_off_in,
input wire al_sh_buf_off_val_in,
input wire [31:0] al_sh_tran_cnt_in,
input wire al_sh_tran_cnt_val_in,
input wire al_sh_autoact_in,
input wire al_sh_autoact_val_in,
input wire al_sh_inter_in,
input wire al_sh_inter_val_in,
input wire al_sh_dir_in,
input wire al_sh_dir_val_in,
input wire [31:0] al_sh_dma_cnt_in,
input wire al_sh_dma_cnt_val_in,
input wire al_sh_notif_in,
input wire al_sh_notif_val_in,
input wire [3:0] al_sh_port_in,
input wire al_sh_port_val_in,
// from tl
input wire [47:0] tl_sh_lba_in,
input wire [15:0] tl_sh_count_in,
input wire [7:0] tl_sh_command_in,
input wire [7:0] tl_sh_err_in,
input wire [7:0] tl_sh_status_in,
input wire [7:0] tl_sh_estatus_in, // E_Status
input wire [7:0] tl_sh_dev_in,
input wire [3:0] tl_sh_port_in,
input wire tl_sh_inter_in,
input wire tl_sh_dir_in,
input wire [63:0] tl_sh_dma_id_in,
input wire [31:0] tl_sh_dma_off_in,
input wire [31:0] tl_sh_dma_cnt_in,
input wire [15:0] tl_sh_tran_cnt_in, // Transfer Count
input wire tl_sh_notif_in,
input wire tl_sh_autoact_in,
input wire tl_sh_lba_val_in,
input wire tl_sh_count_val_in,
input wire tl_sh_command_val_in,
input wire tl_sh_err_val_in,
input wire tl_sh_status_val_in,
input wire tl_sh_estatus_val_in, // E_Status
input wire tl_sh_dev_val_in,
input wire tl_sh_port_val_in,
input wire tl_sh_inter_val_in,
input wire tl_sh_dir_val_in,
input wire tl_sh_dma_id_val_in,
input wire tl_sh_dma_off_val_in,
input wire tl_sh_dma_cnt_val_in,
input wire tl_sh_tran_cnt_val_in, // Transfer Count
input wire tl_sh_notif_val_in,
input wire tl_sh_autoact_val_in,
// all regs to output
output wire sh_data_val_out,
output wire [31:0] sh_data_out,
output wire [7:0] sh_control_out,
output wire [15:0] sh_feature_out,
output wire [47:0] sh_lba_out,
output wire [15:0] sh_count_out,
output wire [7:0] sh_command_out,
output wire [7:0] sh_err_out,
output wire [7:0] sh_status_out,
output wire [7:0] sh_estatus_out, // E_Status
output wire [7:0] sh_dev_out,
output wire [3:0] sh_port_out,
output wire sh_inter_out,
output wire sh_dir_out,
output wire [63:0] sh_dma_id_out,
output wire [31:0] sh_dma_off_out,
output wire [31:0] sh_dma_cnt_out,
output wire [15:0] sh_tran_cnt_out, // Transfer Count
output wire sh_notif_out,
output wire sh_autoact_out
);
// shadow registers
wire [31:0] sh_data;
reg [7:0] sh_control;
reg [15:0] sh_feature;
reg [47:0] sh_lba;
reg [15:0] sh_count;
reg [7:0] sh_command;
reg [7:0] sh_err;
reg [7:0] sh_status;
reg [7:0] sh_estatus; // E_Status
reg [7:0] sh_dev;
reg [3:0] sh_port;
reg sh_inter;
reg sh_dir;
reg [63:0] sh_dma_id;
reg [31:0] sh_dma_off;
reg [31:0] sh_dma_cnt;
reg [15:0] sh_tran_cnt; // Transfer Count
reg sh_notif;
reg sh_autoact;
always @ (posedge clk)
begin
// sh_data <= rst ? 32'h0 : al_sh_data_val_in ? al_sh_data_in : /*tl_sh_data_val_in ? tl_sh_data_in :*/ sh_data;
sh_control <= rst ? 8'h0 : al_sh_control_val_in ? al_sh_control_in : /*tl_sh_control_val_in ? tl_sh_control_in :*/ sh_control;
sh_feature <= rst ? 16'h0 : al_sh_feature_val_in ? al_sh_feature_in : /*tl_sh_feature_val_in ? tl_sh_feature_in :*/ sh_feature;
sh_lba[23:0] <= rst ? 24'h0 : al_sh_lba_lo_val_in ? al_sh_lba_lo_in : tl_sh_lba_val_in ? tl_sh_lba_in[23:0] : sh_lba[23:0];
sh_lba[47:24] <= rst ? 24'h0 : al_sh_lba_hi_val_in ? al_sh_lba_hi_in : tl_sh_lba_val_in ? tl_sh_lba_in[47:24] : sh_lba[47:24];
sh_count <= rst ? 16'h0 : al_sh_count_val_in ? al_sh_count_in : tl_sh_count_val_in ? tl_sh_count_in : sh_count;
sh_command <= rst ? 8'h0 : al_sh_command_val_in ? al_sh_command_in : tl_sh_command_val_in ? tl_sh_command_in : sh_command;
sh_err <= rst ? 8'h0 :/* al_sh_err_val_in ? al_sh_err_in :*/ tl_sh_err_val_in ? tl_sh_err_in : sh_err;
sh_status <= rst ? 8'h0 :/* al_sh_status_val_in ? al_sh_status_in :*/ tl_sh_status_val_in ? tl_sh_status_in : sh_status;
sh_estatus <= rst ? 8'h0 :/* al_sh_estatus_val_in ? al_sh_estatus_in :*/ tl_sh_estatus_val_in ? tl_sh_estatus_in : sh_estatus;
sh_dev <= rst ? 8'h0 : al_sh_dev_val_in ? al_sh_dev_in : tl_sh_dev_val_in ? tl_sh_dev_in : sh_dev;
sh_port <= rst ? 4'h0 : al_sh_port_val_in ? al_sh_port_in : tl_sh_port_val_in ? tl_sh_port_in : sh_port;
sh_inter <= rst ? 1'h0 : al_sh_inter_val_in ? al_sh_inter_in : tl_sh_inter_val_in ? tl_sh_inter_in : sh_inter;
sh_dir <= rst ? 1'h0 : al_sh_dir_val_in ? al_sh_dir_in : tl_sh_dir_val_in ? tl_sh_dir_in : sh_dir;
sh_dma_id[31:0] <= rst ? 32'h0 : al_sh_dma_id_lo_val_in ? al_sh_dma_id_lo_in : tl_sh_dma_id_val_in ? tl_sh_dma_id_in[31:0] : sh_dma_id[31:0];
sh_dma_id[63:32] <= rst ? 32'h0 : al_sh_dma_id_lo_val_in ? al_sh_dma_id_hi_in : tl_sh_dma_id_val_in ? tl_sh_dma_id_in[63:32] : sh_dma_id[63:32];
sh_dma_off <= rst ? 32'h0 : al_sh_buf_off_val_in ? al_sh_buf_off_in : tl_sh_dma_off_val_in ? tl_sh_dma_off_in : sh_dma_off;
sh_dma_cnt <= rst ? 32'h0 : al_sh_dma_cnt_val_in ? al_sh_dma_cnt_in : tl_sh_dma_cnt_val_in ? tl_sh_dma_cnt_in : sh_dma_cnt;
sh_tran_cnt <= rst ? 32'h0 : al_sh_tran_cnt_val_in ? al_sh_tran_cnt_in : tl_sh_tran_cnt_val_in ? tl_sh_tran_cnt_in : sh_tran_cnt;
sh_notif <= rst ? 1'h0 : al_sh_notif_val_in ? al_sh_notif_in : tl_sh_notif_val_in ? tl_sh_notif_in : sh_notif;
sh_autoact <= rst ? 1'h0 : al_sh_autoact_val_in ? al_sh_autoact_in : tl_sh_autoact_val_in ? tl_sh_autoact_in : sh_autoact;
end
// outputs assignment
assign sh_data_out = sh_data;
assign sh_control_out = sh_control;
assign sh_feature_out = sh_feature;
assign sh_lba_out = sh_lba;
assign sh_count_out = sh_count;
assign sh_command_out = sh_command;
assign sh_err_out = sh_err;
assign sh_status_out = sh_status;
assign sh_estatus_out = sh_estatus;
assign sh_dev_out = sh_dev;
assign sh_port_out = sh_port;
assign sh_inter_out = sh_inter;
assign sh_dir_out = sh_dir;
assign sh_dma_id_out = sh_dma_id;
assign sh_dma_off_out = sh_dma_off;
assign sh_dma_cnt_out = sh_dma_cnt;
assign sh_tran_cnt_out = sh_tran_cnt;
assign sh_notif_out = sh_notif;
assign sh_autoact_out = sh_autoact;
// temporaty command register TODO
reg [31:0] cmd;
assign al_cmd_out = cmd;
always @ (posedge clk)
begin
cmd[31:4] <= rst ? 28'h0 : al_cmd_val_in ? al_cmd_in : cmd;
cmd[3] <= rst ? 1'b0 : al_cmd_val_in ? al_cmd_in[3] : cmd_val ? 1'b0 : cmd[3];
cmd[2] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_bad ? 1'b1 : cmd[2];
cmd[1] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_good ? 1'b1 : cmd[2];
cmd[0] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_busy;
end
assign cmd_val = ~cmd_busy & cmd[3];
assign cmd_type = cmd[10:8];
assign cmd_port = cmd[7:4];
// data read buffer, 2048 dwords
reg [9:0] raddr;
reg [9:0] waddr;
assign tl_data_busy_out = 1'b0;
assign tl_data_out = 32'h0;
assign tl_data_last_out = 1'b0;
assign tl_data_val_out = 1'b0;
always @ (posedge clk)
waddr <= rst ? 1'b0 : ~tl_data_val_in ? waddr : (raddr == waddr + 1'b1) ? waddr : waddr + 1'b1;
always @ (posedge clk)
raddr <= rst ? 1'b0 : al_sh_data_strobe_in ? raddr + 1'b1 : waddr;
ram_1kx32_1kx32 rbuf(
.rclk (clk), // clock for read port
.raddr (raddr), // read address
.ren (al_sh_data_strobe_in), // read port enable
.regen (1'b0), // output register enable
.data_out (sh_data), // data out
.wclk (clk), // clock for read port
.waddr (waddr), // write address
.we (tl_data_val_in), // write port enable
.web (4'hf),
.data_in (tl_data_in) // data out
);
endmodule
......@@ -23,6 +23,7 @@ module link #(
parameter DATA_BYTE_WIDTH = 4
)
(
// TODO insert watchdogs
input wire rst,
input wire clk,
......@@ -49,9 +50,9 @@ module link #(
// count every data bundle read by transport layer, even if busy flag is set
// let the transport layer handle oveflows by himself
output wire data_val_out,
output wire data_last_out,
// transport layer tells if its inner buffer is almost full
input wire data_busy_in,
output wire data_last_out,
// request for a new frame transition
input wire frame_req,
......@@ -70,11 +71,13 @@ module link #(
output wire incom_start,
// if incoming transition was completed
output wire incom_done,
// if incoming transition had errors
output wire incom_invalidate,
// transport layer responds on a completion of a FIS
input wire incom_ack_good,
input wire incom_ack_bad,
// oob sequence is reinitiated and link now is not espeblished
// oob sequence is reinitiated and link now is not established or rxelecidle
input wire link_reset,
// TL demands to brutally cancel current transaction
input wire sync_escape_req,
......@@ -93,7 +96,7 @@ module link #(
input wire [DATA_BYTE_WIDTH/2 - 1:0] phy_err_in, // disperr | notintable
// to phy
output wire [DATA_BYTE_WIDTH*8 - 1:0] phy_data_out,
output wire [DATA_BYTE_WIDTH/2 - 1:0] phy_isk_out, // charisk
output wire [DATA_BYTE_WIDTH/2 - 1:0] phy_isk_out // charisk
);
// scrambled data
wire [DATA_BYTE_WIDTH*8 - 1:0] scrambler_out;
......@@ -104,7 +107,7 @@ wire crc_bad;
// current crc
wire [31:0] crc_dword;
wire data_txing; // if there are still some data to transmit and the transaction wasn't cancelled
reg data_txing; // if there are still some data to transmit and the transaction wasn't cancelled
always @ (posedge clk)
data_txing <= rst | (data_last_in & data_strobe_out | dword_val & rcvd_dword[CODE_DMATP]) ? 1'b0 : frame_req ? 1'b1 : data_txing;
......@@ -130,12 +133,6 @@ localparam CODE_OKP = 13;
localparam CODE_ERRP = 14;
// form a response to transport layer
wire frame_done;
assign frame_done = frame_done_good | frame_done_bad;
assign frame_done_good = status_send_wait & dword_val & rcvd_dword[CODE_OKP];
assign frame_done_bad = status_send_wait & dword_val & rcvd_dword[CODE_ERRP];
// fsm
// states and transitions are taken from the doc, "Link Layer State Machine" chapter
// power mode states are not implemented. TODO insert them as an additional branch of fsm
......@@ -249,7 +246,7 @@ assign alignes_pair_0 = alignes_timer == 9'd252;
assign alignes_pair_1 = alignes_timer == 9'd253;
assign alignes_pair = alignes_pair_0 | alignes_pair_1;
always @ (posedge clk)
alignes_timer <= rst | alignes_pause_1 | state_reset ? 9'h0 : alignes_timer + 1'b1;
alignes_timer <= rst | alignes_pair_1 | state_reset ? 9'h0 : alignes_timer + 1'b1;
wire got_escape;
......@@ -280,8 +277,8 @@ assign set_wait = state_send_eof & phy_ready &
// receiver's branch
assign set_rcvr_wait = state_idle & dword_val & rcvd_dword[CODE_XRDYP]
| state_send_rdy & dword_val & rcvd_dword[CODE_XRDYP];
assign set_rcvr_rdy = state_rcv_wait & dword_val & rcvd_dword[CODE_XRDYP] & ~data_busy_in;
assign set_rcvr_data = state_rcvr_rdy & dword_val & rcvd_dword[CODE_SOFP];
assign set_rcvr_rdy = state_rcvr_wait & dword_val & rcvd_dword[CODE_XRDYP] & ~data_busy_in;
assign set_rcvr_data = state_rcvr_rdy & dword_val & rcvd_dword[CODE_SOFP]
| state_rcvr_rhold & dword_val & ~rcvd_dword[CODE_HOLDP] & ~rcvd_dword[CODE_EOFP] & ~rcvd_dword[CODE_SYNCP] & ~data_busy_in
| state_rcvr_shold & dword_val & ~rcvd_dword[CODE_HOLDP] & ~rcvd_dword[CODE_EOFP] & ~rcvd_dword[CODE_SYNCP];
assign set_rcvr_rhold = state_rcvr_data & dword_val & rcvd_dword[CODE_DATA] & data_busy_in;
......@@ -292,32 +289,32 @@ assign set_rcvr_eof = state_rcvr_data & dword_val & rcvd_dword[CODE_E
| state_rcvr_shold & dword_val & rcvd_dword[CODE_EOFP];
assign set_rcvr_goodcrc = state_rcvr_eof & crc_good;
assign set_rcvr_goodend = state_rcvr_goodcrc& incom_ack_good;
assign set_rcvr_badend = state_rcvr_data & dword_val & rcvd_dword[CODE_WTRM]
assign set_rcvr_badend = state_rcvr_data & dword_val & rcvd_dword[CODE_WTRMP]
| state_rcvr_eof & crc_bad
| state_rcvr_goodcrc& incom_ack_bad;
assign clr_sync_esc = set_nocomerr | set_reset | dword_val & (rcvd_dword[CODE_RDYP] | rcvd_dword[CODE_SYNCP]);
assign clr_nocommerr = set_reset | set_nocomm;
assign clr_nocomm = set_reset | set_align;
assign clr_align = set_nocomerr | set_reset | phy_ready;
assign clr_reset = ~link_reset;
assign clr_send_rdy = set_nocomerr | set_reset | set_sync_esc | set_send_sof | set_rcvr_wait;
assign clr_send_sof = set_nocomerr | set_reset | set_sync_esc | set_send_data | got_escape;
assign clr_send_data = set_nocomerr | set_reset | set_sync_esc | set_send_rhold | set_send_shold | set_send_crc | got_escape;
assign clr_send_rhold = set_nocomerr | set_reset | set_sync_esc | set_send_data | set_send_crc | got_escape;
assign clr_send_shold = set_nocomerr | set_reset | set_sync_esc | set_send_data | set_send_rhold | set_send_crc | got_escape;
assign clr_send_crc = set_nocomerr | set_reset | set_sync_esc | set_send_eof | got_escape;
assign clr_send_eof = set_nocomerr | set_reset | set_sync_esc | set_send_wait | got_escape;
assign clr_wait = set_nocomerr | set_reset | set_sync_esc | frame_done | got_escape;
assign clr_rcvr_wait = set_nocomerr | set_reset | set_sync_esc | set_rcvr_rdy | dword_val & ~rcvd_dword[CODE_RDYP];
assign clr_rcvr_rdy = set_nocomerr | set_reset | set_sync_esc | set_rcvr_data | dword_val & ~rcvd_dword[CODE_RDYP] & ~rcvd_dword[CODE_SOFP];
assign clr_rcvr_data = set_nocomerr | set_reset | set_sync_esc | set_rcvr_rhold | set_rcvr_shold | set_rcvr_eof | set_rcvr_badend | got_escape;
assign clr_rcvr_rhold = set_nocomerr | set_reset | set_sync_esc | set_rcvr_data | set_rcvr_eof | set_rcvr_shold | got_escape;
assign clr_rcvr_shold = set_nocomerr | set_reset | set_sync_esc | set_rcvr_data | set_rcvr_eof | got_escape;
assign clr_rcvr_eof = set_nocomerr | set_reset | set_sync_esc | set_rcvr_eof | set_rcvr_goodcrc | set_rcvr_badcrc;
assign clr_rcvr_goodcrc = set_nocomerr | set_reset | set_sync_esc | set_rcvr_goodend | set_rcvr_badend | set_rcvr_goodcrc | got_escape;
assign clr_rcvr_goodend = set_nocomerr | set_reset | set_sync_esc | got_escape;
assign clr_rcvr_badend = set_nocomerr | set_reset | set_sync_esc | got_escape;
assign clr_sync_esc = set_nocommerr | set_reset | dword_val & (rcvd_dword[CODE_RRDYP] | rcvd_dword[CODE_SYNCP]);
assign clr_nocommerr = set_reset | set_nocomm;
assign clr_nocomm = set_reset | set_align;
assign clr_align = set_nocommerr | set_reset | phy_ready;
assign clr_reset = ~link_reset;
assign clr_send_rdy = set_nocommerr | set_reset | set_sync_esc | set_send_sof | set_rcvr_wait;
assign clr_send_sof = set_nocommerr | set_reset | set_sync_esc | set_send_data | got_escape;
assign clr_send_data = set_nocommerr | set_reset | set_sync_esc | set_send_rhold | set_send_shold | set_send_crc | got_escape;
assign clr_send_rhold = set_nocommerr | set_reset | set_sync_esc | set_send_data | set_send_crc | got_escape;
assign clr_send_shold = set_nocommerr | set_reset | set_sync_esc | set_send_data | set_send_rhold | set_send_crc | got_escape;
assign clr_send_crc = set_nocommerr | set_reset | set_sync_esc | set_send_eof | got_escape;
assign clr_send_eof = set_nocommerr | set_reset | set_sync_esc | set_wait | got_escape;
assign clr_wait = set_nocommerr | set_reset | set_sync_esc | frame_done | got_escape;
assign clr_rcvr_wait = set_nocommerr | set_reset | set_sync_esc | set_rcvr_rdy | dword_val & ~rcvd_dword[CODE_RRDYP];
assign clr_rcvr_rdy = set_nocommerr | set_reset | set_sync_esc | set_rcvr_data | dword_val & ~rcvd_dword[CODE_RRDYP] & ~rcvd_dword[CODE_SOFP];
assign clr_rcvr_data = set_nocommerr | set_reset | set_sync_esc | set_rcvr_rhold | set_rcvr_shold | set_rcvr_eof | set_rcvr_badend | got_escape;
assign clr_rcvr_rhold = set_nocommerr | set_reset | set_sync_esc | set_rcvr_data | set_rcvr_eof | set_rcvr_shold | got_escape;
assign clr_rcvr_shold = set_nocommerr | set_reset | set_sync_esc | set_rcvr_data | set_rcvr_eof | got_escape;
assign clr_rcvr_eof = set_nocommerr | set_reset | set_sync_esc | set_rcvr_eof | set_rcvr_goodcrc | set_rcvr_badend;
assign clr_rcvr_goodcrc = set_nocommerr | set_reset | set_sync_esc | set_rcvr_goodend | set_rcvr_badend | set_rcvr_goodcrc | got_escape;
assign clr_rcvr_goodend = set_nocommerr | set_reset | set_sync_esc | got_escape;
assign clr_rcvr_badend = set_nocommerr | set_reset | set_sync_esc | got_escape;
// the only truely asynchronous transaction between states is -> state_ reset. It shall not be delayed by sending alignes
// Luckily, while in that state, the line is off, so we dont need to care about merging alignes and state-bounded primitives
......@@ -445,7 +442,7 @@ endgenerate
// select which primitive shall be sent
wire [PRIM_NUM - 1:0] select_prim;
assign select_prim[CODE_SYNCP] = ~alignes_pair & (state_idle | state_sync_esc | state_rcvr_wait | state_reset);
assign select_prim[CODE_ALIGNP] = alignes_pair | (state_nocomm | state_nocomm_err | state_align);
assign select_prim[CODE_ALIGNP] = alignes_pair | (state_nocomm | state_nocommerr | state_align);
assign select_prim[CODE_XRDYP] = ~alignes_pair & (state_send_rdy);
assign select_prim[CODE_SOFP] = ~alignes_pair & (state_send_sof);
assign select_prim[CODE_DATA] = ~alignes_pair & (state_send_data & ~set_send_shold); // if there's no data availible for a transmission, fsm still = state_send_data. Need to explicitly count this case.
......@@ -453,7 +450,7 @@ assign select_prim[CODE_HOLDAP] = ~alignes_pair & (state_send_rhold | state_
assign select_prim[CODE_HOLDP] = ~alignes_pair & (state_send_shold | state_rcvr_rhold | state_send_data & set_send_shold); // the case mentioned 2 lines upper
assign select_prim[CODE_CRC] = ~alignes_pair & (state_send_crc);
assign select_prim[CODE_EOFP] = ~alignes_pair & (state_send_eof);
assign select_prim[CODE_WTRMP] = ~alignes_pair & (state_send_wait);
assign select_prim[CODE_WTRMP] = ~alignes_pair & (state_wait);
assign select_prim[CODE_RRDYP] = ~alignes_pair & (state_rcvr_rdy);
assign select_prim[CODE_IPP] = ~alignes_pair & (state_rcvr_data & ~incom_stop_f | state_rcvr_eof | state_rcvr_goodcrc);
assign select_prim[CODE_DMATP] = ~alignes_pair & (state_rcvr_data & incom_stop_f | state_rcvr_shold & incom_stop_f);
......@@ -492,7 +489,7 @@ assign inc_is_data = dword_val & rcvd_dword[CODE_DATA] & (state_rcvr_data | sta
scrambler scrambler(
.rst (select_prim[CODE_SOFP] | dword_val & rcvd_dword[CODE_SOFP]),
.clk (clk),
.val (select_prim[CODE_DATA] | inc_is_data),
.val_in (select_prim[CODE_DATA] | inc_is_data),
.data_in (crc_dword & {DATA_BYTE_WIDTH*8{select_prim[CODE_CRC]}} |
data_in & {DATA_BYTE_WIDTH*8{select_prim[CODE_DATA]}} |
phy_data_in & {DATA_BYTE_WIDTH*8{inc_is_data}}),
......@@ -515,9 +512,25 @@ assign crc_good = ~|crc_dword & state_rcvr_eof;
assign crc_bad = |crc_dword & state_rcvr_eof;
// to TL data outputs assigment
assign data_out = scrambler_out;
// delay outputs so the last data would be marked
reg [31:0] data_out_r;
reg data_val_out_r;
reg [31:0] data_out_rr;
reg data_val_out_rr;
// if current == EOF => _r == CRC and _rr == last data piece
always @ (posedge clk)
begin
data_out_r <= scrambler_out;
data_out_rr <= data_out_r;
data_val_out_r <= inc_is_data;
data_val_out_rr <= data_val_out_r;
end
assign data_out = data_out_rr;
assign data_mask_out = 2'b11;//{DATA_BYTE_WIDTH/2{1'b1}};
assign data_val_out = select_prim[CODE_DATA];
assign data_val_out = data_val_out_rr;
assign data_last_out = set_rcvr_eof;
// from TL data
// gives a strobe everytime data is present and we're at a corresponding state.
......@@ -535,6 +548,8 @@ assign frame_rej = set_rcvr_wait & state_send_rdy & ~alignes_pair;
assign incom_start = set_rcvr_wait & ~alignes_pair;
// ... and processed
assign incom_done = set_rcvr_goodcrc & ~alignes_pair;
// or the FIS had errors
assign incom_invalidate = state_rcvr_eof & crc_bad & ~alignes_pair | state_rcvr_data & dword_val & rcvd_dword[CODE_WTRMP];
// shows that incoming primitive or data is ready to be processed // TODO somehow move alignes_pair into dword_val
assign dword_val = |rcvd_dword & phy_ready;
......@@ -558,6 +573,12 @@ assign rcvd_dword[CODE_ERRP] = phy_isk_in[0] == 1'b1 & ~|phy_isk_in[DATA_BYTE_W
// phy level errors handling TODO
assign dec_err = |phy_err_in;
// form a response to transport layer
wire frame_done;
assign frame_done = frame_done_good | frame_done_bad;
assign frame_done_good = state_wait & dword_val & rcvd_dword[CODE_OKP];
assign frame_done_bad = state_wait & dword_val & rcvd_dword[CODE_ERRP];
`ifdef CHECKERS_ENABLED
// incoming primitives
always @ (posedge clk)
......
......@@ -26,7 +26,7 @@
// All references to doc = to SerialATA_Revision_2_6_Gold.pdf
module oob #(
parameter DATA_BYTE_WIDTH = 4,
parameter CLK_SPEED_GRADE = 2, // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
)
(
// sata clk = usrclk2
......@@ -94,7 +94,7 @@ module oob #(
// reset speedgrade to the fastest one
output wire speed_rst_req,
input wire speed_rst_ack
`endif OOB_MULTISPEED
`endif //OOB_MULTISPEED
);
// 873.8 us error timer
......@@ -118,7 +118,7 @@ reg [DATA_BYTE_WIDTH - 1:0] rxcharisk;
// primitives detection
wire detected_alignp;
wire detected_synp;
wire detected_syncp;
// fsm, doc p265,266
wire state_idle;
......@@ -157,13 +157,13 @@ assign set_wait_cominit = state_idle & oob_start & ~cominit_req;
assign set_wait_comwake = state_idle & cominit_req & cominit_allow | state_wait_cominit & rxcominitdet;
assign set_wait_align = state_wait_comwake & rxcomwakedet;
assign set_wait_synp = state_wait_align & detected_alignp;
assign set_wait_linkup = state_wait_synp & detected_synp;
assign set_wait_linkup = state_wait_synp & detected_syncp;
assign set_error = timer_fin & (state_wait_cominit | state_wait_comwake | state_wait_align | state_wait_synp/* | state_wait_linkup*/);
assign clr_wait_cominit = set_wait_comwake | set_error;
assign clr_wait_comwake = set_wait_align | set_error;
assign clr_wait_align = set_wait_synp | set_error;
assign clr_wait_synp = set_wait_linkup | set_error;
assign clr_wait_linkup = state_linkup; //TODO not so important, but still have to trace 3 back-to-back non alignp primitives
assign clr_wait_linkup = state_wait_linkup; //TODO not so important, but still have to trace 3 back-to-back non alignp primitives
assign clr_error = state_error;
// waiting timeout timer
......@@ -179,7 +179,7 @@ assign oob_incompatible = state_wait_align & set_error;
assign oob_done = set_wait_linkup;
// noone responds to cominits
assign oob_silince = set_error & state_wait_cominit;
assign oob_silence = set_error & state_wait_cominit;
// other timeouts
assign oob_error = set_error & ~oob_silence & ~oob_incompatible;
......@@ -207,34 +207,40 @@ assign cominit_req = cominit_req_set | cominit_req_r;
// detect which primitives sends the device after comwake was done
generate
if (DATA_BYTE_WIDTH == 16)
if (DATA_BYTE_WIDTH == 2)
begin
reg detected_alignp_f;
always @ (posedge clk)
detected_alignp_f <= rst | ~state_wait_align ? 1'b0 :
~|(rxdata ^ {8'b01001010, 8'b10111100}) & ~|(rxchaisk ^ 2'b01); // {D10.2, K28.5}
assign detected_alignp = detected_aligp_f & ~|(rxdata ^ {8'b01111011, 8'b01001010}) & ~|(rxchaisk ^ 2'b00); // {D27.3, D10.2}
~|(rxdata ^ {8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 2'b01); // {D10.2, K28.5}
assign detected_alignp = detected_alignp_f & ~|(rxdata ^ {8'b01111011, 8'b01001010}) & ~|(rxcharisk ^ 2'b00); // {D27.3, D10.2}
reg detected_syncp_f;
always @ (posedge clk)
detected_syncp_f <= rst | ~state_wait_sync ? 1'b0 :
~|(rxdata ^ {8'b10010101, 8'b01111100}) & ~|(rxchaisk ^ 2'b01); // {D21.4, K28.3}
assign detected_syncp = detected_syncp_f & ~|(rxdata ^ {8'b10110101, 8'b10110101}) & ~|(rxchaisk ^ 2'b00); // {D21.5, D21.5}
detected_syncp_f <= rst | ~state_wait_synp ? 1'b0 :
~|(rxdata ^ {8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 2'b01); // {D21.4, K28.3}
assign detected_syncp = detected_syncp_f & ~|(rxdata ^ {8'b10110101, 8'b10110101}) & ~|(rxcharisk ^ 2'b00); // {D21.5, D21.5}
end
else
if (DATA_BYTE_WIDTH == 32)
if (DATA_BYTE_WIDTH == 4)
begin
assign detected_alignp = detected_aligp_f & ~|(rxdata ^ {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}) & ~|(rxchaisk ^ 4'h1); // {D27.3, D10.2, D10.2, K28.5}
assign detected_syncp = detected_syncp_f & ~|(rxdata ^ {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}) & ~|(rxchaisk ^ 4'h1); // {D21.5, D21.5, D21.4, K28.3}
assign detected_alignp = ~|(rxdata ^ {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 4'h1); // {D27.3, D10.2, D10.2, K28.5}
assign detected_syncp = ~|(rxdata ^ {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 4'h1); // {D21.5, D21.5, D21.4, K28.3}
end
else
if (DATA_BYTE_WIDTH == 64)
if (DATA_BYTE_WIDTH == 8)
begin
assign detected_alignp = detected_aligp_f & ~|(rxdata ^ {2{8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}}) & ~|(rxchaisk ^ 8'h11); // {D27.3, D10.2, D10.2, K28.5}
assign detected_syncp = detected_syncp_f & ~|(rxdata ^ {2{8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}}) & ~|(rxchaisk ^ 8'h11); // {D21.5, D21.5, D21.4, K28.3}
assign detected_alignp = ~|(rxdata ^ {2{8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}}) & ~|(rxcharisk ^ 8'h11); // {D27.3, D10.2, D10.2, K28.5}
assign detected_syncp = ~|(rxdata ^ {2{8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}}) & ~|(rxcharisk ^ 8'h11); // {D21.5, D21.5, D21.4, K28.3}
end
else
$display("%m oob module works only with 16/32/64 gtx input data width");
begin
always @ (posedge clk)
begin
$display("%m oob module works only with 16/32/64 gtx input data width");
$finish;
end
end
endgenerate
// buf inputs from gtx
......@@ -263,9 +269,9 @@ wire [DATA_BYTE_WIDTH - 1:0] txcharisk_align;
always @ (posedge clk)
begin
txdata <= state_wait_align ? txdata_d102 :
state_wait_sync ? txdata_align : txdata_in;
txchaisk <= state_wait_align ? txcharisk_d102 :
state_wait_sync ? txcharisk_align : txcharisk_in;
state_wait_synp ? txdata_align : txdata_in;
txcharisk <= state_wait_align ? txcharisk_d102 :
state_wait_synp ? txcharisk_align : txcharisk_in;
end
// Continious D10.2 primitive
......@@ -274,30 +280,34 @@ assign txdata_d102 = {DATA_BYTE_WIDTH{8'b01001010}};
// Align primitive: K28.5 + D10.2 + D10.2 + D27.3
generate
if (DATA_BYTE_WIDTH == 16)
if (DATA_BYTE_WIDTH == 2)
begin
reg align_odd;
always @ (posedge clk)
align_odd <= rst | ~state_wait_sync ? 1'b0 : ~align_odd;
align_odd <= rst | ~state_wait_synp ? 1'b0 : ~align_odd;
assign txcharisk_align = align_odd ? 2'b01 : 2'b00;
assign txdata_align = align_odd ? {8'b01001010, 8'b10111100} : // {D10.2, K28.5}
{8'b01111011, 8'b01001010); // {D27.3, D10.2}
{8'b01111011, 8'b01001010}; // {D27.3, D10.2}
end
else
if (DATA_BYTE_WIDTH == 32)
if (DATA_BYTE_WIDTH == 4)
begin
assign txcharisk_align = 4'h1;
assign txdata_align = {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}; // {D27.3, D10.2, D10.2, K28.5}
end
else
if (DATA_BYTE_WIDTH == 64)
if (DATA_BYTE_WIDTH == 8)
begin
assign txcharisk_align = 8'h11;
assign txdata_align = {2{8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}}; // 2x{D27.3, D10.2, D10.2, K28.5}
end
else
$display("%m oob module works only with 16/32/64 gtx input data width");
always @ (posedge clk)
begin
$display("%m oob module works only with 16/32/64 gtx input data width");
$finish;
end
endgenerate
// set data outputs to gtx
......
......@@ -44,17 +44,19 @@ module transport #(
input wire incom_start,
// LL reports of a completion of an incoming frame transmission.
input wire incom_done,
// LL reports of errors in current FIS
input wire incom_invalidate, // TODO
// TL analyzes FIS and returnes if FIS makes sense.
output wire incom_ack_good,
// ... and if it doesn't
output wire incom_ack_bad,
// transmission interrupts
// TL demands to brutally cancel current transaction
// TL demands to brutally cancel current transaction TODO
input wire sync_escape_req,
// acknowlegement of a successful reception
// acknowlegement of a successful reception TODO
output wire sync_escape_ack,
// TL demands to stop current recieving session
// TL demands to stop current recieving session TODO
input wire incom_stop_req,
// controls from a command layer (CL)
......@@ -70,6 +72,7 @@ module transport #(
output wire cmd_done_good,
// request is completed, but device wasn't able to receive
output wire cmd_done_bad,
// shadow registers TODO reduce outputs/inputs count. or not
// actual registers are stored in CL
input wire [31:0] sh_data_in,
......@@ -84,20 +87,44 @@ module transport #(
input wire sh_dir_in,
input wire [63:0] sh_dma_id_in,
input wire [31:0] sh_buf_off_in,
input wire [32:0] sh_dma_cnt_in,
input wire sh_notif_in,
input wire [31:0] sh_tran_cnt_in,
input wire [3:0] sh_port_in,
// TL decodes register writes and sends corresponding issues to CL
output wire [31:0] sh_data_out,
output wire sh_data_val,
output wire [47:0] sh_lba_out,
output wire sh_lba_val,
output wire [15:0] sh_count_out,
output wire [7:0] sh_command_out,
output wire [7:0] sh_err_out,
output wire sh_err_val,
output wire [7:0] sh_status_out,
output wire sh_status_val,
output wire [15:0] sh_count_out,
output wire sh_count_val,
output wire [7:0] sh_estatus_out, // E_Status
output wire [7:0] sh_dev_out,
output wire sh_dev_val,
output wire [3:0] sh_port_out,
output wire sh_inter_out,
output wire sh_dir_out,
output wire [63:0] sh_dma_id_out,
output wire [31:0] sh_dma_off_out,
output wire [31:0] sh_dma_cnt_out,
output wire [15:0] sh_tran_cnt_out, // Transfer Count
output wire sh_notif_out,
output wire sh_autoact_out,
output wire sh_lba_val_out,
output wire sh_count_val_out,
output wire sh_command_val_out,
output wire sh_err_val_out,
output wire sh_status_val_out,
output wire sh_estatus_val_out, // E_Status
output wire sh_dev_val_out,
output wire sh_port_val_out,
output wire sh_inter_val_out,
output wire sh_dir_val_out,
output wire sh_dma_id_val_out,
output wire sh_dma_off_val_out,
output wire sh_dma_cnt_val_out,
output wire sh_tran_cnt_val_out, // Transfer Count
output wire sh_notif_val_out,
output wire sh_autoact_val_out,
// shows if dma activate was received (a pulse)
output wire got_dma_activate,
......@@ -110,6 +137,7 @@ module transport #(
input wire [DATA_BYTE_WIDTH*8 - 1:0] ll_data_in,
input wire [DATA_BYTE_WIDTH/2 - 1:0] ll_data_mask_in,
input wire ll_data_val_in,
input wire ll_data_last_in,
// transport layer tells if its inner buffer is almost full
output wire ll_data_busy_out,
......@@ -128,13 +156,14 @@ module transport #(
output wire [DATA_BYTE_WIDTH*8 - 1:0] cl_data_out,
output wire [DATA_BYTE_WIDTH/2 - 1:0] cl_data_mask_out,
output wire cl_data_val_out,
output wire cl_data_last_out,
// transport layer tells if its inner buffer is almost full
input wire cl_data_busy_in,
// data inputs from CL
input wire [DATA_BYTE_WIDTH*8 - 1:0] cl_data_out,
input wire [DATA_BYTE_WIDTH*8 - 1:0] cl_data_in,
// not implemented yet TODO
input wire [DATA_BYTE_WIDTH*8 - 1:0] cl_data_mask_in,
input wire [DATA_BYTE_WIDTH/2 - 1:0] cl_data_mask_in,
input wire cl_data_last_in,
input wire cl_data_val_in,
output wire cl_data_strobe_out,
......@@ -143,6 +172,8 @@ module transport #(
// watchdog timers calls. They shall be handled in TL, but for debug purposes are wired to the upper level
// when eof acknowledgement is not received after sent FIS
output wire watchdog_eof,
// when too many dwords is in current FIS
output wire watchdog_dwords
);
// How much time does device have to response on EOF
......@@ -152,8 +183,6 @@ parameter [13:0] WATCHDOG_EOF_LIMIT = 14'd1000;
// a) received FIS with incorrect length (seems like an error, so no registers shall be written)
// b) incoming transmission overrides outcoming, so we have to latch outcoming values in real shadow registers
// while storing incoming ones in the local copy
reg [31:0] loc_data;
reg [15:0] loc_feature;
reg [47:0] loc_lba;
reg [15:0] loc_count;
reg [7:0] loc_command;
......@@ -171,6 +200,7 @@ reg [15:0] loc_tran_cnt; // Transfer Count
reg loc_notif;
reg loc_autoact;
// latching cmd inputs
reg [3:0] cmd_port_r;
reg [2:0] cmd_type_r;
......@@ -180,16 +210,14 @@ always @ (posedge clk)
cmd_port_r <= rst ? 4'h0 : cmd_val ? cmd_port : cmd_port_r;
// incomming command type decode, shows which type of FIS shall be issued
localparam CMD_TYPE_REG_DEV = 2'h0; // Reg H2D, bit C -> 0
localparam CMD_TYPE_REG_CMD = 2'h1; // Reg H2D, bit C -> 1
localparam CMD_TYPE_DMA_SETUP = 2'h2;
localparam CMD_TYPE_DATA = 2'h3;
localparam CMD_TYPE_BIST_ACT = 2'h4;
localparam [2:0] CMD_TYPE_REG_DEV = 3'h0; // Reg H2D, bit C -> 0
localparam [2:0] CMD_TYPE_REG_CMD = 3'h1; // Reg H2D, bit C -> 1
localparam [2:0] CMD_TYPE_DMA_SETUP = 3'h2;
localparam [2:0] CMD_TYPE_DATA = 3'h3;
localparam [2:0] CMD_TYPE_BIST_ACT = 3'h4;
// asserts after FIS is sent
reg cmd_done_f;
// count sent dwords within current FIS scope
reg [13:0] dword_cnt;
// current header dword
wire [31:0] ll_header_dword;
// current dword shall be header's
......@@ -197,11 +225,11 @@ wire ll_header_val;
// if last data dword is header's
wire ll_header_last;
// incorrect size or unmatched type of a received FIS
reg bad_fis_rcvd;
// if a FIS has wrong size, make sure it would stop
reg [13:0] err_timer;
// last count condition
wire err_timeout = err_timer == 14'd2049;
reg bad_fis_received;
// if a FIS has wrong size, make sure it would stop, universal dword counter
reg [13:0] dword_cnt;
// FIS dword size exceeded condition
assign watchdog_dwords = dword_cnt == 14'd2049;
// ask for a receiving termination in case of errors
reg incom_stop_req_timeout;
// dma activate is received when its type met and no errors occurs
......@@ -260,13 +288,33 @@ always @ (posedge clk)
if (rst)
begin
state <= STATE_IDLE;
err_timer <= 14'h0;
incom_stop_req_timeout <= 1'b1;
dword_cnt <= 14'h0;
incom_stop_req_timeout <= 1'b0;
bad_fis_received <= 1'b0;
loc_lba <= 48'h0;
loc_count <= 32'h0;
loc_command <= 8'h0;
loc_err <= 8'h0;
loc_status <= 8'h0;
loc_estatus <= 8'h0;
loc_dev <= 8'h0;
loc_port <= 4'h0;
loc_inter <= 1'h0;
loc_dir <= 1'h0;
loc_dma_id <= 64'h0;
loc_dma_off <= 32'h0;
loc_dma_cnt <= 32'h0;
loc_tran_cnt <= 16'h0;
loc_notif <= 1'h0;
loc_autoact <= 1'h0;
end
else
case (state)
STATE_IDLE:
begin
dword_cnt <= 14'h0;
incom_stop_req_timeout <= 1'b0;
bad_fis_received <= 1'b0;
if (frame_req)
state <= STATE_OUTCOMING;
else
......@@ -274,6 +322,23 @@ always @ (posedge clk)
state <= STATE_INCOMING;
else
state <= STATE_IDLE;
loc_lba <= sh_lba_in;
loc_count <= sh_count_in;
loc_command <= sh_command_in;
loc_err <= 8'h0;
loc_status <= 8'h0;
loc_estatus <= 8'h0;
loc_dev <= 8'h0;
loc_port <= sh_port_in;
loc_inter <= sh_inter_in;
loc_dir <= sh_dir_in;
loc_dma_id <= sh_dma_id_in;
loc_dma_off <= sh_buf_off_in;
loc_dma_cnt <= sh_dma_cnt_in;
loc_tran_cnt <= sh_tran_cnt_in;
loc_notif <= sh_notif_in;
loc_autoact <= sh_autoact_in;
end
STATE_INCOMING:
......@@ -292,7 +357,7 @@ always @ (posedge clk)
loc_port <= ll_data_in[11:8];
loc_inter <= ll_data_in[14];
loc_status <= ll_data_in[23:16];
loc_error <= ll_data_in[31:24];
loc_err <= ll_data_in[31:24];
state <= STATE_IN_REG_1;
end
else
......@@ -307,8 +372,10 @@ always @ (posedge clk)
// DMA Activate
begin
if (~ll_data_last_in)
begin
state <= STATE_IN_DMAA_ERR;
err_timer <= 14'h1;
dword_cnt <= 14'h1;
end
else
begin
// got_dma_activate - wire assigment
......@@ -368,7 +435,7 @@ always @ (posedge clk)
loc_dir <= ll_data_in[13];
loc_inter <= ll_data_in[14];
loc_status <= ll_data_in[23:16];
loc_error <= ll_data_in[31:24];
loc_err <= ll_data_in[31:24];
state <= STATE_IN_PIOS_1;
end
else
......@@ -383,12 +450,14 @@ always @ (posedge clk)
// Set Device Bits
begin
if (~ll_data_last_in)
begin
loc_inter <= ll_data_in[14];
loc_notif <= ll_data_in[15];
loc_status[2:0] <= ll_data_in[19:17];
loc_status[6:4] <= ll_data_in[23:21];
loc_error <= ll_data_in[31:24];
loc_err <= ll_data_in[31:24];
state <= STATE_IN_SDB_1;
end
else
// an error state, too little dwords transfered
begin
......@@ -400,7 +469,8 @@ always @ (posedge clk)
default:
// no known FIS type matched
begin
state <= STATE_IN_UNRECOG;
dword_cnt <= 14'h0;
state <= STATE_IN_UNRECOG;
end
endcase
end
......@@ -410,12 +480,12 @@ always @ (posedge clk)
// or if FIS won't start because of incoming transmission. In such case outcoming request parameter shall be latched TODO or not?
begin
dword_cnt <= 14'h0;
state <= frame_rej ? STATE_INCOMING;
frame_ack & cmd_type_r == CMD_TYPE_REG_DEV ? STATE_OUT_REG_0 :
frame_ack & cmd_type_r == CMD_TYPE_REG_CMD ? STATE_OUT_REG_0 :
frame_ack & cmd_type_r == CMD_TYPE_DMA_SETUP ? STATE_OUT_DMAS_0 :
frame_ack & cmd_type_r == CMD_TYPE_DATA ? STATE_OUT_DATA_0 :
frame_ack & cmd_type_r == CMD_TYPE_BIST_ACT ? STATE_OUT_BIST_0 :
state <= frame_rej ? STATE_INCOMING :
frame_ack & cmd_type_r == CMD_TYPE_REG_DEV ? STATE_OUT_REG :
frame_ack & cmd_type_r == CMD_TYPE_REG_CMD ? STATE_OUT_REG :
frame_ack & cmd_type_r == CMD_TYPE_DMA_SETUP ? STATE_OUT_DMAS :
frame_ack & cmd_type_r == CMD_TYPE_DATA ? STATE_OUT_DATA_H :
frame_ack & cmd_type_r == CMD_TYPE_BIST_ACT ? STATE_OUT_BIST :
STATE_OUTCOMING;
end
......@@ -423,7 +493,7 @@ always @ (posedge clk)
// receiving data from Data FIS, bypass it into buffer at upper level
begin
if (incom_done)
// EOF received
// EOF received, CRC good
begin
state <= STATE_IDLE;
end
......@@ -459,7 +529,7 @@ always @ (posedge clk)
loc_lba[23:16] <= ll_data_in[15:8];
loc_lba[39:32] <= ll_data_in[23:16];
loc_dev[7:0] <= ll_data_in[31:24];
state <= STATE_IN_REG_2:
state <= STATE_IN_REG_2;
end
end
......@@ -471,7 +541,7 @@ always @ (posedge clk)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
STATE_IDLE <= STATE_IDLE;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Reserved, LBA High (exp), LBA Mid (exp), LBA Low (exp)}
......@@ -491,7 +561,7 @@ always @ (posedge clk)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IN_IDLE;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Reserved, Reserved, Sector Count (exp), Sector Count}
......@@ -508,13 +578,13 @@ always @ (posedge clk)
if (ll_data_last_in)
// correct frame size, finishing
begin
state <= STATE_IN_IDLE;
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_REG_ERR;
err_timer <= 14'h4;
dword_cnt <= 14'h4;
end
end
......@@ -530,14 +600,14 @@ always @ (posedge clk)
end
else
begin
if (err_timeout)
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
err_timer <= err_timer + 1'b1;
dword_cnt <= dword_cnt + 1'b1;
end
end
......@@ -553,14 +623,14 @@ always @ (posedge clk)
end
else
begin
if (err_timeout)
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
err_timer <= err_timer + 1'b1;
dword_cnt <= dword_cnt + 1'b1;
end
end
......@@ -595,8 +665,8 @@ always @ (posedge clk)
else
// going to the next dword, parse current one: DMA Buffer Id High
begin
loc_lba[63:32] <= ll_data_in[31:0];
state <= STATE_IN_DMAS_3;
loc_dma_id[63:32] <= ll_data_in[31:0];
state <= STATE_IN_DMAS_3;
end
end
......@@ -608,7 +678,7 @@ always @ (posedge clk)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
STATE_IDLE <= STATE_IDLE;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: Reserved
......@@ -625,7 +695,7 @@ always @ (posedge clk)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
STATE_IDLE <= STATE_IDLE;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: DMA Buffer Offset
......@@ -643,7 +713,7 @@ always @ (posedge clk)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
STATE_IDLE <= STATE_IDLE;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: DMA Transfer Count
......@@ -660,13 +730,13 @@ always @ (posedge clk)
if (ll_data_last_in)
// correct frame size, finishing, current dword: Reserved
begin
state <= STATE_IN_IDLE;
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_DMAS_ERR;
err_timer <= 14'h6;
dword_cnt <= 14'h6;
end
end
......@@ -682,14 +752,14 @@ always @ (posedge clk)
end
else
begin
if (err_timeout)
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
err_timer <= err_timer + 1'b1;
dword_cnt <= dword_cnt + 1'b1;
end
end
......@@ -701,7 +771,7 @@ always @ (posedge clk)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
STATE_IDLE <= STATE_IDLE;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: TODO
......@@ -717,13 +787,13 @@ always @ (posedge clk)
if (ll_data_last_in)
// correct frame size, finishing, current dword: Reserved
begin
state <= STATE_IN_IDLE;
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_BIST_ERR;
err_timer <= 14'h2;
dword_cnt <= 14'h2;
end
end
......@@ -739,14 +809,14 @@ always @ (posedge clk)
end
else
begin
if (err_timeout)
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
err_timer <= err_timer + 1'b1;
dword_cnt <= dword_cnt + 1'b1;
end
end
......@@ -758,7 +828,7 @@ always @ (posedge clk)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
STATE_IDLE <= STATE_IDLE;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Device, LBA High, LBA Mid, LBA Low}
......@@ -766,7 +836,7 @@ always @ (posedge clk)
loc_lba[7:0] <= ll_data_in[7:0];
loc_lba[23:16] <= ll_data_in[15:8];
loc_lba[39:32] <= ll_data_in[23:16];
loc_device <= ll_data_in[31:24];
loc_dev <= ll_data_in[31:24];
state <= STATE_IN_PIOS_2;
end
end
......@@ -775,20 +845,20 @@ always @ (posedge clk)
// receiving PIO Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
STATE_IDLE <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Reserved, LBA High (exp), LBA Mid (exp), LBA Low (exp)}
begin
loc_lba[15:8] <= ll_data_in[7:0];
loc_lba[31:24] <= ll_data_in[15:8];
loc_lba[47:40] <= ll_data_in[23:16];
state <= STATE_IN_PIOS_3;
end
if (ll_data_last_in)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {Reserved, LBA High (exp), LBA Mid (exp), LBA Low (exp)}
begin
loc_lba[15:8] <= ll_data_in[7:0];
loc_lba[31:24] <= ll_data_in[15:8];
loc_lba[47:40] <= ll_data_in[23:16];
state <= STATE_IN_PIOS_3;
end
end
STATE_IN_PIOS_3:
......@@ -799,7 +869,7 @@ always @ (posedge clk)
// incorrect frame size
begin
bad_fis_received <= 1'b1;
STATE_IDLE <= STATE_IDLE;
state <= STATE_IDLE;
end
else
// going to the next dword, parse current one: {E_Status, Reserved, Sector Count (exp), Sector Count}
......@@ -810,21 +880,21 @@ always @ (posedge clk)
end
end
STATE_IN_BIST_4:
// receiving BIST FIS, dword by dword
STATE_IN_PIOS_4:
// receiving PIO Setup FIS, dword by dword
begin
if (ll_data_val_in)
if (ll_data_last_in)
// correct frame size, finishing, current dword: {Reserved, Transfer Count}
begin
loc_tran_cnt <= ll_data_in[15:0];
state <= STATE_IN_IDLE;
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_BIST_ERR;
err_timer <= 14'h4;
dword_cnt <= 14'h4;
end
end
......@@ -840,14 +910,14 @@ always @ (posedge clk)
end
else
begin
if (err_timeout)
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
err_timer <= err_timer + 1'b1;
dword_cnt <= dword_cnt + 1'b1;
end
end
......@@ -858,13 +928,13 @@ always @ (posedge clk)
if (ll_data_last_in)
// correct frame size, finishing, current dword: Reserved
begin
state <= STATE_IN_IDLE;
state <= STATE_IDLE;
end
else
// incorrect frame size
begin
state <= STATE_IN_SDB_ERR;
err_timer <= 14'h1;
dword_cnt <= 14'h1;
end
end
......@@ -880,14 +950,14 @@ always @ (posedge clk)
end
else
begin
if (err_timeout)
if (watchdog_dwords)
// if for some reason FIS continue transferring for too long, terminate it
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
err_timer <= err_timer + 1'b1;
dword_cnt <= dword_cnt + 1'b1;
end
end
......@@ -907,9 +977,11 @@ always @ (posedge clk)
if (ll_data_strobe_in)
begin
if (cl_data_last_in)
begin
// All data is transmitted
dword_cnt <= 14'h0;
state <= STATE_OUT_WAIT_RESP;
end
else
if (dword_cnt == 2048)
// data_limit_exceed - wire assigned
......@@ -928,8 +1000,10 @@ always @ (posedge clk)
if (ll_data_strobe_in)
// 5 header dwords, then wait for a reception on a device side
if (dword_cnt[2:0] == 3'h4)
begin
dword_cnt <= 14'h0;
state <= STATE_OUT_WAIT_RESP;
end
else
begin
state <= STATE_OUT_REG;
......@@ -943,8 +1017,10 @@ always @ (posedge clk)
if (ll_data_strobe_in)
// 7 header dwords, then wait for a reception on a device side
if (dword_cnt[2:0] == 3'h6)
begin
dword_cnt <= 14'h0;
state <= STATE_OUT_WAIT_RESP;
end
else
begin
state <= STATE_OUT_DMAS;
......@@ -957,8 +1033,10 @@ always @ (posedge clk)
if (ll_data_strobe_in)
// 3 header dwords, then wait for a reception on a device side
if (dword_cnt[2:0] == 3'h2)
begin
dword_cnt <= 14'h0;
state <= STATE_OUT_WAIT_RESP;
end
else
begin
state <= STATE_OUT_BIST;
......@@ -983,6 +1061,7 @@ always @ (posedge clk)
// watchdog_eof wire assigned
// for now while debugging let it be indicated on higher level TODO Choose exception. May be send incom stop req.
// Be aware of no response for that. In such case go for rst for ll. Or better make link_reset -> 1. And dont forget for oob
end
else
begin
dword_cnt <= dword_cnt + 1'b1;
......@@ -992,6 +1071,22 @@ always @ (posedge clk)
STATE_IN_UNRECOG:
begin
if (incom_done | incom_invalidate)
// transmission complete
// incom_ack_bad wire assigned
state <= STATE_IDLE;
else
if (watchdog_dwords)
begin
state <= STATE_IDLE;
incom_stop_req_timeout <= 1'b1;
end
else
begin
dword_cnt <= dword_cnt + 1'b1;
state <= STATE_IN_UNRECOG;
end
end
default:
......@@ -999,10 +1094,25 @@ always @ (posedge clk)
end
endcase
// buys circuit
assign cmd_busy = |state | frame_busy;
// respond if received FIS had any meaning in terms of TL
// actual response shall come next tick after done signal to fit LL fsm
reg incom_done_r;
always @ (posedge clk)
incom_done_r <= incom_done;
assign incom_ack_bad = state == STATE_IN_UNRECOG & incom_done_r | bad_fis_received;
assign incom_ack_good = incom_done_r & ~incom_ack_bad;
// after a device says it received the FIS, reveal the error code
assign cmd_done_good = state == STATE_OUT_WAIT_RESP & frame_done_good;
assign cmd_done_bad = state == STATE_OUT_WAIT_RESP & frame_done_bad;
// Reg H2D FIS header
wire [31:0] header_regfis;
assign header_regfis = dword_cnt[2:0] == 3'h0 ? {sh_feature_in[7:0], sh_command_in, cmd_type_r == CMD_TYPE_REG_CMD, 3'h0, cmd_port_r, 8'h27} : // features command C R R R PMPort FISType
dword_cnt[2:0] == 3'h1 ? {sh_dev_in, sh_lba_in[39:32], sh_lba_in[23:16], sh_lba_in[7:0] : // Device LBAHigh LBAMid LBALow
dword_cnt[2:0] == 3'h1 ? {sh_dev_in, sh_lba_in[39:32], sh_lba_in[23:16], sh_lba_in[7:0]} : // Device LBAHigh LBAMid LBALow
dword_cnt[2:0] == 3'h2 ? {sh_feature_in[15:8], sh_lba_in[47:40], sh_lba_in[31:24], sh_lba_in[15:8]} : // Features (exp) LBAHigh (exp) LBAMid (exp) LBALow (exp)
dword_cnt[2:0] == 3'h3 ? {sh_control_in[7:0], 8'h00, sh_count_in[15:0]} : // Control Reserved SectorCount (exp) SectorCount
/*dword_cnt[2:0] == 3'h4 ?*/ {32'h0000}; // Reserved
......@@ -1012,7 +1122,7 @@ assign header_dmas = dword_cnt[3:0] == 3'h0 ? {8'h0, 8'h0, sh_autoact_in,
dword_cnt[3:0] == 3'h1 ? {sh_dma_id_in[31:0]} : // DMA Buffer Identifier Low
dword_cnt[3:0] == 3'h2 ? {sh_dma_id_in[63:32]} : // DMA Buffer Identifier High
dword_cnt[3:0] == 3'h4 ? {sh_buf_off_in[31:0]} : // DMA Buffer Offset
dword_cnt[3:0] == 3'h5 ? {sh_tran_cnt[31:0]} : // DMA Transfer Count
dword_cnt[3:0] == 3'h5 ? {sh_tran_cnt_in[31:0]} : // DMA Transfer Count
/* 3'h3 | 3'h6 */ {32'h0000}; // Reserved
// BIST Activate FIS header
wire [31:0] header_bist; // TODO
......@@ -1036,11 +1146,12 @@ assign ll_header_dword = {32{state == STATE_OUT_REG}} & header_regfis |
// bypass data from ll to cl if it's data stage in data FIS
assign cl_data_val_out = ll_data_val_in & state == STATE_IN_DATA;
assign cl_data_last_out = ll_data_val_in & ll_data_last_in & state == STATE_IN_DATA;
assign cl_data_mask_out = ll_data_mask_in;
assign cl_data_out = ll_data_in & {32{cl_data_val_out}};
// set data to ll: bypass payload from cl or headers constructed in here
assign ll_data_val = ll_header_val | cl_data_val_in;
assign ll_data_val_out = ll_header_val | cl_data_val_in;
assign ll_data_last_out = ll_header_last & ll_header_val | cl_data_last_in & ~ll_header_val;
assign ll_data_out = ll_header_dword & {32{ll_header_val}} | cl_data_in & {32{~ll_header_val}};
assign ll_data_mask_out = {2{ll_header_val}} | cl_data_mask_in & {2{~ll_header_val}};
......@@ -1052,6 +1163,44 @@ assign data_limit_exceeded = dword_cnt == 14'd2048 & ~cl_data_last_in;
wire chk_strobe_while_waitresp;
assign chk_strobe_while_waitresp = state == STATE_OUT_WAIT_RESP & ll_data_strobe_in;
// update shadow registers as soon as transaction finishes TODO invalidate in case of errors
// TODO update only corresponding fields, which was updated during the transmission
assign sh_lba_out = loc_lba;
assign sh_count_out = loc_count;
assign sh_command_out = loc_command;
assign sh_err_out = loc_err;
assign sh_status_out = loc_status;
assign sh_estatus_out = loc_estatus;
assign sh_dev_out = loc_dev;
assign sh_port_out = loc_port;
assign sh_inter_out = loc_inter;
assign sh_dir_out = loc_dir;
assign sh_dma_id_out = loc_dma_id;
assign sh_dma_off_out = loc_dma_off;
assign sh_dma_cnt_out = loc_dma_cnt;
assign sh_tran_cnt_out = loc_tran_cnt;
assign sh_notif_out = loc_notif;
assign sh_autoact_out = loc_autoact;
assign sh_lba_val_out = ll_data_last_in;
assign sh_count_val_out = ll_data_last_in;
assign sh_command_val_out = ll_data_last_in;
assign sh_err_val_out = ll_data_last_in;
assign sh_status_val_out = ll_data_last_in;
assign sh_estatus_val_out = ll_data_last_in;
assign sh_dev_val_out = ll_data_last_in;
assign sh_port_val_out = ll_data_last_in;
assign sh_inter_val_out = ll_data_last_in;
assign sh_dir_val_out = ll_data_last_in;
assign sh_dma_id_val_out = ll_data_last_in;
assign sh_dma_off_val_out = ll_data_last_in;
assign sh_dma_cnt_val_out = ll_data_last_in;
assign sh_tran_cnt_val_out = ll_data_last_in;
assign sh_notif_val_out = ll_data_last_in;
assign sh_autoact_val_out = ll_data_last_in;
`ifdef CHECKERS_ENABLED
always @ (posedge clk)
if (~rst)
......@@ -1073,7 +1222,17 @@ always @ (posedge clk)
$stop;
end
`endif
assign chk_inc_dword_limit_exceeded = state = STATE_IN_DATA & dword_cnt == 14'd2049;
`ifdef CHECKERS_ENABLED
always @ (posedge clk)
if (~rst)
if (watchdog_dwords)
begin
$display("ERROR in %m: state %h - current FIS contains more than 2048 dwords", state);
$finish;
end
`endif
wire chk_inc_dword_limit_exceeded;
assign chk_inc_dword_limit_exceeded = state == STATE_IN_DATA & dword_cnt == 14'd2049;
`ifdef CHECKERS_ENABLED
always @ (posedge clk)
if (~rst)
......
......@@ -22,6 +22,7 @@
* For now assuming the actual rtl would be Ashwin's
*/
module sata_host(
// TODO trim these old interfaces
// command, control and status
output wire ready_for_cmd,
input wire new_cmd,
......@@ -54,43 +55,626 @@ module sata_host(
output wire plllkdet,
output wire dcmlocked
);/*
assign ready_for_cmd = 1'b0;
assign sata_core_full = 1'b0;
assign sata_dout = 32'b0;
assign sata_core_empty = 1'b0;
assign sata_timer = 1'b0;
assign linkup = 1'b0;
assign txp_out = 1'b0;
assign txn_out = 1'b0;
assign plllkdet = 1'b0;
assign dcmlocked = 1'b0;*/
sata_core sata_core(
.ready_for_cmd (ready_for_cmd),
.new_cmd (new_cmd),
.cmd_type (cmd_type),
.sector_count (sector_count),
.sector_addr (sector_addr),
.sata_din (sata_din),
.sata_din_we (sata_din_we),
.sata_core_full (sata_core_full),
.sata_dout (sata_dout),
.sata_dout_re (sata_dout_re),
.sata_core_empty (sata_core_empty),
.SATA_USER_DATA_CLK_IN (data_clk_in),
.SATA_USER_DATA_CLK_OUT (data_clk_out),
.sata_timer (sata_timer),
.CLKIN_150 (clkin_150),
.reset (reset),
.LINKUP (linkup),
.TXP0_OUT (txp_out),
.TXN0_OUT (txn_out),
.RXP0_IN (rxp_in),
.RXN0_IN (rxn_in),
.PLLLKDET_OUT_N (plllkdet),
.DCMLOCKED_OUT (dcmlocked)
// end of old ifaces
// temporary
input wire [31:0] al_cmd_in; // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good; cmd_busy}
input wire al_cmd_val_in;
input wire [31:0] al_cmd_out; // same
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
input wire [31:0] al_sh_data_in, // write data
input wire al_sh_data_val_in, // write strobe
input wire al_sh_data_strobe_in, // read strobe
input wire [15:0] al_sh_feature_in,
input wire al_sh_feature_val_in,
input wire [23:0] al_sh_lba_lo_in,
input wire al_sh_lba_lo_val_in,
input wire [23:0] al_sh_lba_hi_in,
input wire al_sh_lba_hi_val_in,
input wire [15:0] al_sh_count_in,
input wire al_sh_count_val_in,
input wire [7:0] al_sh_command_in,
input wire al_sh_command_val_in,
input wire [7:0] al_sh_dev_in,
input wire al_sh_dev_val_in,
input wire [7:0] al_sh_control_in,
input wire al_sh_control_val_in,
input wire [31:0] al_sh_dma_id_lo_in
input wire al_sh_dma_id_lo_val_in,
input wire [31:0] al_sh_dma_id_hi_in,
input wire al_sh_dma_id_hi_val_in,
input wire [31:0] al_sh_buf_off_in,
input wire al_sh_buf_off_val_in,
input wire [31:0] al_sh_tran_cnt_in,
input wire al_sh_tran_cnt_val_in,
input wire al_sh_autoact_in,
input wire al_sh_autoact_val_in,
input wire al_sh_inter_in,
input wire al_sh_inter_val_in,
input wire al_sh_dir_in,
input wire al_sh_dir_val_in,
input wire [31:0] al_sh_dma_cnt_in,
input wire al_sh_dma_cnt_val_in,
input wire al_sh_notif_in,
input wire al_sh_notif_val_in,
input wire [3:0] al_sh_port_in,
input wire al_sh_port_val_in,
);
wire rst;
// sata clk
wire clk;
// tl cmd iface
wire [2:0] cl2tl_cmd_type;
wire cl2tl_cmd_val;
wire [3:0] cl2tl_cmd_port;
wire cl2tl_cmd_busy;
wire cl2tl_cmd_done_good;
wire cl2tl_cmd_done_bad;
// data from tl
wire [31:0] tl2cl_data;
wire tl2cl_data_val;
wire tl2cl_data_last;
wire tl2cl_data_busy;
// to tl
wire [31:0] cl2tl_data;
wire cl2tl_data_last;
wire cl2tl_data_val;
wire cl2tl_data_strobe;
// from tl
wire [47:0] tl2cl_sh_lba_in;
wire [15:0] tl2cl_sh_count_in;
wire [7:0] tl2cl_sh_command_in;
wire [7:0] tl2cl_sh_err_in;
wire [7:0] tl2cl_sh_status_in;
wire [7:0] tl2cl_sh_estatus_in; // E_Status
wire [7:0] tl2cl_sh_dev_in;
wire [3:0] tl2cl_sh_port_in;
wire tl2cl_sh_inter_in;
wire tl2cl_sh_dir_in;
wire [63:0] tl2cl_sh_dma_id_in;
wire [31:0] tl2cl_sh_dma_off_in;
wire [31:0] tl2cl_sh_dma_cnt_in;
wire [15:0] tl2cl_sh_tran_cnt_in; // Transfer Count
wire tl2cl_sh_notif_in;
wire tl2cl_sh_autoact_in;
wire tl2cl_sh_lba_val_in;
wire tl2cl_sh_count_val_in;
wire tl2cl_sh_command_val_in;
wire tl2cl_sh_err_val_in;
wire tl2cl_sh_status_val_in;
wire tl2cl_sh_estatus_val_in; // E_Status
wire tl2cl_sh_dev_val_in;
wire tl2cl_sh_port_val_in;
wire tl2cl_sh_inter_val_in;
wire tl2cl_sh_dir_val_in;
wire tl2cl_sh_dma_id_val_in;
wire tl2cl_sh_dma_off_val_in;
wire tl2cl_sh_dma_cnt_val_in;
wire tl2cl_sh_tran_cnt_val_in; // Transfer Count
wire tl2cl_sh_notif_val_in;
wire tl2cl_sh_autoact_val_in;
// all regs to output
wire sh_data_val;
wire [31:0] sh_data;
wire [7:0] sh_control;
wire [15:0] sh_feature;
wire [47:0] sh_lba;
wire [15:0] sh_count;
wire [7:0] sh_command;
wire [7:0] sh_err;
wire [7:0] sh_status;
wire [7:0] sh_estatus; // E_Status
wire [7:0] sh_dev;
wire [3:0] sh_port;
wire sh_inter;
wire sh_dir;
wire [63:0] sh_dma_id;
wire [31:0] sh_dma_off;
wire [31:0] sh_dma_cnt;
wire [15:0] sh_tran_cnt; // Transfer Count
wire sh_notif;
wire sh_autoact;
command command(
.rst (rst),
.clk (clk),
// tl cmd iface
.cmd_type (cl2tl_cmd_type),
.cmd_val (cl2tl_cmd_val),
.cmd_port (cl2tl_cmd_port),
.cmd_busy (cl2tl_cmd_busy),
.cmd_done_good (cl2tl_cmd_done_good),
.cmd_done_bad (cl2tl_cmd_done_bad),
// temporary TODO
.al_cmd_in (al_cmd_in), // == {cmd_type, cmd_port, cmd_val, cmd_done_bad, cmd_done_good, cmd_busy}
.al_cmd_val_in (al_cmd_val_in),
.al_cmd_out (al_cmd_out), // same
// data from tl
.tl_data_in (tl2cl_data),
.tl_data_val_in (tl2tl_data_val),
.tl_data_last_in (tl2tl_data_last),
.tl_data_busy_out (tl2tl_data_busy),
// to tl
.tl_data_out (cl2tl_data),
.tl_data_last_out (cl2tl_data_last),
.tl_data_val_out (cl2tl_data_val),
.tl_data_strobe_in (cl2tl_data_strobe),
// tmp inputs directly from registers for each and every shadow register and control bit
// from al
.al_sh_data_in (al_sh_data_in), // write data
.al_sh_data_val_in (al_sh_data_val_in), // write strobe
.al_sh_data_strobe_in (al_sh_data_strobe_in), // read strobe
.al_sh_feature_in (al_sh_feature_in),
.al_sh_feature_val_in (al_sh_feature_val_in),
.al_sh_lba_lo_in (al_sh_lba_lo_in),
.al_sh_lba_lo_val_in (al_sh_lba_lo_val_in),
.al_sh_lba_hi_in (al_sh_lba_hi_in),
.al_sh_lba_hi_val_in (al_sh_lba_hi_val_in),
.al_sh_count_in (al_sh_count_in),
.al_sh_count_val_in (al_sh_count_val_in),
.al_sh_command_in (al_sh_command_in),
.al_sh_command_val_in (al_sh_command_val_in),
.al_sh_dev_in (al_sh_dev_in),
.al_sh_dev_val_in (al_sh_dev_val_in),
.al_sh_control_in (al_sh_control_in),
.al_sh_control_val_in (al_sh_control_val_in),
.al_sh_dma_id_lo_in (al_sh_dma_id_lo_in),
.al_sh_dma_id_lo_val_in (al_sh_dma_id_lo_val_in),
.al_sh_dma_id_hi_in (al_sh_dma_id_hi_in),
.al_sh_dma_id_hi_val_in (al_sh_dma_id_hi_val_in),
.al_sh_buf_off_in (al_sh_buf_off_in),
.al_sh_buf_off_val_in (al_sh_buf_off_val_in),
.al_sh_tran_cnt_in (al_sh_tran_cnt_in),
.al_sh_tran_cnt_val_in (al_sh_tran_cnt_val_in),
.al_sh_autoact_in (al_sh_autoact_in),
.al_sh_autoact_val_in (al_sh_autoact_val_in),
.al_sh_inter_in (al_sh_inter_in),
.al_sh_inter_val_in (al_sh_inter_val_in),
.al_sh_dir_in (al_sh_dir_in),
.al_sh_dir_val_in (al_sh_dir_val_in),
.al_sh_dma_cnt_in (al_sh_dma_cnt_in),
.al_sh_dma_cnt_val_in (al_sh_dma_cnt_val_in),
.al_sh_notif_in (al_sh_notif_in),
.al_sh_notif_val_in (al_sh_notif_val_in),
.al_sh_port_in (al_sh_port_in),
.al_sh_port_val_in (al_sh_port_val_in),
// from tl
.tl_sh_lba_in (tl_sh_lba_in),
.tl_sh_count_in (tl_sh_count_in),
.tl_sh_command_in (tl_sh_command_in),
.tl_sh_err_in (tl_sh_err_in),
.tl_sh_status_in (tl_sh_status_in),
.tl_sh_estatus_in (tl_sh_estatus_in), // E_Status
.tl_sh_dev_in (tl_sh_dev_in),
.tl_sh_port_in (tl_sh_port_in),
.tl_sh_inter_in (tl_sh_inter_in),
.tl_sh_dir_in (tl_sh_dir_in),
.tl_sh_dma_id_in (tl_sh_dma_id_in),
.tl_sh_dma_off_in (tl_sh_dma_off_in),
.tl_sh_dma_cnt_in (tl_sh_dma_cnt_in),
.tl_sh_tran_cnt_in (tl_sh_tran_cnt_in), // Transfer Count
.tl_sh_notif_in (tl_sh_notif_in),
.tl_sh_autoact_in (tl_sh_autoact_in),
.tl_sh_lba_val_in (tl_sh_lba_val_in),
.tl_sh_count_val_in (tl_sh_count_val_in),
.tl_sh_command_val_in (tl_sh_command_val_in),
.tl_sh_err_val_in (tl_sh_err_val_in),
.tl_sh_status_val_in (tl_sh_status_val_in),
.tl_sh_estatus_val_in (tl_sh_estatus_val_in), // E_Status
.tl_sh_dev_val_in (tl_sh_dev_val_in),
.tl_sh_port_val_in (tl_sh_port_val_in),
.tl_sh_inter_val_in (tl_sh_inter_val_in),
.tl_sh_dir_val_in (tl_sh_dir_val_in),
.tl_sh_dma_id_val_in (tl_sh_dma_id_val_in),
.tl_sh_dma_off_val_in (tl_sh_dma_off_val_in),
.tl_sh_dma_cnt_val_in (tl_sh_dma_cnt_val_in),
.tl_sh_tran_cnt_val_in (tl_sh_tran_cnt_val_in), // Transfer Count
.tl_sh_notif_val_in (tl_sh_notif_val_in),
.tl_sh_autoact_val_in (tl_sh_autoact_val_in),
// all regs to output
.sh_data_val_out (sh_data_val_out),
.sh_data_out (sh_data_out),
.sh_control_out (sh_control_out),
.sh_feature_out (sh_feature_out),
.sh_lba_out (sh_lba_out),
.sh_count_out (sh_count_out),
.sh_command_out (sh_command_out),
.sh_err_out (sh_err_out),
.sh_status_out (sh_status_out),
.sh_estatus_out (sh_estatus_out), // E_Status
.sh_dev_out (sh_dev_out),
.sh_port_out (sh_port_out),
.sh_inter_out (sh_inter_out),
.sh_dir_out (sh_dir_out),
.sh_dma_id_out (sh_dma_id_out),
.sh_dma_off_out (sh_dma_off_out),
.sh_dma_cnt_out (sh_dma_cnt_out),
.sh_tran_cnt_out (sh_tran_cnt_out), // Transfer Count
.sh_notif_out (sh_notif_out),
.sh_autoact_out (sh_autoact_out)
);
// issue a frame
wire frame_req;
// frame started to be transmitted
wire frame_ack;
// frame issue was rejected because of incoming frame with higher priority
wire frame_rej;
// LL is not ready to receive a frame request. frame_req shall be low if busy is asserted
wire frame_busy;
// frame was transmitted w/o probles and successfully received @ a device side
wire frame_done_good;
// frame was transmitted, but device messages of problems with receiving
wire frame_done_bad;
// LL reports of an incoming frame transmission. They're always allowed and have the highest priority
wire incom_start;
// LL reports of a completion of an incoming frame transmission.
wire incom_done;
// LL reports of errors in current FIS
wire incom_invalidate; // TODO
// TL analyzes FIS and returnes if FIS makes sense.
wire incom_ack_good;
// ... and if it doesn't
wire incom_ack_bad;
// transmission interrupts
// TL demands to brutally cancel current transaction TODO
wire sync_escape_req;
// acknowlegement of a successful reception TODO
wire sync_escape_ack;
// TL demands to stop current recieving session TODO
wire incom_stop_req;
// shows if dma activate was received (a pulse)
wire got_dma_activate;
wire [3:0] got_dma_activate_port;
// if CL made a mistake in controlling data FIS length
wire data_limit_exceeded;
// LL data
// data inputs from LL
wire [DATA_BYTE_WIDTH*8 - 1:0] ll_data_in;
wire [DATA_BYTE_WIDTH/2 - 1:0] ll_data_mask_in;
wire ll_data_val_in;
wire ll_data_last_in;
// transport layer tells if its inner buffer is almost full
wire ll_data_busy_out;
// data outputs to LL
wire [DATA_BYTE_WIDTH*8 - 1:0] ll_data_out;
// not implemented yet TODO
wire [DATA_BYTE_WIDTH*8 - 1:0] ll_data_mask_out;
wire ll_data_last_out;
wire ll_data_val_out;
wire ll_data_strobe_in;
// watchdog timers calls. They shall be handled in TL, but for debug purposes are wired to the upper level
// when eof acknowledgement is not received after sent FIS
wire watchdog_eof;
// when too many dwords is in current FIS
wire watchdog_dwords;
transport transport(
.clk (clk),
.rst (rst),
// link layer (LL) control
// issue a frame
.frame_req (frame_req),
// frame started to be transmitted
.frame_ack (frame_ack),
// frame issue was rejected because of incoming frame with higher priority
.frame_rej (frame_rej),
// LL is not ready to receive a frame request. frame_req shall be low if busy is asserted
.frame_busy (frame_busy),
// frame was transmitted w/o probles and successfully received @ a device side
.frame_done_good (frame_done_good),
// frame was transmitted, but device messages of problems with receiving
.frame_done_bad (frame_done_bad),
// LL reports of an incoming frame transmission. They're always allowed and have the highest priority
.incom_start (incom_start),
// LL reports of a completion of an incoming frame transmission.
.incom_done (incom_done),
// LL reports of errors in current FIS
.incom_invalidate (incom_invalidate), // TODO
// TL analyzes FIS and returnes if FIS makes sense.
.incom_ack_good (incom_ack_good),
// ... and if it doesn't
.incom_ack_bad (incom_ack_bad),
// transmission interrupts
// TL demands to brutally cancel current transaction TODO
.sync_escape_req (sync_escape_req),
// acknowlegement of a successful reception TODO
.sync_escape_ack (sync_escape_ack),
// TL demands to stop current recieving session TODO
.incom_stop_req (incom_stop_req),
// controls from a command layer (CL)
// FIS type, ordered by CL
.cmd_type (cl2tl_cmd_type),
// request itself
.cmd_val (cl2tl_cmd_val),
// destination port
.cmd_port (cl2tl_cmd_port),
// if cmd got into processing, busy asserts, when TL is ready to receive a new cmd, busy deasserts
.cmd_busy (cl2tl_cmd_busy),
// indicates completion of a request
.cmd_done_good (cl2tl_cmd_done_good),
// request is completed, but device wasn't able to receive
.cmd_done_bad (cl2tl_cmd_done_bad),
// shadow registers TODO reduce outputs/inputs count. or not
// actual registers are stored in CL
.sh_data_in (sh_data),
.sh_feature_in (sh_feature),
.sh_lba_in (sh_lba),
.sh_count_in (sh_count),
.sh_command_in (sh_command),
.sh_dev_in (sh_dev),
.sh_control_in (sh_control),
.sh_autoact_in (sh_autoact),
.sh_inter_in (sh_inter),
.sh_dir_in (sh_dir),
.sh_dma_id_in (sh_dma_id),
.sh_buf_off_in (sh_buf_off),
.sh_dma_cnt_in (sh_dma_cnt),
.sh_notif_in (sh_notif),
.sh_tran_cnt_in (sh_tran_cnt),
.sh_port_in (sh_port),
// TL decodes register writes and sends corresponding issues to CL
.sh_lba_out (tl2cl_sh_lba_out),
.sh_count_out (tl2cl_sh_count_out),
.sh_command_out (tl2cl_sh_command_out),
.sh_err_out (tl2cl_sh_err_out),
.sh_status_out (tl2cl_sh_status_out),
.sh_estatus_out (tl2cl_sh_estatus_out), // E_Status
.sh_dev_out (tl2cl_sh_dev_out),
.sh_port_out (tl2cl_sh_port_out),
.sh_inter_out (tl2cl_sh_inter_out),
.sh_dir_out (tl2cl_sh_dir_out),
.sh_dma_id_out (tl2cl_sh_dma_id_out),
.sh_dma_off_out (tl2cl_sh_dma_off_out),
.sh_dma_cnt_out (tl2cl_sh_dma_cnt_out),
.sh_tran_cnt_out (tl2cl_sh_tran_cnt_out), // Transfer Count
.sh_notif_out (tl2cl_sh_notif_out),
.sh_autoact_out (tl2cl_sh_autoact_out),
.sh_lba_val_out (tl2cl_sh_lba_val_out),
.sh_count_val_out (tl2cl_sh_count_val_out),
.sh_command_val_out (tl2cl_sh_command_val_out),
.sh_err_val_out (tl2cl_sh_err_val_out),
.sh_status_val_out (tl2cl_sh_status_val_out),
.sh_estatus_val_out (tl2cl_sh_estatus_val_out), // E_Status
.sh_dev_val_out (tl2cl_sh_dev_val_out),
.sh_port_val_out (tl2cl_sh_port_val_out),
.sh_inter_val_out (tl2cl_sh_inter_val_out),
.sh_dir_val_out (tl2cl_sh_dir_val_out),
.sh_dma_id_val_out (tl2cl_sh_dma_id_val_out),
.sh_dma_off_val_out (tl2cl_sh_dma_off_val_out),
.sh_dma_cnt_val_out (tl2cl_sh_dma_cnt_val_out),
.sh_tran_cnt_val_out (tl2cl_sh_tran_cnt_val_out), // Transfer Count
.sh_notif_val_out (tl2cl_sh_notif_val_out),
.sh_autoact_val_out (tl2cl_sh_autoact_val_out),
// shows if dma activate was received (a pulse)
.got_dma_activate (got_dma_activate),
.got_dma_activate_port (got_dma_activate_port),
// if CL made a mistake in controlling data FIS length
.data_limit_exceeded (data_limit_exceeded),
// LL data
// data inputs from LL
.ll_data_in (ll_data_in),
.ll_data_mask_in (ll_data_mask_in),
.ll_data_val_in (ll_data_val_in),
.ll_data_last_in (ll_data_last_in),
// transport layer tells if its inner buffer is almost full
.ll_data_busy_out (ll_data_busy_out),
// data outputs to LL
.ll_data_out (ll_data_out),
// not implemented yet TODO
.ll_data_mask_out (ll_data_mask_out),
.ll_data_last_out (ll_data_last_out),
.ll_data_val_out (ll_data_val_out),
.ll_data_strobe_in (ll_data_strobe_in),
// CL data
// required content is bypassed from ll, other is trimmed
// only content of data FIS, starting from 1st dword. Max burst = 2048 dwords
// data outputs to CL
.cl_data_out (tl2cl_data),
.cl_data_mask_out (),
.cl_data_val_out (tl2cl_data_val),
.cl_data_last_out (tl2cl_data_last),
// transport layer tells if its inner buffer is almost full
.cl_data_busy_in (tl2cl_data_busy),
// data inputs from CL
.cl_data_in (cl2tl_data),
// not implemented yet TODO
.cl_data_mask_in (cl2tl_data_mask),
.cl_data_last_in (cl2tl_data_last),
.cl_data_val_in (cl2tl_data_val),
.cl_data_strobe_out (cl2tl_data_strobe),
// watchdog timers calls. They shall be handled in TL, but for debug purposes are wired to the upper level
// when eof acknowledgement is not received after sent FIS
.watchdog_eof (watchdog_eof),
// when too many dwords is in current FIS
.watchdog_dwords (watchdog_dwords)
);
// data s from transport layer
// data stream (if any data during OOB setting => ignored)
wire [DATA_BYTE_WIDTH*8 - 1:0] data_in,
// in case of strange data aligments and size (1st mentioned @ doc, p.310, odd number of words case)
// Actually, only last data bundle shall be masked, others are always valid.
// Mask could be encoded into 3 bits instead of 4 for qword, but encoding+decoding aren't worth the bit
// TODO, for now not supported, all mask bits are assumed to be set
wire [DATA_BYTE_WIDTH/2 - 1:0] data_mask_in,
// buffer read strobe
wire data_strobe_out,
// transaction's last data budle pulse
wire data_last_in,
// read data is valid (if 0 while last pulse wasn't received => need to hold the line)
wire data_val_in,
// data s to transport layer
// read data, same as related s
wire [DATA_BYTE_WIDTH*8 - 1:0] data_out,
// same thing - all 1s for now. TODO
wire [DATA_BYTE_WIDTH/2 - 1:0] data_mask_out,
// count every data bundle read by transport layer, even if busy flag is set
// let the transport layer handle oveflows by himself
wire data_val_out,
// transport layer tells if its inner buffer is almost full
wire data_busy_in,
wire data_last_out,
// request for a new frame transition
wire frame_req,
// a little bit of overkill with the cound of response signals, think of throwing out 1 of them
// LL tells back if it cant handle the request for now
wire frame_busy,
// LL tells if the request is transmitting
wire frame_ack,
// or if it was cancelled because of simultanious incoming transmission
wire frame_rej,
// TL tell if the outcoming transaction is done and how it was done
wire frame_done_good,
wire frame_done_bad,
// if started an incoming transaction
wire incom_start,
// if incoming transition was completed
wire incom_done,
// if incoming transition had errors
wire incom_invalidate,
// transport layer responds on a completion of a FIS
wire incom_ack_good,
wire incom_ack_bad,
// oob sequence is reinitiated and link now is not established or rxelecidle
wire link_reset,
// TL demands to brutally cancel current transaction
wire sync_escape_req,
// acknowlegement of a successful reception
wire sync_escape_ack,
// TL demands to stop current recieving session
wire incom_stop_req,
// s from phy
// phy is ready - link is established
wire phy_ready,
// data-primitives stream from phy
wire [DATA_BYTE_WIDTH*8 - 1:0] phy_data_in,
wire [DATA_BYTE_WIDTH/2 - 1:0] phy_isk_in, // charisk
wire [DATA_BYTE_WIDTH/2 - 1:0] phy_err_in, // disperr | notintable
// to phy
wire [DATA_BYTE_WIDTH*8 - 1:0] phy_data_out,
wire [DATA_BYTE_WIDTH/2 - 1:0] phy_isk_out // charisk
link link(
// TODO insert watchdogs
.rst (rst),
.clk (clk),
// data inputs from transport layer
// input data stream (if any data during OOB setting => ignored)
.data_in (data_in),
// in case of strange data aligments and size (1st mentioned @ doc, p.310, odd number of words case)
// Actually, only last data bundle shall be masked, others are always valid.
// Mask could be encoded into 3 bits instead of 4 for qword, but encoding+decoding aren't worth the bit
// TODO, for now not supported, all mask bits are assumed to be set
.data_mask_in (data_mask_in),
// buffer read strobe
.data_strobe_out (data_strobe_out),
// transaction's last data budle pulse
.data_last_in (data_last_in),
// read data is valid (if 0 while last pulse wasn't received => need to hold the line)
.data_val_in (data_val_in),
// data outputs to transport layer
// read data, same as related inputs
.data_out (data_out),
// same thing - all 1s for now. TODO
.data_mask_out (data_mask_out),
// count every data bundle read by transport layer, even if busy flag is set
// let the transport layer handle oveflows by himself
.data_val_out (data_val_out),
// transport layer tells if its inner buffer is almost full
.data_busy_in (data_busy_in),
.data_last_out (data_last_out),
// request for a new frame transition
.frame_req (frame_req),
// a little bit of overkill with the cound of response signals, think of throwing out 1 of them
// LL tells back if it cant handle the request for now
.frame_busy (frame_busy),
// LL tells if the request is transmitting
.frame_ack (frame_ack),
// or if it was cancelled because of simultanious incoming transmission
.frame_rej (frame_rej),
// TL tell if the outcoming transaction is done and how it was done
.frame_done_good (frame_done_good),
.frame_done_bad (frame_done_bad),
// if started an incoming transaction
.incom_start (incom_start),
// if incoming transition was completed
.incom_done (incom_done),
// if incoming transition had errors
.incom_invalidate (incom_invalidate),
// transport layer responds on a completion of a FIS
.incom_ack_good (incom_ack_good),
.incom_ack_bad (incom_ack_bad),
// oob sequence is reinitiated and link now is not established or rxelecidle
.link_reset (link_reset),
// TL demands to brutally cancel current transaction
.sync_escape_req (sync_escape_req),
// acknowlegement of a successful reception
.sync_escape_ack (sync_escape_ack),
// TL demands to stop current recieving session
.incom_stop_req (incom_stop_req),
// inputs from phy
// phy is ready - link is established
.phy_ready (phy_ready),
// data-primitives stream from phy
.phy_data_in (phy_data_in),
.phy_isk_in (phy_isk_in), // charisk
.phy_err_in (phy_err_in), // disperr | notintable
// to phy
.phy_data_out (phy_data_out),
.phy_isk_out // charis
);
endmodule
......@@ -395,7 +395,7 @@ dma_adapter dma_adapter(
membridge /*#(
.MEMBRIDGE_ADDR (),
V .MEMBRIDGE_ADDR (),
.MEMBRIDGE_MASK (),
.MEMBRIDGE_CTRL (),
.MEMBRIDGE_STATUS_CNTRL (),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment