ethercat_core





↓RTLコードはこちら





↓RTLコードはこちら





↓RTLコードはこちら





↓RTLコードはこちら
















`default_nettype none

// ESC register
//  | Name                                | Address |    Length | R/W  |         Init Value | Note                    |
//  | :---------------------------------- | :------ | --------: | :--- | -----------------: | :---------------------- |
//  | ESC Information                     | 0x0000  |   2 Bytes | R    |             0x0000 |                         |
//  | Configured Station Address          | 0x0010  |   2 Bytes | R/W  |             0x0000 |                         |
//  | Configured Station Alias            | 0x0012  |   2 Bytes | R/W  |             0x0000 |                         |
//  | ESC DL Control                      | 0x0100  |   4 Bytes | R/W  |         0x00000000 | Not used                |
//  | AL Control                          | 0x0120  |   2 Bytes | R/W  |             0x0000 |                         |
//  | AL Status                           | 0x0130  |   4 Bytes | R    |         0x00000001 |                         |
//  | EEPROM Configuration                | 0x0500  |    1 Byte | R/W  |               0x00 | Not used                |
//  | EEPROM PDI Access State             | 0x0501  |    1 Byte | R/W  |               0x00 | Not used                |
//  | EEPROM Control/Status               | 0x0502  |   2 Bytes | R/W  |             0x0000 |                         |
//  | EEPROM Address                      | 0x0504  |   4 Bytes | R/W  |             0x0000 |                         |
//  | EEPROM Data                         | 0x0508  |   4 Bytes | R    |             0x0000 |                         |
//  | FMMU 0                              | 0x0600  |  16 Bytes | R/W  |          All zeros |                         |
//  | FMMU 1                              | 0x0610  |  16 Bytes | R/W  |          All zeros |                         |
//  | Sync Manager 0                      | 0x0800  |   8 Bytes | R/W  |          All zeros |                         |
//  | Sync Manager 1                      | 0x0808  |   8 Bytes | R/W  |          All zeros |                         |

module ethercat_core # (
  parameter ETH_PORT_NUM = 1
) (
  input  wire clk,
  input  wire rst,
  // GPIO
  input  wire  [31:0] gpio_in,
  output logic [31:0] gpio_out,
  // Pseudo EEPROM
  output logic [31:0] eeprom_address,
  input  wire  [31:0] eeprom_data,
  // AXI4-Stream input
  input  wire  [7:0] s_axis_tdata,
  input  wire        s_axis_tvalid,
  output logic       s_axis_tready,
  input  wire        s_axis_tlast,
  // AXI4-Stream output
  output logic [7:0] m_axis_tdata,
  output logic       m_axis_tvalid,
  input  wire        m_axis_tready,
  output logic       m_axis_tlast
);

  // GPIO connections
  logic [31:0] sync_manager_in[2];
  logic [31:0] sync_manager_out[2];
  assign sync_manager_in[0] = gpio_out;
  assign sync_manager_in[1] = gpio_in;
  assign gpio_out = sync_manager_out[0];

  // AXI4-Stream handshake
  assign s_axis_tready = m_axis_tready | ~m_axis_tvalid;

  // Internal AXI4-Stream
  logic [7:0] int_axis_tdata;
  logic       int_axis_tvalid;
  logic       int_axis_tlast;

  // Application Layer (AL) status parameters
  localparam [7:0]  AL_STATUS_INIT    = 8'h01;
  localparam [7:0]  AL_STATUS_PRE_OP  = 8'h02;
  localparam [7:0]  AL_STATUS_SAFE_OP = 8'h04;
  localparam [7:0]  AL_STATUS_OP      = 8'h08;
  localparam [15:0] AL_STATUS_CODE    = 16'h0000;

  // Address parameters
  localparam ADDR_ESC_INFORMATION               = 16'h0000;
  localparam ADDR_CONFIGURED_STATION_ADDRESS    = 16'h0010;
  localparam ADDR_CONFIGURED_STATION_ALIAS      = 16'h0012;
  localparam ADDR_ESC_DL_CONTROL                = 16'h0100;
  localparam ADDR_AL_CONTROL                    = 16'h0120;
  localparam ADDR_AL_STATUS                     = 16'h0130;
  localparam ADDR_EEPROM_CONFIGURATION          = 16'h0500;
  localparam ADDR_EEPROM_PDI_ACCESS_STATE       = 16'h0501;
  localparam ADDR_EEPROM_CONTROL_STATUS         = 16'h0502;
  localparam ADDR_EEPROM_ADDRESS                = 16'h0504;
  localparam ADDR_EEPROM_DATA                   = 16'h0508;
  localparam ADDR_FMMU_0                        = 16'h0600;
  localparam ADDR_FMMU_1                        = 16'h0610;
  localparam ADDR_SYNC_MANAGER_0                = 16'h0800;
  localparam ADDR_SYNC_MANAGER_1                = 16'h0808;

  // Capture the following information from the EtherCAT datagram header:
  // - Command         ( 8 bits)
  // - Index           ( 8 bits)
  // - Slave Address   (16 bits)
  // - Offset Address  (16 bits)
  // - Logical Address (32 bits)
  // - Length          (11 bits)
  // - Circulating     ( 1 bit)
  // - Next            ( 1 bit)
  // - IRQ             (16 bits)
  logic [ 7:0] ethercat_datagram_command;
  logic [ 7:0] ethercat_datagram_index;
  logic [15:0] ethercat_datagram_slave_address;
  logic [15:0] ethercat_datagram_offset_address;
  wire  [31:0] ethercat_datagram_logical_address = {ethercat_datagram_slave_address, ethercat_datagram_offset_address};
  logic [10:0] ethercat_datagram_length;
  logic        ethercat_datagram_circulating;
  logic        ethercat_datagram_next;
  logic [15:0] ethercat_datagram_irq;
  always_ff @(posedge clk) begin
    if (rst) begin
      ethercat_datagram_length <= 'd0;
    end else begin
      if (s_axis_tvalid & s_axis_tready) begin
        case (ethercat_datagram_counter[0])
          'd0: ethercat_datagram_command              <= s_axis_tdata;
          'd1: ethercat_datagram_index                <= s_axis_tdata;
          'd2: ethercat_datagram_slave_address[7:0]   <= s_axis_tdata;
          'd3: ethercat_datagram_slave_address[15:8]  <= s_axis_tdata;
          'd4: ethercat_datagram_offset_address[7:0]  <= s_axis_tdata;
          'd5: ethercat_datagram_offset_address[15:8] <= s_axis_tdata;
          'd6: ethercat_datagram_length[7:0]          <= s_axis_tdata;
          'd7: begin
            ethercat_datagram_length[10:8]            <= s_axis_tdata[2:0];
            ethercat_datagram_circulating             <= s_axis_tdata[6];
            ethercat_datagram_next                    <= s_axis_tdata[7];
          end
          'd8: ethercat_datagram_irq[7:0]             <= s_axis_tdata;
          'd9: ethercat_datagram_irq[15:8]            <= s_axis_tdata;
          default: ;
        endcase
      end
    end
  end

  // Detect EtherCAT datagram command
  localparam CMD_APRD = 1;
  localparam CMD_APWR = 2;
  localparam CMD_APRW = 3;
  localparam CMD_FPRD = 4;
  localparam CMD_FPWR = 5;
  localparam CMD_FPRW = 6;
  localparam CMD_BRD  = 7;
  localparam CMD_BWR  = 8;
  localparam CMD_BRW  = 9;
  localparam CMD_LRD  = 10;
  localparam CMD_LWR  = 11;
  localparam CMD_LRW  = 12;
  localparam CMD_ARMW = 13; // Not supported
  localparam CMD_FRMW = 14; // Not supported
  logic valid_address, logical_address, write_req, read_req, auto_increment, broadcast;
  wire read_write = write_req & read_req;
  always_comb begin
    valid_address   = 1'b0;
    logical_address = 1'b0;
    write_req       = 1'b0;
    read_req        = 1'b0;
    auto_increment  = 1'b0;
    broadcast       = 1'b0;
    case (ethercat_datagram_command)
      CMD_APRD: begin
        valid_address  = (ethercat_datagram_slave_address == 16'h0000);
        read_req       = 1'b1;
        auto_increment = 1'b1;
      end
      CMD_APWR: begin
        valid_address  = (ethercat_datagram_slave_address == 16'h0000);
        write_req      = 1'b1;
        auto_increment = 1'b1;
      end
      CMD_APRW: begin
        valid_address  = (ethercat_datagram_slave_address == 16'h0000);
        read_req       = 1'b1;
        write_req      = 1'b1;
        auto_increment = 1'b1;
      end
      CMD_FPRD: begin
        valid_address  = (ethercat_datagram_slave_address == configured_station_address);
        read_req       = 1'b1;
      end
      CMD_FPWR: begin
        valid_address  = (ethercat_datagram_slave_address == configured_station_address);
        write_req      = 1'b1;
      end
      CMD_FPRW: begin
        valid_address  = (ethercat_datagram_slave_address == configured_station_address);
        read_req       = 1'b1;
        write_req      = 1'b1;
      end
      CMD_BRD: begin
        valid_address  = 1'b1;
        read_req       = 1'b1;
        broadcast      = 1'b1;
      end
      CMD_BWR: begin
        valid_address  = 1'b1;
        write_req      = 1'b1;
        broadcast      = 1'b1;
      end
      CMD_BRW: begin
        valid_address  = 1'b1;
        read_req       = 1'b1;
        write_req      = 1'b1;
        broadcast      = 1'b1;
      end
      CMD_LRD: begin
        valid_address   = 1'b1;
        logical_address = 1'b1;
        read_req        = 1'b1;
      end
      CMD_LWR: begin
        valid_address   = 1'b1;
        logical_address = 1'b1;
        write_req       = 1'b1;
      end
      CMD_LRW: begin
        valid_address   = 1'b1;
        logical_address = 1'b1;
        read_req        = 1'b1;
        write_req       = 1'b1;
      end
      default: ;
    endcase
  end

  // Rewrite the EtherCAT datagram data
  logic calculate_carry;
  always_ff @(posedge clk) begin
    if (rst) begin
      int_axis_tvalid <= 1'b0;
      m_axis_tvalid   <= 1'b0;
    end else begin
      if (s_axis_tready) begin
        int_axis_tdata  <= s_axis_tdata;
        int_axis_tvalid <= s_axis_tvalid;
        int_axis_tlast  <= s_axis_tlast;
        m_axis_tdata    <= int_axis_tdata;
        m_axis_tvalid   <= int_axis_tvalid;
        m_axis_tlast    <= int_axis_tlast;
        if (auto_increment) begin
          if (ethercat_datagram_slave_address_region_upper) begin
            int_axis_tdata <= s_axis_tdata + {7'd0, calculate_carry};
          end else if (ethercat_datagram_slave_address_region_lower) begin
            {calculate_carry, int_axis_tdata} <= {1'd0, s_axis_tdata} + 'd1;
          end
        end
        if (valid_address) begin
          if (ethercat_datagram_data_region[1]) begin
            if (read_req & read_en) begin
              if (broadcast) begin
                m_axis_tdata <= read_data | int_axis_tdata;
              end else begin
                m_axis_tdata <= read_data;
              end
            end
          end else if (ethercat_working_counter_region[1]) begin
            if (write_success | read_success) begin
              if (ethercat_datagram_region_last[1]) begin
                m_axis_tdata <= int_axis_tdata + {7'd0, calculate_carry};
              end else begin
                {calculate_carry, m_axis_tdata} <= {1'd0, int_axis_tdata} +
                                                   {(~read_write)? 9'd1:
                                                                   (write_success & read_success)? 9'd3:
                                                                   (write_success)? 9'd2: 9'd1};
              end
            end
          end
        end
      end
    end
  end

  // Register control logics
  logic write_en, read_en;
  logic [7:0]   read_data;
  logic [15:0]  configured_station_address;
  logic [15:0]  configured_station_alias;
  logic [31:0]  esc_dl_control;
  logic [7:0]   al_status;
  logic [7:0]   eeprom_configuration;
  logic [7:0]   eeprom_pdi_access_state;
  logic [15:0]  eeprom_control_status;
  logic [127:0] fmmu[2];
  logic [63:0]  sync_manager[2];
  wire  [15:0]  target_offset_address  = ethercat_datagram_offset_address  + {4'd0,  ethercat_datagram_data_counter};
  wire  [31:0]  target_logical_address = ethercat_datagram_logical_address + {20'd0, ethercat_datagram_data_counter};
  always_ff @(posedge clk) begin
    if (rst) begin
      read_data                     <= 'd0;
      configured_station_address    <= 'd0;
      configured_station_alias      <= 'd0;
      esc_dl_control                <= 'd0;
      al_status                     <= AL_STATUS_INIT;
      eeprom_configuration          <= 'd0;
      eeprom_pdi_access_state       <= 'd0;
      eeprom_control_status         <= 'd0;
      eeprom_address                <= 'd0;
      fmmu[0]                       <= 'd0;
      fmmu[1]                       <= 'd0;
      sync_manager[0]               <= 'd0;
      sync_manager[1]               <= 'd0;
    end else begin
      if (s_axis_tvalid & s_axis_tready & valid_address & ethercat_datagram_data_region[0]) begin
        write_en <= 1'b0; read_en <= 1'b0; read_data <= 'd0;
        if (logical_address) begin
          if (fmmu_log_address_offset[0] < fmmu_log_length[0]) begin
            write_en <= fmmu_write_en[0]; read_en <= fmmu_read_en[0];
            case (fmmu_phys_address[0])
              sync_manager_address[0]: begin
                if (write_req & fmmu_write_en[0]) sync_manager_out[0][fmmu_log_address_offset[0]*8+:8] <= s_axis_tdata;
                if (read_req  & fmmu_read_en[0])  read_data <= sync_manager_in[0][fmmu_log_address_offset[0]*8+:8];
              end
              sync_manager_address[1]: begin
                if (write_req & fmmu_write_en[0]) sync_manager_out[1][fmmu_log_address_offset[0]*8+:8] <= s_axis_tdata;
                if (read_req  & fmmu_read_en[0])  read_data <= sync_manager_in[1][fmmu_log_address_offset[0]*8+:8];
              end
              default: ;
            endcase
          end else if (fmmu_log_address_offset[1] < fmmu_log_length[1]) begin
            write_en <= fmmu_write_en[1]; read_en <= fmmu_read_en[1];
            case (fmmu_phys_address[1])
              sync_manager_address[0]: begin
                if (write_req & fmmu_write_en[1]) sync_manager_out[0][fmmu_log_address_offset[1]*8+:8] <= s_axis_tdata;
                if (read_req  & fmmu_read_en[1])  read_data <= sync_manager_in[0][fmmu_log_address_offset[1]*8+:8];
              end
              sync_manager_address[1]: begin
                if (write_req & fmmu_write_en[1]) sync_manager_out[1][fmmu_log_address_offset[1]*8+:8] <= s_axis_tdata;
                if (read_req  & fmmu_read_en[1])  read_data <= sync_manager_in[1][fmmu_log_address_offset[1]*8+:8];
              end
              default: ;
            endcase
          end
        end else begin
          write_en <= 1'b1; read_en <= 1'b1;
          if (target_offset_address[15:1] == ADDR_ESC_INFORMATION[15:1]) begin
            write_en  <= 1'b0;
            if (read_req)  read_data <= 8'h00;
          end else if (target_offset_address[15:1] == ADDR_CONFIGURED_STATION_ADDRESS[15:1]) begin
            if (write_req) configured_station_address[target_offset_address[0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= configured_station_address[target_offset_address[0]*8+:8];
          end else if (target_offset_address[15:1] == ADDR_CONFIGURED_STATION_ALIAS[15:1]) begin
            if (write_req) configured_station_alias[target_offset_address[0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= configured_station_alias[target_offset_address[0]*8+:8];
          end else if (target_offset_address[15:2] == ADDR_ESC_DL_CONTROL[15:2]) begin
            if (write_req) esc_dl_control[target_offset_address[1:0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= esc_dl_control[target_offset_address[1:0]*8+:8];
          end else if (target_offset_address[15:0] == ADDR_AL_CONTROL[15:0]) begin
            if (write_req) al_status <= s_axis_tdata;
            if (read_req)  read_data <= al_status;
          end else if (target_offset_address[15:0] == ADDR_AL_STATUS[15:0]) begin
            write_en <= 1'b0;
            if (read_req)  read_data <= al_status;
          end else if (target_offset_address[15:0] == ADDR_EEPROM_CONFIGURATION[15:0]) begin
            if (write_req) eeprom_configuration <= s_axis_tdata;
            if (read_req)  read_data <= eeprom_configuration;
          end else if (target_offset_address[15:0] == ADDR_EEPROM_PDI_ACCESS_STATE[15:0]) begin
            if (write_req) eeprom_pdi_access_state <= s_axis_tdata;
            if (read_req)  read_data <= eeprom_pdi_access_state;
          end else if (target_offset_address[15:1] == ADDR_EEPROM_CONTROL_STATUS[15:1]) begin
            if (write_req) eeprom_control_status[target_offset_address[0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= eeprom_control_status[target_offset_address[0]*8+:8];
          end else if (target_offset_address[15:2] == ADDR_EEPROM_ADDRESS[15:2]) begin
            if (write_req) eeprom_address[target_offset_address[1:0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= eeprom_address[target_offset_address[1:0]*8+:8];
          end else if (target_offset_address[15:2] == ADDR_EEPROM_DATA[15:2]) begin
            write_en <= 1'b0;
            if (read_req)  read_data <= eeprom_data[target_offset_address[1:0]*8+:8];
          end else if (target_offset_address[15:4] == ADDR_FMMU_0[15:4]) begin
            if (write_req) fmmu[0][target_offset_address[3:0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= fmmu[0][target_offset_address[3:0]*8+:8];
          end else if (target_offset_address[15:4] == ADDR_FMMU_1[15:4]) begin
            if (write_req) fmmu[1][target_offset_address[3:0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= fmmu[1][target_offset_address[3:0]*8+:8];
          end else if (target_offset_address[15:3] == ADDR_SYNC_MANAGER_0[15:3]) begin
            if (write_req) sync_manager[0][target_offset_address[2:0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= sync_manager[0][target_offset_address[2:0]*8+:8];
          end else if (target_offset_address[15:3] == ADDR_SYNC_MANAGER_1[15:3]) begin
            if (write_req) sync_manager[1][target_offset_address[2:0]*8+:8] <= s_axis_tdata;
            if (read_req)  read_data <= sync_manager[1][target_offset_address[2:0]*8+:8];
          end else begin
            write_en <= 1'b0; read_en <= 1'b0; read_data <= 'd0;
          end
        end
      end
    end
  end

  // Write/Read success flags
  logic write_success, read_success;
  always_ff @(posedge clk) begin
    if (ethercat_datagram_slave_address_region_lower) begin
      write_success <= 1'b0;
      read_success  <= 1'b0;
    end else if (ethercat_datagram_data_region[1]) begin
      write_success <= (write_success | write_en) & write_req;
      read_success  <= (read_success  | read_en)  & read_req;
    end
  end

  // Count the Ethernet packet
  localparam ETHERNET_HEADER_LENGTH = 14;
  localparam ETHERCAT_HEADER_LENGTH = 2;
  logic [4:0] ethernet_counter;
  always_ff @(posedge clk) begin
    if (rst) begin
      ethernet_counter <= 'd0;
    end else begin
      if (s_axis_tvalid & s_axis_tready) begin
        if (s_axis_tlast) begin
          ethernet_counter <= 'd0;
        end else if (ethernet_counter < '1) begin
          ethernet_counter <= ethernet_counter + 'd1;
        end
      end
    end
  end

  // Count the EtherCAT datagram
  localparam ETHERCAT_DATAGRAM_HEADER_LENGTH = 10;
  localparam ETHERCAT_DATAGRAM_WORKING_COUNTER_LENGTH = 2;
  logic [11:0] ethercat_datagram_counter[2];
  always_ff @(posedge clk) begin
    if (rst) begin
      ethercat_datagram_counter[0] <= 'd0;
      ethercat_datagram_counter[1] <= 'd0;
    end else begin
      if (s_axis_tvalid & s_axis_tready) begin
        if (ethercat_datagram_region[0]) begin
          if (ethercat_datagram_region_last[0]) begin
            ethercat_datagram_counter[0] <= 'd0;
          end else if (ethercat_datagram_counter[0] < '1) begin
            ethercat_datagram_counter[0] <= ethercat_datagram_counter[0] + 'd1;
          end
        end
        if (ethercat_datagram_region[1]) begin
          if (ethercat_datagram_region_last[1]) begin
            ethercat_datagram_counter[1] <= 'd0;
          end else if (ethercat_datagram_counter[1] < '1) begin
            ethercat_datagram_counter[1] <= ethercat_datagram_counter[1] + 'd1;
          end
        end
      end
    end
  end

  // Detect the EtherCAT datagram region
  logic ethercat_datagram_region[2];
  always_ff @(posedge clk) begin
    if (rst) begin
      ethercat_datagram_region[0] <= 1'b0;
    end else begin
      if (s_axis_tvalid & s_axis_tready) begin
        if (ethercat_header_region_last) begin
          ethercat_datagram_region[0] <= 1'b1;
        end else if (~ethercat_datagram_next & ethercat_datagram_region_last[0]) begin
          ethercat_datagram_region[0] <= 1'b0;
        end
        ethercat_datagram_region[1] <= ethercat_datagram_region[0];
      end
    end
  end

  // Utility logics and wires
  logic [31:0] fmmu_log_address[2];
  assign fmmu_log_address[0] = fmmu[0][31:0];
  assign fmmu_log_address[1] = fmmu[1][31:0];

  logic [31:0] fmmu_log_address_offset[2];
  assign fmmu_log_address_offset[0] = target_logical_address - fmmu_log_address[0];
  assign fmmu_log_address_offset[1] = target_logical_address - fmmu_log_address[1];

  logic [15:0] fmmu_log_length[2];
  assign fmmu_log_length[0] = fmmu[0][47:32];
  assign fmmu_log_length[1] = fmmu[1][47:32];

  logic fmmu_write_en[2];
  assign fmmu_write_en[0] = fmmu[0][89];
  assign fmmu_write_en[1] = fmmu[1][89];

  logic fmmu_read_en[2];
  assign fmmu_read_en[0]  = fmmu[0][88];
  assign fmmu_read_en[1]  = fmmu[1][88];

  logic [15:0] fmmu_phys_address[2];
  assign fmmu_phys_address[0] = fmmu[0][79:64];
  assign fmmu_phys_address[1] = fmmu[1][79:64];

  logic [15:0] sync_manager_address[2];
  assign sync_manager_address[0] = sync_manager[0][15:0];
  assign sync_manager_address[1] = sync_manager[1][15:0];

  wire ethernet_header_region      = (ethernet_counter < ETHERNET_HEADER_LENGTH);
  wire ethernet_frame_region       = ~ethernet_header_region;
  wire ethercat_header_region      = ethernet_frame_region &
                                     (ethernet_counter < (ETHERNET_HEADER_LENGTH +
                                                          ETHERCAT_HEADER_LENGTH));
  wire ethercat_header_region_last = ethernet_frame_region &
                                     (ethernet_counter == (ETHERNET_HEADER_LENGTH +
                                                           ETHERCAT_HEADER_LENGTH - 1));

  wire [11:0] ethercat_datagram_data_counter = ethercat_datagram_counter[0] - ETHERCAT_DATAGRAM_HEADER_LENGTH;
  wire ethercat_datagram_slave_address_region_lower = (ethercat_datagram_counter[0] == 'd2);
  wire ethercat_datagram_slave_address_region_upper = (ethercat_datagram_counter[0] == 'd3);

  logic ethercat_datagram_data_region[2];
  assign ethercat_datagram_data_region[0] = (ethercat_datagram_counter[0] >= (ETHERCAT_DATAGRAM_HEADER_LENGTH)) &
                                            (ethercat_datagram_counter[0] <  (ETHERCAT_DATAGRAM_HEADER_LENGTH +
                                                                           ethercat_datagram_length));
  assign ethercat_datagram_data_region[1] = (ethercat_datagram_counter[1] >= (ETHERCAT_DATAGRAM_HEADER_LENGTH)) &
                                            (ethercat_datagram_counter[1] <  (ETHERCAT_DATAGRAM_HEADER_LENGTH +
                                                                           ethercat_datagram_length));

  logic ethercat_datagram_region_last[2];
  assign ethercat_datagram_region_last[0] = (ethercat_datagram_counter[0] == (ETHERCAT_DATAGRAM_HEADER_LENGTH +
                                                                              ethercat_datagram_length +
                                                                              ETHERCAT_DATAGRAM_WORKING_COUNTER_LENGTH - 1));
  assign ethercat_datagram_region_last[1] = (ethercat_datagram_counter[1] == (ETHERCAT_DATAGRAM_HEADER_LENGTH +
                                                                              ethercat_datagram_length +
                                                                              ETHERCAT_DATAGRAM_WORKING_COUNTER_LENGTH - 1));

  logic ethercat_working_counter_region[2];
  assign ethercat_working_counter_region[0] = (ethercat_datagram_counter[0] >= (ETHERCAT_DATAGRAM_HEADER_LENGTH +
                                                                                ethercat_datagram_length)) &
                                              (ethercat_datagram_counter[0] <  (ETHERCAT_DATAGRAM_HEADER_LENGTH +
                                                                                ethercat_datagram_length +
                                                                                ETHERCAT_DATAGRAM_WORKING_COUNTER_LENGTH));
  assign ethercat_working_counter_region[1] = (ethercat_datagram_counter[1] >= (ETHERCAT_DATAGRAM_HEADER_LENGTH +
                                                                                ethercat_datagram_length)) &
                                              (ethercat_datagram_counter[1] <  (ETHERCAT_DATAGRAM_HEADER_LENGTH +
                                                                                ethercat_datagram_length +
                                                                                ETHERCAT_DATAGRAM_WORKING_COUNTER_LENGTH));

endmodule

`default_nettype wire