// | |
// Copyright 2022 Tobias Strauch, Munich, Bavaria | |
// | |
// SPDX-FileCopyrightText: 2020 Efabless Corporation | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// SPDX-License-Identifier: Apache-2.0 | |
// | |
module gpio (clk, | |
rstn, | |
gpio_dir_reg, | |
gpio_out_reg, | |
gpio_in, | |
dbus_rdwr_gpio_base, | |
dbus_rd_add_bus, | |
dbus_wr_add_bus, | |
dbus_rdwr_be_in, | |
dbus_wr_en, | |
dbus_wr_data_in, | |
dbus_rd_req, | |
dbus_rd_data_out, | |
ca_match, | |
ca_command_in, | |
gpio_event, | |
gpio_event_ack, | |
gpio_command_out); | |
//`include "MPSOC_parameters.v" | |
parameter GPIO_EVENT_BANKS = 4; | |
parameter GPIO_OFFSET = 32'h80030000; | |
parameter GPIO_BASE = 16'h8003; | |
parameter GPIO_STEP = 12'h100; | |
parameter GPIO_DIR_CLR = 16'h0000; | |
parameter GPIO_DIR_SET = 16'h0004; | |
parameter GPIO_OUT_CLR = 16'h0010; | |
parameter GPIO_OUT_SET = 16'h0014; | |
parameter GPIO_IN = 16'h0020; | |
parameter GPIO_LVL0 = 16'h0030; | |
parameter GPIO_LVL1 = 16'h0034; | |
parameter GPIO_CAP = 16'h0040; | |
parameter GPIO_EVENT_ADD = 16'h1000; | |
parameter CORES = 1; | |
parameter BANKS = 4; | |
parameter GPIOS = 32; | |
input clk; | |
input rstn; | |
output [GPIOS - 1:0] gpio_dir_reg; | |
output [GPIOS - 1:0] gpio_out_reg; | |
input [GPIOS - 1:0] gpio_in; | |
input [CORES-1:0] dbus_rdwr_gpio_base; | |
input [31:0] dbus_rd_add_bus; | |
input [31:0] dbus_wr_add_bus; | |
input [7:0] dbus_rdwr_be_in; | |
input [CORES-1:0] dbus_wr_en; | |
input [31:0] dbus_wr_data_in; | |
input [CORES-1:0] dbus_rd_req; | |
output [31:0] dbus_rd_data_out; | |
input [CORES-1:0] ca_match; | |
input [31:0] ca_command_in; | |
output [CORES-1:0] gpio_event; | |
input [CORES-1:0] gpio_event_ack; | |
output [31:0] gpio_command_out; | |
wire [31:0] dbus_rd_add [CORES-1:0]; | |
assign dbus_rd_add[0] = dbus_rd_add_bus[ 31: 0]; | |
wire [31:0] dbus_wr_add [CORES-1:0]; | |
assign dbus_wr_add[0] = dbus_wr_add_bus[ 31: 0]; | |
reg [CORES-1:0] dbus_wr_en_d1; | |
wire [31:0] dbus_wr_data [CORES-1:0]; | |
reg [31:0] dbus_wr_data_d1 [CORES-1:0]; | |
reg [31:0] dbus_wr_data_d2 [CORES-1:0]; | |
assign dbus_wr_data[0] = dbus_wr_data_in[ 31: 0]; | |
reg [31:0] dbus_rd_data [CORES-1:0]; | |
assign dbus_rd_data_out = dbus_rd_data[0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
dbus_wr_data_d2[l] <= 0; | |
dbus_wr_data_d1[l] <= 0; | |
dbus_wr_en_d1[l] <= 1'b0; | |
end | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
dbus_wr_data_d2[l] <= dbus_wr_data_d1[l]; | |
dbus_wr_data_d1[l] <= dbus_wr_data[l]; | |
dbus_wr_en_d1[l] <= dbus_wr_en; | |
end | |
end | |
reg [31:0] ca_command_reg [CORES-1:0]; | |
reg [3:0] ca_match_reg; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
ca_command_reg[l] <= 0; | |
end | |
ca_match_reg <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
ca_command_reg[l] <= ca_command_in[ 31: 0]; | |
end | |
ca_match_reg <= ca_match; | |
end | |
reg [31:0] gpio_command [CORES-1:0]; | |
assign gpio_command_out = gpio_command[0]; | |
reg [GPIOS - 1:0] gpio_dir_reg; | |
reg [GPIOS - 1:0] gpio_out_reg; | |
reg [GPIOS - 1:0] gpio_level_reg; | |
reg [GPIOS - 1:0] gpio_armed_reg; | |
reg [GPIO_EVENT_BANKS * 8 - 1:0] gpio_event_reg; | |
reg [GPIO_EVENT_BANKS * 8 - 1:0] gpio_cap_reg; | |
reg [1:0] gpio_core_reg [31:0]; | |
reg [GPIOS - 1:0] gpio_in_l1_reg; | |
reg [GPIOS - 1:0] gpio_in_l2_reg; | |
reg [GPIOS - 1:0] gpio_in_l3_reg; | |
reg [GPIOS - 1:0] gpio_in_reg; | |
integer k, l, m, n; | |
// CLEAR DIR | |
reg [14:0] gpio_clr_dir_dbus_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_clr_dir_dbus_reg[l] <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_clr_dir_dbus_reg[l] <= 0; | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (dbus_wr_en/* _c3 */[l] & dbus_rdwr_gpio_base/* _c3 */[l] & (dbus_wr_add/* _c3 */[l][15:0] == (k * GPIO_STEP) + GPIO_DIR_CLR)) | |
gpio_clr_dir_dbus_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [14:0] gpio_clr_dir_ca_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_clr_dir_ca_reg[l] <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_clr_dir_ca_reg[l] <= 0; | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (ca_match_reg[l] & (ca_command_reg[l][/*31:29*/30:28] == 3'b010) & (ca_command_reg[l][11:8] == k)) | |
gpio_clr_dir_ca_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [GPIOS - 1:0] gpio_clr_dir_sig; | |
always @(*) //gpio_clr_dir_dbus_reg or dbus_wr_data_d1/* _c4 */ or gpio_clr_dir_ca_reg or ca_command_reg) | |
begin | |
gpio_clr_dir_sig = 0; // overwrite bit-wise | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (gpio_clr_dir_dbus_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (dbus_wr_data_d1/* _c4 */[l][m]) | |
gpio_clr_dir_sig[k * 8 + m] = 1'b1; | |
end | |
if (gpio_clr_dir_ca_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (ca_command_reg[l][m]) | |
gpio_clr_dir_sig[k * 8 + m] = 1'b1; | |
end | |
end | |
end | |
end | |
// SET DIR | |
reg [14:0] gpio_set_dir_dbus_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_set_dir_dbus_reg[l] <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_set_dir_dbus_reg[l] <= 0; | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (dbus_wr_en/* _c3 */[l] & dbus_rdwr_gpio_base/* _c3 */[l] & (dbus_wr_add/* _c3 */[l][15:0] == (k * GPIO_STEP) + GPIO_DIR_SET)) | |
gpio_set_dir_dbus_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [14:0] gpio_set_dir_ca_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_set_dir_ca_reg[l] <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_set_dir_ca_reg[l] <= 0; | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all 4 cores addressing possibilities | |
if (ca_match_reg[l] & (ca_command_reg[l][/*31:29*/30:28] == 3'b011) & (ca_command_reg[l][11:8] == k)) | |
gpio_set_dir_ca_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [GPIOS - 1:0] gpio_set_dir_sig; | |
always @(*) | |
begin | |
gpio_set_dir_sig = 0; // overwrite bit-wise | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (gpio_set_dir_dbus_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (dbus_wr_data_d1/* _c4 */[l][m]) | |
gpio_set_dir_sig[k * 8 + m] = 1'b1; | |
end | |
if (gpio_set_dir_ca_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (ca_command_reg[l][m]) | |
gpio_set_dir_sig[k * 8 + m] = 1'b1; | |
end | |
end | |
end | |
end | |
// DIR | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_dir_reg <= 0; | |
end else begin | |
gpio_dir_reg <= (gpio_dir_reg | gpio_set_dir_sig) & (~gpio_clr_dir_sig); | |
end | |
// CLEAR OUT | |
reg [14:0] gpio_clr_out_dbus_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_clr_out_dbus_reg[l] <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_clr_out_dbus_reg[l] <= 0; | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (dbus_wr_en/* _c3 */[l] & dbus_rdwr_gpio_base/* _c3 */[l] & (dbus_wr_add/* _c3 */[l][15:0] == (k * GPIO_STEP) + GPIO_OUT_CLR)) | |
gpio_clr_out_dbus_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [14:0] gpio_clr_out_ca_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_clr_out_ca_reg[l] <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_clr_out_ca_reg[l] <= 0; | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all 4 cores addressing possibilities | |
if (ca_match_reg[l] & (ca_command_reg[l][/*31:29*/30:28] == 3'b000) & (ca_command_reg[l][11:8] == k)) | |
gpio_clr_out_ca_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [GPIOS - 1:0] gpio_clr_out_sig; | |
always @(*) | |
begin | |
gpio_clr_out_sig = 0; // overwrite bit-wise | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (gpio_clr_out_dbus_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (dbus_wr_data_d1[l][m]) | |
gpio_clr_out_sig[k * 8 + m] = 1'b1; | |
end | |
if (gpio_clr_out_ca_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (ca_command_reg[l][m]) | |
gpio_clr_out_sig[k * 8 + m] = 1'b1; | |
end | |
end | |
end | |
end | |
// SET OUT | |
reg [14:0] gpio_set_out_dbus_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_set_out_dbus_reg[l] <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_set_out_dbus_reg[l] <= 0; | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (dbus_wr_en/* _c3 */[l] & dbus_rdwr_gpio_base/* _c3 */[l] & (dbus_wr_add/* _c3 */[l][15:0] == (k * GPIO_STEP) + GPIO_OUT_SET)) | |
gpio_set_out_dbus_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [14:0] gpio_set_out_ca_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_set_out_ca_reg[l] <= 0; | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) | |
gpio_set_out_ca_reg[l] <= 0; | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (ca_match_reg[l] & (ca_command_reg[l][/*31:29*/30:28] == 3'b001) & (ca_command_reg[l][11:8] == k)) | |
gpio_set_out_ca_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [GPIOS - 1:0] gpio_set_out_sig; | |
always @(*) | |
begin | |
gpio_set_out_sig = 0; // overwrite bit-wise | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (gpio_set_out_dbus_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (dbus_wr_data_d1[l][m]) | |
gpio_set_out_sig[k * 8 + m] = 1'b1; | |
end | |
if (gpio_set_out_ca_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (ca_command_reg[l][m]) | |
gpio_set_out_sig[k * 8 + m] = 1'b1; | |
end | |
end | |
end | |
end | |
// OUT | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_out_reg <= 0; | |
end else begin | |
gpio_out_reg <= (gpio_out_reg | gpio_set_out_sig) & (~gpio_clr_out_sig); | |
end | |
// Filter IN | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_in_l1_reg <= 0; | |
gpio_in_l2_reg <= 0; | |
gpio_in_l3_reg <= 0; | |
gpio_in_reg <= 0; | |
end else begin | |
gpio_in_reg <= (gpio_in_l3_reg & gpio_in_l2_reg) | | |
(gpio_in_l3_reg & gpio_in_l1_reg) | | |
(gpio_in_l2_reg & gpio_in_l1_reg); | |
gpio_in_l3_reg <= gpio_in_l2_reg; | |
gpio_in_l2_reg <= gpio_in_l1_reg; | |
gpio_in_l1_reg <= gpio_in; | |
end | |
// read | |
reg [14:0] gpio_rd_sel_in_reg [CORES-1:0]; | |
reg [14:0] gpio_rd_sel_cap_reg [CORES-1:0]; | |
always @(dbus_rd_req or dbus_rdwr_gpio_base) begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
gpio_rd_sel_in_reg[l] <= 0; | |
gpio_rd_sel_cap_reg[l] <= 0; | |
end | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (dbus_rd_req[l] & dbus_rdwr_gpio_base/* _c3 */[l] & | |
(dbus_rd_add[l][15:0] == ((k * GPIO_STEP) + GPIO_IN))) begin | |
gpio_rd_sel_in_reg[l][k] <= 1'b1; | |
end else if (dbus_rd_req[l] & dbus_rdwr_gpio_base[l] & | |
(dbus_rd_add[l][15:0] == ((k * GPIO_STEP) + GPIO_CAP))) begin | |
gpio_rd_sel_cap_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
end | |
reg [7:0] gpio_rd_data_in [CORES-1:0][BANKS-1:0]; | |
reg [7:0] gpio_rd_data_cap [CORES-1:0][BANKS-1:0]; | |
always @(*) | |
begin | |
for (k = 0; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (gpio_rd_sel_in_reg[l][k]) begin | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
gpio_rd_data_in[l][k][m] = gpio_in_reg[k * 8 + m]; | |
end | |
end else | |
gpio_rd_data_in[l][k] = 0; | |
if (gpio_rd_sel_cap_reg[l][k]) begin | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
gpio_rd_data_cap[l][k][m] = gpio_cap_reg[k * 8 + m]; | |
end | |
end else | |
gpio_rd_data_cap[l][k] = 0; | |
end | |
end | |
end | |
always @(*) | |
begin | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
dbus_rd_data[l][7:0] = gpio_rd_data_in[l][0] | | |
gpio_rd_data_in[l][1] | | |
gpio_rd_data_in[l][2] | | |
gpio_rd_data_in[l][3] | | |
gpio_rd_data_cap[l][0] | | |
gpio_rd_data_cap[l][1] | | |
gpio_rd_data_cap[l][2] | | |
gpio_rd_data_cap[l][3]; | |
end | |
end | |
// LEVEL | |
reg [CORES-1:0] gpio_event; | |
always @(*) begin | |
for (l = 0; l < CORES; l = l + 1) begin // go through all 4 core | |
gpio_event[l] = !(gpio_prop_p4_fsm[l] == 0) & !gpio_event_ack; | |
end | |
end | |
reg [CORES-1:0] gpio_command_reg; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_command_reg <= 0; | |
end else begin | |
gpio_command_reg <= 0; | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (dbus_wr_en/* _c3 */[l] & dbus_rdwr_gpio_base/* _c3 */[l] & (dbus_wr_add/* _c3 */[l][15:0] == GPIO_EVENT_ADD)) | |
gpio_command_reg[l] <= 1'b1; | |
end | |
end | |
reg [1:0] gpio_prop_p4_fsm [CORES-1:0]; | |
reg [1:0] gpio_prop_p4_ack; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_prop_p4_ack <= 0; | |
for (l = 0; l < CORES; l = l + 1) begin | |
gpio_prop_p4_fsm[l] <= 0; | |
end | |
for (l = 0; l < CORES; l = l + 1) begin | |
gpio_command[l] <= 0; | |
end | |
end else begin | |
gpio_command[0][30] <= 1'b1; | |
for (l = 0; l < CORES; l = l + 1) // go through all CORES cores addressing possibilities | |
if (gpio_command_reg[l]) | |
gpio_command[l][13:0] <= dbus_wr_data_d1/* _c4 */[l][13:0]; | |
///////////////////////////////////// | |
// event propagation, pipe 4 | |
///////////////////////////////////// | |
gpio_prop_p4_ack <= 0; | |
for (l = 0; l < CORES; l = l + 1) begin // go through all 4 core | |
if (gpio_prop_p4_fsm[l] == 0) begin // empty pipe element | |
if (gpio_prop_p3_fsm[l * 2 + 0]) begin // go through nibble group | |
gpio_prop_p4_fsm[l] <= 0 + 1; // state = bit count + 1 | |
gpio_command[l][19:14] <= {gpio_prop_p3_fsm[l * 2 + 0][1:0] - 1, gpio_prop_p3_tag[l * 2 + 0]}; | |
gpio_command[l][20] <= 1'b0; | |
gpio_prop_p4_ack[l * 2 + 0] <= 1'b1; | |
end else if (gpio_prop_p3_fsm[l * 2 + 1]) begin | |
gpio_prop_p4_fsm[l] <= 1 + 1; | |
gpio_command[l][19:14] <= {gpio_prop_p3_fsm[l * 2 + 1][1:0] - 1, gpio_prop_p3_tag[l * 2 + 1]}; | |
gpio_command[l][20] <= 1'b1; | |
gpio_prop_p4_ack[l * 2 + 1] <= 1'b1; | |
end | |
end else if (gpio_event_ack[l]) begin | |
case (gpio_prop_p4_fsm[l]) // synopsys full_case | |
1: if (gpio_prop_p3_fsm[l * 2 + 1]) begin | |
gpio_prop_p4_fsm[l] <= 1 + 1; | |
gpio_command[l][19:14] <= {gpio_prop_p3_fsm[l * 2 + 1][1:0] - 1, gpio_prop_p3_tag[l * 2 + 1]}; | |
gpio_command[l][20] <= 1'b1; | |
gpio_prop_p4_ack[l * 2 + 1] <= 1'b1; | |
end else | |
gpio_prop_p4_fsm[l] <= 0; | |
2: if (gpio_prop_p3_fsm[l * 2 + 0]) begin | |
gpio_prop_p4_fsm[l] <= 0 + 1; | |
gpio_command[l][19:14] <= {gpio_prop_p3_fsm[l * 2 + 0][1:0] - 1, gpio_prop_p3_tag[l * 2 + 0]}; | |
gpio_command[l][20] <= 1'b0; | |
gpio_prop_p4_ack[l * 2 + 0] <= 1'b1; | |
end else | |
gpio_prop_p4_fsm[l] <= 0; | |
default : ; | |
endcase | |
end | |
end | |
end | |
reg [2:0] gpio_prop_p3_fsm [1:0]; | |
reg [3:0] gpio_prop_p3_tag [1:0]; | |
reg [7:0] gpio_prop_p3_ack; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_prop_p3_ack <= 0; | |
for (l = 0; l < 2; l = l + 1) begin | |
gpio_prop_p3_fsm[l] <= 0; | |
gpio_prop_p3_tag[l] <= 0; | |
end | |
end else begin | |
///////////////////////////////////// | |
// event propagation, pipe 3 | |
///////////////////////////////////// | |
gpio_prop_p3_ack <= 0; | |
for (l = 0; l < CORES; l = l + 1) begin // go through all 4 core | |
for (k = 0; k < 2; k = k + 1) begin // go through all nibble groups | |
if (gpio_prop_p3_fsm[l * 2 + k] == 0) begin // empty pipe element | |
if (gpio_prop_p2_fsm[l * 8 + k * 4 + 0]) begin // go through nibble group | |
gpio_prop_p3_fsm[l * 2 + k] <= 0 + 1; // state = bit count + 1 | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 0] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 0]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 0] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 1]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 1 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 1] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 1]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 1] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 2]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 2 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 2] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 2]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 2] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 3]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 3 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 3] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 3]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 3] <= 1'b1; | |
end | |
end else if (gpio_prop_p4_ack[l * 2 + k]) begin | |
case (gpio_prop_p3_fsm[l * 2 + k]) // synopsys full_case | |
1: if (gpio_prop_p2_fsm[l * 8 + k * 4 + 1]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 1 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 1] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 1]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 1] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 2]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 2 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 2] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 2]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 2] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 3]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 3 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 3] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 3]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 3] <= 1'b1; | |
end else | |
gpio_prop_p3_fsm[l * 2 + k] <= 0; | |
2: if (gpio_prop_p2_fsm[l * 8 + k * 4 + 2]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 2 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 2] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 2]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 2] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 3]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 3 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 3] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 3]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 3] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 0]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 0 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 0] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 0]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 0] <= 1'b1; | |
end else | |
gpio_prop_p3_fsm[l * 2 + k] <= 0; | |
3: if (gpio_prop_p2_fsm[l * 8 + k * 4 + 3]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 3 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 3] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 3]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 3] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 0]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 0 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 0] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 0]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 0] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 1]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 1 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 1] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 1]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 1] <= 1'b1; | |
end else | |
gpio_prop_p3_fsm[l * 2 + k] <= 0; | |
4: if (gpio_prop_p2_fsm[l * 8 + k * 4 + 0]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 0 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 0] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 0]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 0] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 1]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 1 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 1] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 1]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 1] <= 1'b1; | |
end else if (gpio_prop_p2_fsm[l * 8 + k * 4 + 2]) begin | |
gpio_prop_p3_fsm[l * 2 + k] <= 2 + 1; | |
gpio_prop_p3_tag[l * 2 + k] <= {gpio_prop_p2_fsm[l * 8 + k * 4 + 2] - 1, gpio_prop_p2_tag[l * 8 + k * 4 + 2]}; | |
gpio_prop_p3_ack[l * 8 + k * 4 + 2] <= 1'b1; | |
end else | |
gpio_prop_p3_fsm[l * 2 + k] <= 0; | |
default : ; | |
endcase | |
end | |
end | |
end | |
end | |
reg [2:0] gpio_prop_p2_fsm [7:0]; | |
reg [1:0] gpio_prop_p2_tag [7:0]; | |
reg [31:0] gpio_prop_p2_ack; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_prop_p2_ack <= 0; | |
for (l = 0; l < 8; l = l + 1) begin | |
gpio_prop_p2_fsm[l] <= 0; | |
gpio_prop_p2_tag[l] <= 0; | |
end | |
end else begin | |
///////////////////////////////////// | |
// event propagation, pipe 2 | |
///////////////////////////////////// | |
gpio_prop_p2_ack <= 0; | |
for (l = 0; l < CORES; l = l + 1) begin // go through all 4 core | |
for (k = 0; k < 8; k = k + 1) begin // go through all nibble groups | |
if (gpio_prop_p2_fsm[l * 8 + k] == 0) begin // empty pipe element | |
if (gpio_prop_p1_fsm[l * 32 + k * 4 + 0]) begin // go through nibble group | |
gpio_prop_p2_fsm[l * 8 + k] <= 0 + 1; // state = bit count + 1 | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 0] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 0][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 0] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 1]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 1 + 1; | |
//gpio_prop_p2_tag[l * 8 + k] <= 0; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 1] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 1][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 1] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 2]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 2 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 2] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 2][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 2] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 3]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 3 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 3] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 3][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 3] <= 1'b1; | |
end | |
end else if (gpio_prop_p3_ack[l * 8 + k]) begin | |
case (gpio_prop_p2_fsm[l * 8 + k]) // round robin | |
1: if (gpio_prop_p1_fsm[l * 32 + k * 4 + 1]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 1 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 1] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 1][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 1] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 2]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 2 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 2] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 2][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 2] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 3]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 3 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 3] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 3][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 3] <= 1'b1; | |
end else | |
gpio_prop_p2_fsm[l * 8 + k] <= 0; | |
2: if (gpio_prop_p1_fsm[l * 32 + k * 4 + 2]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 2 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 2] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 2][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 2] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 3]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 3 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 3] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 3][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 3] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 0]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 0 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 0] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 0][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 0] <= 1'b1; | |
end else | |
gpio_prop_p2_fsm[l * 8 + k] <= 0; | |
3: if (gpio_prop_p1_fsm[l * 32 + k * 4 + 3]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 3 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 3] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 3][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 3] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 0]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 0 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 0] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 0][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 0] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 1]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 1 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 1] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 1][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 1] <= 1'b1; | |
end else | |
gpio_prop_p2_fsm[l * 8 + k] <= 0; | |
4: if (gpio_prop_p1_fsm[l * 32 + k * 4 + 0]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 0 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 0] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 0][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 0] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 1]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 1 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 1] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 1][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 1] <= 1'b1; | |
end else if (gpio_prop_p1_fsm[l * 32 + k * 4 + 2]) begin | |
gpio_prop_p2_fsm[l * 8 + k] <= 2 + 1; | |
gpio_prop_p2_tag[l * 8 + k] <= {gpio_prop_p1_fsm[l * 32 + k * 4 + 2] - 1, gpio_prop_p1_tag[l * 32 + k * 4 + 2][0]}; | |
gpio_prop_p2_ack[l * 32 + k * 4 + 2] <= 1'b1; | |
end else | |
gpio_prop_p2_fsm[l * 8 + k] <= 0; | |
default : ; | |
endcase | |
end | |
end | |
end | |
end | |
reg [1:0] gpio_prop_p1_fsm [31:0]; | |
reg [1:0] gpio_prop_p1_tag [31:0]; | |
reg [63:0] gpio_prop_p1_ack; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_prop_p1_ack <= 0; | |
for (l = 0; l < 32; l = l + 1) begin | |
gpio_prop_p1_fsm[l] <= 0; | |
gpio_prop_p1_tag[l] <= 0; | |
end | |
end else begin | |
///////////////////////////////////// | |
// event propagation, pipe 1 | |
///////////////////////////////////// | |
gpio_prop_p1_ack <= 0; | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores | |
for (k = 0; k < GPIO_EVENT_BANKS; k = k + 1) begin // go through all nibble groups | |
for (n = 0; n < 2; n = n + 1) begin // go through all 2 nibbles | |
if (gpio_prop_p1_fsm[l * 32 + k * 2 + n] == 0) begin // empty pipe element | |
if (gpio_prop_p0_fsm[l * 64 + k * 4 + n * 2 + 0]) begin // go through nibble group | |
gpio_prop_p1_fsm[l * 32 + k * 2 + n] <= 0 + 1; // state = bit count + 1 | |
gpio_prop_p1_tag[l * 32 + k * 2 + n] <= gpio_prop_p0_fsm[l * 64 + k * 4 + n * 2 + 0] - 1; | |
gpio_prop_p1_ack[l * 64 + k * 4 + n * 2 + 0] <= 1'b1; | |
end else if (gpio_prop_p0_fsm[l * 64 + k * 4 + n * 2 + 1]) begin | |
gpio_prop_p1_fsm[l * 32 + k * 2 + n] <= 1 + 1; | |
gpio_prop_p1_tag[l * 32 + k * 2 + n] <= gpio_prop_p0_fsm[l * 64 + k * 4 + n * 2 + 1] - 1; | |
gpio_prop_p1_ack[l * 64 + k * 4 + n * 2 + 1] <= 1'b1; | |
end | |
end else if (gpio_prop_p2_ack[l * 32 + k * 2 + n]) begin | |
case (gpio_prop_p1_fsm[l * 32 + k * 2 + n]) // synopsys full_case | |
1: if (gpio_prop_p0_fsm[l * 64 + k * 4 + n * 2 + 1]) begin | |
gpio_prop_p1_fsm[l * 32 + k * 2 + n] <= 1 + 1; | |
gpio_prop_p1_tag[l * 32 + k * 2 + n] <= gpio_prop_p0_fsm[l * 64 + k * 4 + n * 2 + 1] - 1; | |
gpio_prop_p1_ack[l * 64 + k * 4 + n * 2 + 1] <= 1'b1; | |
end else | |
gpio_prop_p1_fsm[l * 32 + k * 2 + n] <= 0; | |
2: if (gpio_prop_p0_fsm[l * 64 + k * 4 + n * 2 + 0]) begin | |
gpio_prop_p1_fsm[l * 32 + k * 2 + n] <= 0 + 1; | |
gpio_prop_p1_tag[l * 32 + k * 2 + n] <= gpio_prop_p0_fsm[l * 64 + k * 4 + n * 2 + 0] - 1; | |
gpio_prop_p1_ack[l * 64 + k * 4 + n * 2 + 0] <= 1'b1; | |
end else | |
gpio_prop_p1_fsm[l * 32 + k * 2 + n] <= 0; | |
default : ; | |
endcase | |
end | |
end | |
end | |
end | |
end | |
reg [GPIO_EVENT_BANKS-1:0] gpio_sel_lvl0_reg [CORES-1:0]; | |
reg [GPIO_EVENT_BANKS-1:0] gpio_sel_lvl1_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
gpio_sel_lvl0_reg[l] <= 0; | |
gpio_sel_lvl1_reg[l] <= 0; | |
end | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
gpio_sel_lvl0_reg[l] <= 0; | |
gpio_sel_lvl1_reg[l] <= 0; | |
end | |
for (k = 0; k < GPIO_EVENT_BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if ((dbus_wr_add/* _c2 */[l][15:0] == (k * GPIO_STEP) + GPIO_LVL0) & dbus_rdwr_gpio_base/* _c3 */[l]) | |
gpio_sel_lvl0_reg[l][k] <= 1'b1; | |
if ((dbus_wr_add/* _c2 */[l][15:0] == (k * GPIO_STEP) + GPIO_LVL1) & dbus_rdwr_gpio_base/* _c3 */[l]) | |
gpio_sel_lvl1_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [GPIO_EVENT_BANKS-1:0] gpio_lvl0_reg [CORES-1:0]; | |
reg [GPIO_EVENT_BANKS-1:0] gpio_lvl1_reg [CORES-1:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
gpio_lvl0_reg[l] <= 0; | |
gpio_lvl1_reg[l] <= 0; | |
end | |
end else begin | |
for (l = 0; l < CORES; l = l + 1) begin | |
gpio_lvl0_reg[l] <= 0; | |
gpio_lvl1_reg[l] <= 0; | |
end | |
for (k = 0; k < GPIO_EVENT_BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (dbus_wr_en_d1/* _c3 */[l] & gpio_sel_lvl0_reg[l][k]) | |
gpio_lvl0_reg[l][k] <= 1'b1; | |
if (dbus_wr_en_d1/* _c3 */[l] & gpio_sel_lvl1_reg[l][k]) | |
gpio_lvl1_reg[l][k] <= 1'b1; | |
end | |
end | |
end | |
reg [1:0] gpio_prop_p0_fsm [63:0]; | |
always @(posedge clk or negedge rstn) | |
if (~rstn) begin | |
gpio_level_reg <= 0; | |
gpio_armed_reg <= 0; | |
for (l = 0; l < 32; l = l + 1) begin | |
gpio_core_reg[l] <= 0; | |
end | |
gpio_event_reg <= 0; | |
for (l = 0; l < 64; l = l + 1) begin | |
gpio_prop_p0_fsm[l] <= 0; | |
end | |
gpio_cap_reg <= 0; | |
end else begin | |
///////////////////////////////////// | |
// event propagation, pipe 0 | |
///////////////////////////////////// | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES core sources | |
for (k = 0; k < GPIO_EVENT_BANKS; k = k + 1) begin // go through all banks | |
for (n = 0; n < 4; n = n + 1) begin // go through all 2 nibbles | |
if (gpio_prop_p0_fsm[l * 64 + k * 4 + n] == 0) begin // empty pipe element | |
if (gpio_event_reg[k * 8 + n * 2 + 0] & (gpio_core_reg[k * 8 + n * 2 + 0] == l)) begin | |
gpio_prop_p0_fsm[l * 64 + k * 4 + n] <= 1; // state = nibble count + 1 | |
gpio_event_reg[k * 8 + n * 2 + 0] <= 1'b0; | |
end else if (gpio_event_reg[k * 8 + n * 2 + 1] & (gpio_core_reg[k * 8 + n * 2 + 1] == l)) begin | |
gpio_prop_p0_fsm[l * 64 + k * 4 + n] <= 2; // state = nibble count + 1 | |
gpio_event_reg[k * 8 + n * 2 + 1] <= 1'b0; | |
end | |
end else if (gpio_prop_p1_ack[l * 64 + k * 4 + n]) begin | |
case (gpio_prop_p0_fsm[l * 64 + k * 4 + n]) // round robin | |
1: if ((gpio_event_reg[k * 8 + n * 2 + 1]) & (gpio_core_reg[k * 8 + n * 2 + 1] == l)) begin | |
gpio_prop_p0_fsm[l * 64 + k * 4 + n] <= 2; | |
gpio_event_reg[k * 8 + n * 2 + 1] <= 1'b0; | |
end else | |
gpio_prop_p0_fsm[l * 64 + k * 4 + n] <= 0; | |
2: if ((gpio_event_reg[k * 8 + n * 2 + 0]) & (gpio_core_reg[k * 8 + n * 2 + 0] == l)) begin | |
gpio_prop_p0_fsm[l * 64 + k * 4 + n] <= 1; | |
gpio_event_reg[k * 8 + n * 2 + 0] <= 1'b0; | |
end else | |
gpio_prop_p0_fsm[l * 64 + k * 4 + n] <= 0; | |
default : ; | |
endcase | |
end | |
end | |
end | |
end | |
///////////////////////////////////// | |
// detect event, unarm | |
///////////////////////////////////// | |
for (k = 0; k < GPIO_EVENT_BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits | |
if (!gpio_event_reg[k * 8 + m]) | |
if (gpio_armed_reg[k * 8 + m]) | |
if (gpio_level_reg[k * 8 + m] == gpio_in_reg[k * 8 + m]) begin | |
gpio_event_reg[k * 8 + m] <= 1'b1; | |
gpio_armed_reg[k * 8 + m] <= 1'b0; | |
if (m < 7) | |
gpio_cap_reg[k * 8 + m + 1] <= gpio_in_reg[k * 8 + m + 1]; | |
else | |
gpio_cap_reg[k * 8 + m - 7] <= gpio_in_reg[k * 8 + m - 7]; | |
end | |
end | |
end | |
///////////////////////////////////// | |
// write data bus: | |
// save level and core | |
// set armed flag | |
///////////////////////////////////// | |
for (k = 0; k < GPIO_EVENT_BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (l = 0; l < CORES; l = l + 1) begin // go through all CORES cores addressing possibilities | |
if (gpio_lvl0_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits | |
if (dbus_wr_data_d2/* _c4 */[l][m]) begin | |
gpio_level_reg[k * 8 + m] <= 1'b0; | |
gpio_armed_reg[k * 8 + m] <= 1'b1; | |
gpio_core_reg[k * 8 + m] <= l; | |
end | |
end | |
if (gpio_lvl1_reg[l][k]) | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits, bus wide didn't work | |
if (dbus_wr_data_d2/* _c4 */[l][m]) begin | |
gpio_level_reg[k * 8 + m] <= 1'b1; | |
gpio_armed_reg[k * 8 + m] <= 1'b1; | |
gpio_core_reg[k * 8 + m] <= l; | |
end | |
end | |
end | |
end | |
///////////////////////////////////// | |
// remove unconnected and ARTY LED related banks | |
///////////////////////////////////// | |
for (k = GPIO_EVENT_BANKS; k < BANKS; k = k + 1) begin // go through all 8 bit wide banks | |
for (m = 0; m < 8; m = m + 1) begin // go through all bits | |
gpio_level_reg[k * 8 + m] <= 1'b0; | |
gpio_armed_reg[k * 8 + m] <= 1'b0; | |
gpio_core_reg[k * 8 + m] <= 0; | |
end | |
end | |
end | |
endmodule |