blob: bd432c196f81f87d765ec0365318718c6d1048a7 [file] [log] [blame]
module adbg_axi_biu
#(
parameter AXI_ADDR_WIDTH = 32,
parameter AXI_DATA_WIDTH = 64,
parameter AXI_USER_WIDTH = 6,
parameter AXI_ID_WIDTH = 3
)
(
tck_i,
trstn_i,
data_i,
data_o,
addr_i,
strobe_i,
rd_wrn_i,
rdy_o,
err_o,
word_size_i,
axi_aclk,
axi_aresetn,
axi_master_aw_valid,
axi_master_aw_addr,
axi_master_aw_prot,
axi_master_aw_region,
axi_master_aw_len,
axi_master_aw_size,
axi_master_aw_burst,
axi_master_aw_lock,
axi_master_aw_cache,
axi_master_aw_qos,
axi_master_aw_id,
axi_master_aw_user,
axi_master_aw_ready,
axi_master_ar_valid,
axi_master_ar_addr,
axi_master_ar_prot,
axi_master_ar_region,
axi_master_ar_len,
axi_master_ar_size,
axi_master_ar_burst,
axi_master_ar_lock,
axi_master_ar_cache,
axi_master_ar_qos,
axi_master_ar_id,
axi_master_ar_user,
axi_master_ar_ready,
axi_master_w_valid,
axi_master_w_data,
axi_master_w_strb,
axi_master_w_user,
axi_master_w_last,
axi_master_w_ready,
axi_master_r_valid,
axi_master_r_data,
axi_master_r_resp,
axi_master_r_last,
axi_master_r_id,
axi_master_r_user,
axi_master_r_ready,
axi_master_b_valid,
axi_master_b_resp,
axi_master_b_id,
axi_master_b_user,
axi_master_b_ready
);
//parameter AXI_ADDR_WIDTH = 32;
//parameter AXI_DATA_WIDTH = 64;
//parameter AXI_USER_WIDTH = 6;
//parameter AXI_ID_WIDTH = 3;
input wire tck_i;
input wire trstn_i;
input wire [63:0] data_i;
output reg [63:0] data_o;
input wire [31:0] addr_i;
input wire strobe_i;
input wire rd_wrn_i;
output reg rdy_o;
output wire err_o;
input wire [3:0] word_size_i;
input wire axi_aclk;
input wire axi_aresetn;
output reg axi_master_aw_valid;
output wire [AXI_ADDR_WIDTH - 1:0] axi_master_aw_addr;
output wire [2:0] axi_master_aw_prot;
output wire [3:0] axi_master_aw_region;
output wire [7:0] axi_master_aw_len;
output reg [2:0] axi_master_aw_size;
output wire [1:0] axi_master_aw_burst;
output wire axi_master_aw_lock;
output wire [3:0] axi_master_aw_cache;
output wire [3:0] axi_master_aw_qos;
output wire [AXI_ID_WIDTH - 1:0] axi_master_aw_id;
output wire [AXI_USER_WIDTH - 1:0] axi_master_aw_user;
input wire axi_master_aw_ready;
output reg axi_master_ar_valid;
output wire [AXI_ADDR_WIDTH - 1:0] axi_master_ar_addr;
output wire [2:0] axi_master_ar_prot;
output wire [3:0] axi_master_ar_region;
output wire [7:0] axi_master_ar_len;
output reg [2:0] axi_master_ar_size;
output wire [1:0] axi_master_ar_burst;
output wire axi_master_ar_lock;
output wire [3:0] axi_master_ar_cache;
output wire [3:0] axi_master_ar_qos;
output wire [AXI_ID_WIDTH - 1:0] axi_master_ar_id;
output wire [AXI_USER_WIDTH - 1:0] axi_master_ar_user;
input wire axi_master_ar_ready;
output reg axi_master_w_valid;
output wire [AXI_DATA_WIDTH - 1:0] axi_master_w_data;
output wire [(AXI_DATA_WIDTH / 8) - 1:0] axi_master_w_strb;
output wire [AXI_USER_WIDTH - 1:0] axi_master_w_user;
output wire axi_master_w_last;
input wire axi_master_w_ready;
input wire axi_master_r_valid;
input wire [AXI_DATA_WIDTH - 1:0] axi_master_r_data;
input wire [1:0] axi_master_r_resp;
input wire axi_master_r_last;
input wire [AXI_ID_WIDTH - 1:0] axi_master_r_id;
input wire [AXI_USER_WIDTH - 1:0] axi_master_r_user;
output reg axi_master_r_ready;
input wire axi_master_b_valid;
input wire [1:0] axi_master_b_resp;
input wire [AXI_ID_WIDTH - 1:0] axi_master_b_id;
input wire [AXI_USER_WIDTH - 1:0] axi_master_b_user;
output reg axi_master_b_ready;
reg [(AXI_DATA_WIDTH / 8) - 1:0] sel_reg;
reg [AXI_ADDR_WIDTH - 1:0] addr_reg;
reg [AXI_DATA_WIDTH - 1:0] data_in_reg;
reg [AXI_DATA_WIDTH - 1:0] data_out_reg;
reg wr_reg;
reg str_sync;
reg rdy_sync;
reg err_reg;
reg rdy_sync_tff1;
reg rdy_sync_tff2;
reg rdy_sync_tff2q;
reg str_sync_wbff1;
reg str_sync_wbff2;
reg str_sync_wbff2q;
reg data_o_en;
reg rdy_sync_en;
reg err_en;
reg [(AXI_DATA_WIDTH / 8) - 1:0] be_dec;
wire start_toggle;
reg [AXI_DATA_WIDTH - 1:0] swapped_data_i;
reg [AXI_DATA_WIDTH - 1:0] swapped_data_out;
reg [1:0] axi_fsm_state;
reg [1:0] next_fsm_state;
always @(*)
if (AXI_DATA_WIDTH == 64)
case (word_size_i)
4'h1:
if (addr_i[2:0] == 3'b000)
be_dec = 8'b00000001;
else if (addr_i[2:0] == 3'b001)
be_dec = 8'b00000010;
else if (addr_i[2:0] == 3'b010)
be_dec = 8'b00000100;
else if (addr_i[2:0] == 3'b011)
be_dec = 8'b00001000;
else if (addr_i[2:0] == 3'b100)
be_dec = 8'b00010000;
else if (addr_i[2:0] == 3'b101)
be_dec = 8'b00100000;
else if (addr_i[2:0] == 3'b110)
be_dec = 8'b01000000;
else
be_dec = 8'b10000000;
4'h2:
if (addr_i[2:1] == 2'b00)
be_dec = 8'b00000011;
else if (addr_i[2:1] == 2'b01)
be_dec = 8'b00001100;
else if (addr_i[2:1] == 2'b10)
be_dec = 8'b00110000;
else
be_dec = 8'b11000000;
4'h4:
if (addr_i[2] == 1'b0)
be_dec = 8'b00001111;
else
be_dec = 8'b11110000;
4'h8: be_dec = 8'b11111111;
default: be_dec = 8'b11111111;
endcase
else if (AXI_DATA_WIDTH == 32)
case (word_size_i)
4'h1:
if (addr_i[1:0] == 2'b00)
be_dec = 4'b0001;
else if (addr_i[1:0] == 2'b01)
be_dec = 4'b0010;
else if (addr_i[1:0] == 2'b10)
be_dec = 4'b0100;
else
be_dec = 4'b1000;
4'h2:
if (addr_i[1] == 1'b0)
be_dec = 4'b0011;
else
be_dec = 4'b1100;
4'h4: be_dec = 4'b1111;
4'h8: be_dec = 4'b1111;
default: be_dec = 4'b1111;
endcase
always @(*)
if (AXI_DATA_WIDTH == 64)
case (be_dec)
8'b00001111: swapped_data_i = {32'h00000000, data_i[63:32]};
8'b11110000: swapped_data_i = {data_i[63:32], 32'h00000000};
8'b00000011: swapped_data_i = {48'h000000000000, data_i[63:48]};
8'b00001100: swapped_data_i = {32'h00000000, data_i[63:48], 16'h0000};
8'b00110000: swapped_data_i = {16'h0000, data_i[63:48], 32'h00000000};
8'b11000000: swapped_data_i = {data_i[63:48], 48'h000000000000};
8'b00000001: swapped_data_i = {56'h00000000000000, data_i[63:56]};
8'b00000010: swapped_data_i = {48'h000000000000, data_i[63:56], 8'h00};
8'b00000100: swapped_data_i = {40'h0000000000, data_i[63:56], 16'h0000};
8'b00001000: swapped_data_i = {32'h00000000, data_i[63:56], 24'h000000};
8'b00010000: swapped_data_i = {24'h000000, data_i[63:56], 32'h00000000};
8'b00100000: swapped_data_i = {16'h0000, data_i[63:56], 40'h0000000000};
8'b01000000: swapped_data_i = {8'h00, data_i[63:56], 48'h000000000000};
8'b10000000: swapped_data_i = {data_i[63:56], 56'h00000000000000};
default: swapped_data_i = data_i;
endcase
else if (AXI_DATA_WIDTH == 32)
case (be_dec)
4'b1111: swapped_data_i = data_i[63:32];
4'b0011: swapped_data_i = {16'h0000, data_i[63:48]};
4'b1100: swapped_data_i = {data_i[63:48], 16'h0000};
4'b0001: swapped_data_i = {24'h000000, data_i[63:56]};
4'b0010: swapped_data_i = {16'h0000, data_i[63:56], 8'h00};
4'b0100: swapped_data_i = {8'h00, data_i[63:56], 16'h0000};
4'b1000: swapped_data_i = {data_i[63:56], 24'h000000};
default: swapped_data_i = data_i[63:32];
endcase
generate
if (AXI_DATA_WIDTH == 64) begin : genblk1
always @(*)
case (sel_reg)
8'b00001111: swapped_data_out = axi_master_r_data;
8'b11110000: swapped_data_out = {32'h00000000, axi_master_r_data[63:32]};
8'b00000011: swapped_data_out = axi_master_r_data;
8'b00001100: swapped_data_out = {16'h0000, axi_master_r_data[63:16]};
8'b00110000: swapped_data_out = {32'h00000000, axi_master_r_data[63:32]};
8'b11000000: swapped_data_out = {48'h000000000000, axi_master_r_data[63:48]};
8'b00000001: swapped_data_out = axi_master_r_data;
8'b00000010: swapped_data_out = {8'h00, axi_master_r_data[63:8]};
8'b00000100: swapped_data_out = {16'h0000, axi_master_r_data[63:16]};
8'b00001000: swapped_data_out = {24'h000000, axi_master_r_data[63:24]};
8'b00010000: swapped_data_out = {32'h00000000, axi_master_r_data[63:32]};
8'b00100000: swapped_data_out = {40'h0000000000, axi_master_r_data[63:40]};
8'b01000000: swapped_data_out = {48'h000000000000, axi_master_r_data[63:48]};
8'b10000000: swapped_data_out = {56'h00000000000000, axi_master_r_data[63:56]};
default: swapped_data_out = axi_master_r_data;
endcase
end
else if (AXI_DATA_WIDTH == 32) begin : genblk1
always @(*)
case (sel_reg)
4'b1111: swapped_data_out = axi_master_r_data;
4'b0011: swapped_data_out = axi_master_r_data;
4'b1100: swapped_data_out = {16'h0000, axi_master_r_data[31:16]};
4'b0001: swapped_data_out = axi_master_r_data;
4'b0010: swapped_data_out = {8'h00, axi_master_r_data[31:8]};
4'b0100: swapped_data_out = {16'h0000, axi_master_r_data[31:16]};
4'b1000: swapped_data_out = {24'h000000, axi_master_r_data[31:24]};
default: swapped_data_out = axi_master_r_data;
endcase
end
endgenerate
always @(posedge tck_i or negedge trstn_i)
if (~trstn_i) begin
sel_reg <= 'h0;
addr_reg <= 'h0;
data_in_reg <= 'h0;
wr_reg <= 1'b0;
end
else if (strobe_i && rdy_o) begin
sel_reg <= be_dec;
addr_reg <= addr_i;
if (!rd_wrn_i)
data_in_reg <= swapped_data_i;
wr_reg <= ~rd_wrn_i;
end
always @(posedge tck_i or negedge trstn_i)
if (~trstn_i)
str_sync <= 1'b0;
else if (strobe_i && rdy_o)
str_sync <= ~str_sync;
always @(posedge tck_i or negedge trstn_i)
if (~trstn_i) begin
rdy_sync_tff1 <= 1'b0;
rdy_sync_tff2 <= 1'b0;
rdy_sync_tff2q <= 1'b0;
end
else begin
rdy_sync_tff1 <= rdy_sync;
rdy_sync_tff2 <= rdy_sync_tff1;
rdy_sync_tff2q <= rdy_sync_tff2;
end
always @(posedge tck_i or negedge trstn_i)
if (~trstn_i)
rdy_o <= 1'b1;
else if (strobe_i && rdy_o)
rdy_o <= 1'b0;
else if (rdy_sync_tff2 != rdy_sync_tff2q)
rdy_o <= 1'b1;
assign axi_master_ar_addr = addr_reg;
assign axi_master_aw_addr = addr_reg;
assign axi_master_w_data = data_in_reg;
assign axi_master_w_strb = sel_reg;
always @(*)
if (AXI_DATA_WIDTH == 64)
data_o = data_out_reg;
else if (AXI_DATA_WIDTH == 32)
data_o = {32'h00000000, data_out_reg};
assign err_o = err_reg;
assign axi_master_aw_prot = 'h0;
assign axi_master_aw_region = 'h0;
assign axi_master_aw_len = 'h0;
assign axi_master_aw_burst = 'h0;
assign axi_master_aw_lock = 'h0;
assign axi_master_aw_cache = 'h0;
assign axi_master_aw_qos = 'h0;
assign axi_master_aw_id = 'h0;
assign axi_master_aw_user = 'h0;
assign axi_master_ar_prot = 'h0;
assign axi_master_ar_region = 'h0;
assign axi_master_ar_len = 'h0;
assign axi_master_ar_burst = 'h0;
assign axi_master_ar_lock = 'h0;
assign axi_master_ar_cache = 'h0;
assign axi_master_ar_qos = 'h0;
assign axi_master_ar_id = 'h0;
assign axi_master_ar_user = 'h0;
assign axi_master_w_user = 'h0;
assign axi_master_w_last = 1'b1;
always @(*)
case (word_size_i)
4'h1: begin
axi_master_aw_size = 3'b000;
axi_master_ar_size = 3'b000;
end
4'h2: begin
axi_master_aw_size = 3'b001;
axi_master_ar_size = 3'b001;
end
4'h4: begin
axi_master_aw_size = 3'b010;
axi_master_ar_size = 3'b010;
end
4'h8: begin
axi_master_aw_size = 3'b011;
axi_master_ar_size = 3'b011;
end
default: begin
axi_master_aw_size = 3'b011;
axi_master_ar_size = 3'b011;
end
endcase
always @(posedge axi_aclk or negedge axi_aresetn)
if (!axi_aresetn) begin
str_sync_wbff1 <= 1'b0;
str_sync_wbff2 <= 1'b0;
str_sync_wbff2q <= 1'b0;
end
else begin
str_sync_wbff1 <= str_sync;
str_sync_wbff2 <= str_sync_wbff1;
str_sync_wbff2q <= str_sync_wbff2;
end
assign start_toggle = str_sync_wbff2 != str_sync_wbff2q;
always @(posedge axi_aclk or negedge axi_aresetn)
if (!axi_aresetn)
err_reg <= 1'b0;
else if (err_en)
err_reg <= (wr_reg ? (axi_master_b_resp == 2'b00 ? 1'b0 : 1'b1) : (axi_master_r_resp == 2'b00 ? 1'b0 : 1'b1));
always @(posedge axi_aclk or negedge axi_aresetn)
if (!axi_aresetn)
data_out_reg <= 32'h00000000;
else if (data_o_en)
data_out_reg <= swapped_data_out;
always @(posedge axi_aclk or negedge axi_aresetn)
if (!axi_aresetn)
rdy_sync <= 1'b0;
else if (rdy_sync_en)
rdy_sync <= ~rdy_sync;
always @(posedge axi_aclk or negedge axi_aresetn)
if (~axi_aresetn)
axi_fsm_state <= 2'd0;
else
axi_fsm_state <= next_fsm_state;
always @(*) begin
axi_master_aw_valid = 1'b0;
axi_master_w_valid = 1'b0;
axi_master_ar_valid = 1'b0;
axi_master_b_ready = 1'b0;
axi_master_r_ready = 1'b0;
next_fsm_state = axi_fsm_state;
rdy_sync_en = 1'b0;
data_o_en = 1'b0;
err_en = 1'b0;
case (axi_fsm_state)
2'd0:
if (start_toggle)
next_fsm_state = 2'd1;
else
next_fsm_state = 2'd0;
2'd1: begin
if (wr_reg)
axi_master_aw_valid = 1'b1;
else
axi_master_ar_valid = 1'b1;
if (wr_reg && axi_master_aw_ready)
next_fsm_state = 2'd2;
else if (!wr_reg && axi_master_ar_ready)
next_fsm_state = 2'd3;
end
2'd2: begin
axi_master_w_valid = 1'b1;
if (axi_master_w_ready)
next_fsm_state = 2'd3;
end
2'd3: begin
if (wr_reg)
axi_master_b_ready = 1'b1;
else
axi_master_r_ready = 1'b1;
if (wr_reg && axi_master_b_valid) begin
next_fsm_state = 2'd0;
rdy_sync_en = 1'b1;
err_en = 1'b1;
end
else if (!wr_reg && axi_master_r_valid) begin
data_o_en = 1'b1;
next_fsm_state = 2'd0;
rdy_sync_en = 1'b1;
err_en = 1'b1;
end
end
endcase
end
endmodule