| // Copyright lowRISC contributors. | |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | |
| // SPDX-License-Identifier: Apache-2.0 | |
| module gpiodpi | |
| #( | |
| parameter string NAME = "gpio0", | |
| parameter N_GPIO = 32 | |
| )( | |
| input logic clk_i, | |
| input logic rst_ni, | |
| output logic [N_GPIO-1:0] gpio_p2d, | |
| input logic [N_GPIO-1:0] gpio_d2p, | |
| input logic [N_GPIO-1:0] gpio_en_d2p | |
| ); | |
| import "DPI-C" function | |
| chandle gpiodpi_create(input string name, input int n_bits); | |
| import "DPI-C" function | |
| void gpiodpi_device_to_host(input chandle ctx, input [N_GPIO-1:0] gpio_d2p, | |
| input [N_GPIO-1:0] gpio_en_d2p); | |
| import "DPI-C" function | |
| void gpiodpi_close(input chandle ctx); | |
| import "DPI-C" function | |
| int gpiodpi_host_to_device_tick(input chandle ctx, | |
| input [N_GPIO-1:0] gpio_en_d2p); | |
| chandle ctx; | |
| initial begin | |
| ctx = gpiodpi_create(NAME, N_GPIO); | |
| end | |
| final begin | |
| gpiodpi_close(ctx); | |
| end | |
| logic [N_GPIO-1:0] gpio_d2p_r; | |
| always_ff @(posedge clk_i) begin | |
| gpio_d2p_r <= gpio_d2p; | |
| if (gpio_d2p_r != gpio_d2p) begin | |
| gpiodpi_device_to_host(ctx, gpio_d2p, gpio_en_d2p); | |
| end | |
| end | |
| logic gpio_write_pulse; | |
| always_ff @(posedge clk_i or negedge rst_ni) begin | |
| if (!rst_ni) begin | |
| gpio_p2d <= '0; // default value | |
| end else if (gpio_write_pulse) begin | |
| gpio_p2d <= gpiodpi_host_to_device_tick(ctx, gpio_en_d2p); | |
| end | |
| end | |
| // gpiodpio_host_to_device_tick() will be called every MAX_COUNT | |
| // clock posedges; this should be kept reasonably high, since each | |
| // tick call will perform at least one syscall. | |
| localparam MAX_COUNT = 2048; | |
| logic [$clog2(MAX_COUNT)-1:0] counter; | |
| assign gpio_write_pulse = counter == MAX_COUNT -1; | |
| always_ff @(posedge clk_i or negedge rst_ni) begin | |
| if (!rst_ni) begin | |
| counter <= '0; | |
| end else if (gpio_write_pulse) begin | |
| counter <= '0; | |
| end else begin | |
| counter <= counter + 1'b1; | |
| end | |
| end | |
| endmodule |