1

The following is the top level module of a VC707 based Microblaze/PS2 controller.

I have connected a FMC-CE GPIO Daughter Card to the FMC1 Connector on the FPGA and a PMOD-PS2 on the 6 pin GPIO header on the board.

enter image description here

What do I need to do to pass DRC?

MMIO Unit

`include "chu_io_map.svh"
module mmio_sys_sampler_arty_a7
#(
  parameter N_SW = 8,
            N_LED = 8
)   
(
     (* dont_touch = "true" *) input  logic clk,
     (* dont_touch = "true" *) input  logic reset,
   // FPro bus 
     (* dont_touch = "true" *)input   logic mmio_cs,
     (* dont_touch = "true" *)input   logic mmio_wr,
     (* dont_touch = "true" *)input   logic mmio_rd,
     (* dont_touch = "true" *) input  logic [20:0] mmio_addr, 
     (* dont_touch = "true" *)input   logic [31:0] mmio_wr_data,
     (* dont_touch = "true" *)output  logic [31:0] mmio_rd_data,
   // uart
     (* dont_touch = "true" *) input logic rx,
     (* dont_touch = "true" *)output  logic tx,          
   // ps2
     inout  tri ps2d,
     inout  tri ps2c
);

   //declaration
   logic [63:0] mem_rd_array;
   logic [63:0] mem_wr_array;
   logic [63:0] cs_array;
   logic [4:0] reg_addr_array [63:0];
   logic [31:0] rd_data_array [63:0]; 
   logic [31:0] wr_data_array [63:0];
   logic [15:0] adsr_env;

   // body
   // instantiate mmio controller 
   chu_mmio_controller ctrl_unit
   (.clk(clk),
    .reset(reset),
    .mmio_cs(mmio_cs),
    .mmio_wr(mmio_wr),
    .mmio_rd(mmio_rd),
    .mmio_addr(mmio_addr), 
    .mmio_wr_data(mmio_wr_data),
    .mmio_rd_data(mmio_rd_data),
    // slot interface
    .slot_cs_array(cs_array),
    .slot_mem_rd_array(mem_rd_array),
    .slot_mem_wr_array(mem_wr_array),
    .slot_reg_addr_array(reg_addr_array),
    .slot_rd_data_array(rd_data_array), 
    .slot_wr_data_array(wr_data_array)
    );

   // slot 1: UART 
   chu_uart #(.FIFO_DEPTH_BIT(8))  uart_slot1 
   (.clk(clk),
    .reset(reset),
    .cs(cs_array[`S1_UART1]),
    .read(mem_rd_array[`S1_UART1]),
    .write(mem_wr_array[`S1_UART1]),
    .addr(reg_addr_array[`S1_UART1]),
    .rd_data(rd_data_array[`S1_UART1]),
    .wr_data(wr_data_array[`S1_UART1]), 
    .tx(tx),
    .rx(rx)
    );


   // slot 11: ps2 
    chu_ps2_core #(.W_SIZE(6)) ps2_slot11 
    (.clk(clk),
     .reset(reset),
     .cs(cs_array[`S11_PS2]),
     .read(mem_rd_array[`S11_PS2]),
     .write(mem_wr_array[`S11_PS2]),
     .addr(reg_addr_array[`S11_PS2]),
     .rd_data(rd_data_array[`S11_PS2]),
     .wr_data(wr_data_array[`S11_PS2]),
     .ps2d(ps2d),
     .ps2c(ps2c)
     );


   // assign 0's to all unused slot rd_data signals
   generate
      genvar i;
      for (i=14; i<64; i=i+1) begin
         assign rd_data_array[i] = 32'h0;
      end
   endgenerate
endmodule

UART

// 
//  Reg map (each port uses 4 address space)
//    * 0: read data and status
//    * 1: write baud rate 
//    * 2: write data 
//    * 3: dummy write to remove data from head of rx FIFO 
//
module chu_uart
   #(parameter  FIFO_DEPTH_BIT = 8)  // # addr bits of FIFO
   (
        (* dont_touch = "true" *) input  logic clk,
        (* dont_touch = "true" *)input   logic reset,
    // slot interface
        (* dont_touch = "true" *) input  logic cs,
        (* dont_touch = "true" *) input  logic read,
        (* dont_touch = "true" *)input   logic write,
        (* dont_touch = "true" *)  input logic [4:0] addr,
        (* dont_touch = "true" *)input   logic [31:0] wr_data,
       (* dont_touch = "true" *)  output [31:0] rd_data,
       (* dont_touch = "true" *) output logic tx,
        (* dont_touch = "true" *)  input logic rx    
   );

   // signal declaration
   logic wr_uart, rd_uart, wr_dvsr ;
   logic tx_full, rx_empty;
   logic [10:0] dvsr_reg;
   logic [7:0] r_data;
   logic ctrl_reg;

   // body
   // instantiate uart
   uart #(.DBIT(8), .SB_TICK(16), .FIFO_W(FIFO_DEPTH_BIT)) uart_unit    
   (.clk(clk), .reset(reset), .rd_uart(rd_uart), .wr_uart(wr_uart), .rx(rx), .dvsr(dvsr_reg), .w_data(wr_data[7:0]), .tx_full(tx_full), .rx_empty(rx_empty), .tx(tx), .r_data(rd_data[7:0]) );

   // dvsr register
   always_ff @(posedge clk, posedge reset)
      if (reset)
         dvsr_reg <= 0;
      else   
         if (wr_dvsr)
            dvsr_reg <= wr_data[10:0];
   // decoding logic
   assign wr_dvsr = (write && cs && (addr[1:0]==2'b01));
   assign wr_uart = (write && cs && (addr[1:0]==2'b10));
   assign rd_uart = (write && cs && (addr[1:0]==2'b11));
   // slot read interface
   assign rd_data = {22'h000000, tx_full,  rx_empty, r_data};
endmodule

UART UNIT

// 
//  Reg map (each port uses 4 address space)
//    * 0: read data and status
//    * 1: write baud rate 
//    * 2: write data 
//    * 3: dummy write to remove data from head of rx FIFO 
//
module chu_uart
   #(parameter  FIFO_DEPTH_BIT = 8)  // # addr bits of FIFO
   (
        (* dont_touch = "true" *) input  logic clk,
        (* dont_touch = "true" *)input   logic reset,

        (* dont_touch = "true" *) input  logic cs,
        (* dont_touch = "true" *) input  logic read,
        (* dont_touch = "true" *)input   logic write,
        (* dont_touch = "true" *)  input logic [4:0] addr,
        (* dont_touch = "true" *)input   logic [31:0] wr_data,
       (* dont_touch = "true" *)  output [31:0] rd_data,
       (* dont_touch = "true" *) output logic tx,
        (* dont_touch = "true" *)  input logic rx    
   );


   logic wr_uart, rd_uart, wr_dvsr ;
   logic tx_full, rx_empty;
   logic [10:0] dvsr_reg;
   logic [7:0] r_data;
   logic ctrl_reg;


   uart #(.DBIT(8), .SB_TICK(16), .FIFO_W(FIFO_DEPTH_BIT)) uart_unit    
   (.clk(clk), .reset(reset), .rd_uart(rd_uart), .wr_uart(wr_uart), .rx(rx), .dvsr(dvsr_reg), .w_data(wr_data[7:0]), .tx_full(tx_full), .rx_empty(rx_empty), .tx(tx), .r_data(rd_data[7:0]) );

   // dvsr register
   always_ff @(posedge clk, posedge reset)
      if (reset)
         dvsr_reg <= 0;
      else   
         if (wr_dvsr)
            dvsr_reg <= wr_data[10:0];
   // decoding logic
   assign wr_dvsr = (write && cs && (addr[1:0]==2'b01));
   assign wr_uart = (write && cs && (addr[1:0]==2'b10));
   assign rd_uart = (write && cs && (addr[1:0]==2'b11));
   // slot read interface
   assign rd_data = {22'h000000, tx_full,  rx_empty, r_data};
endmodule

BAUD Unit

// baud rate generater (divisor) 
// divided by (dvsr+1)
// Listing 12.1
module baud_gen
   (
      (* dont_touch = "true" *)input  logic clk, reset,
      (* dont_touch = "true" *)input  logic [10:0] dvsr,
      (* dont_touch = "true" *)output logic tick
   );

   // declaration
   logic [10:0] r_reg;
   logic [10:0] r_next;

   // body
   // register
   always_ff @(posedge clk, posedge reset)
   begin
      if (reset)
         r_reg <= 0;
      else
         r_reg <= r_next;
   end

   // next-state logic
   assign r_next = (r_reg==dvsr) ? 0 : r_reg + 1;
   // output logic
   assign tick = (r_reg==1);
endmodule

UART RX

 module uart_rx
       #(
        parameter DBIT = 8,     // # data bits
                  SB_TICK = 16  // # ticks for stop bits
       )
       (
          (* dont_touch = "true" *)input  logic clk, reset,
            (* dont_touch = "true" *) input  logic rx, s_tick,
          (* dont_touch = "true" *)output logic rx_done_tick,
          (* dont_touch = "true" *)output logic [7:0] dout
       );

       // fsm state type 
       typedef enum {idle, start, data, stop} state_type;

       // signal declaration
       state_type state_reg, state_next;
       logic [3:0] s_reg, s_next;
       logic [2:0] n_reg, n_next;
       logic [7:0] b_reg, b_next;

       // body
       // FSMD state & data registers
       always_ff @(posedge clk, posedge reset)
       begin
          if (reset) begin
             state_reg <= idle;
         s_reg <= 0;
         n_reg <= 0;
         b_reg <= 0;
      end
      else begin
         state_reg <= state_next;
         s_reg <= s_next;
         n_reg <= n_next;
         b_reg <= b_next;
      end
   end

   // FSMD next-state logic
   always_comb
   begin
      state_next = state_reg;
      rx_done_tick = 1'b0;
      s_next = s_reg;
      n_next = n_reg;
      b_next = b_reg;
      case (state_reg)
         idle:
            if (~rx) begin
               state_next = start;
               s_next = 0;
            end
         start:
            if (s_tick)
               if (s_reg==7) begin
                  state_next = data;
                  s_next = 0;
                  n_next = 0;
               end
               else
                  s_next = s_reg + 1;
         data:
            if (s_tick)
               if (s_reg==15) begin
                  s_next = 0;
                  b_next = {rx, b_reg[7:1]};
                  if (n_reg==(DBIT-1))
                     state_next = stop ;
                  else
                     n_next = n_reg + 1;
               end
               else
                  s_next = s_reg + 1;
         stop:
            if (s_tick)
               if (s_reg==(SB_TICK-1)) begin
                  state_next = idle;
                  rx_done_tick =1'b1;
               end
               else
                  s_next = s_reg + 1;
      endcase
   end
   // output
   assign dout = b_reg;
endmodule

UART Tx

 module uart_tx
       #(
        parameter DBIT = 8,     // # data bits
                  SB_TICK = 16  // # 16 ticks for 1 stop bit
       )
       (
         (* dont_touch = "true" *)input  logic clk, reset,
          (* dont_touch = "true" *)input  logic tx_start, s_tick,
          (* dont_touch = "true" *)input  logic [7:0] din,
          (* dont_touch = "true" *)output logic tx_done_tick,
          (* dont_touch = "true" *)output logic tx
       );

       // fsm state type 
       typedef enum {idle, start, data, stop} state_type;

       // signal declaration
       state_type state_reg, state_next;
       logic [3:0] s_reg, s_next;
       logic [2:0] n_reg, n_next;
       logic [7:0] b_reg, b_next;
       logic tx_reg, tx_next;

       // body
       // FSMD state & data registers
       always_ff @(posedge clk, posedge reset)
       begin
          if (reset) begin
             state_reg <= idle;
             s_reg <= 0;
             n_reg <= 0;
             b_reg <= 0;
             tx_reg <= 1'b1;
          end
          else begin
             state_reg <= state_next;
             s_reg <= s_next;
             n_reg <= n_next;
             b_reg <= b_next;
             tx_reg <= tx_next;
          end
       end

       // FSMD next-state logic & functional units
       always_comb
       begin
          state_next = state_reg;
          tx_done_tick = 1'b0;
          s_next = s_reg;
          n_next = n_reg;
          b_next = b_reg;
          tx_next = tx_reg ;
          case (state_reg)
             idle: begin
                tx_next = 1'b1;
                if (tx_start) begin
                   state_next = start;
                   s_next = 0;
                   b_next = din;
                end
             end
             start: begin
                tx_next = 1'b0;
                if (s_tick)
                   if (s_reg==15) begin
                      state_next = data;
                      s_next = 0;
                      n_next = 0;
                   end
                   else
                      s_next = s_reg + 1;
             end
             data: begin
                tx_next = b_reg[0];
                if (s_tick)
                   if (s_reg==15) begin
                      s_next = 0;
                      b_next = b_reg >> 1;
                      if (n_reg==(DBIT-1))
                         state_next = stop ;
                      else
                         n_next = n_reg + 1;
                   end
                   else
                      s_next = s_reg + 1;
             end
             stop: begin
                tx_next = 1'b1;
                if (s_tick)
                   if (s_reg==(SB_TICK-1)) begin
                      state_next = idle;
                      tx_done_tick = 1'b1;
                   end
                   else
                     s_next = s_reg + 1;
             end
          endcase
       end
       // output
       assign tx = tx_reg;
    endmodule

FIFO

 module fifo
       #(
        parameter DATA_WIDTH=8, // number of bits in a word
                  ADDR_WIDTH=4  // number of address bits
       )
       (
         (* dont_touch = "true" *) input  logic clk, reset,
          (* dont_touch = "true" *)input  logic rd, wr,
          (* dont_touch = "true" *)input  logic [DATA_WIDTH-1:0] w_data,
          (* dont_touch = "true" *)output logic empty, full,
          (* dont_touch = "true" *)output logic [DATA_WIDTH-1:0] r_data
       );

       //signal declaration
       logic [ADDR_WIDTH-1:0] w_addr, r_addr;
       logic wr_en, full_tmp;

       // body
       // write enabled only when FIFO is not full
       assign wr_en = wr & ~full_tmp;
       assign full = full_tmp;

       // instantiate fifo control unit
       fifo_ctrl #(.ADDR_WIDTH(ADDR_WIDTH)) c_unit
          (.clk(clk), .reset(reset), .rd(rd), .wr(wr), .empty(empty), .full(full_tmp), .w_addr(w_addr), .r_addr(r_addr));

       // instantiate register file
       reg_file 
          #(.DATA_WIDTH(DATA_WIDTH), .ADDR_WIDTH(ADDR_WIDTH)) f_unit (.clk(clk), .wr_en(wr_en), .w_addr(w_addr), .r_addr(r_addr), .w_data(w_data), .r_data(r_data));

    endmodule

Fifo Ctrl

module fifo_ctrl
   #(
    parameter ADDR_WIDTH=4  // number of address bits
   )
   (
      (* dont_touch = "true" *)input  logic clk, reset,
      (* dont_touch = "true" *)input  logic rd, wr,
      (* dont_touch = "true" *) output logic empty, full,
      (* dont_touch = "true" *)output logic [ADDR_WIDTH-1:0] w_addr,
      (* dont_touch = "true" *)output logic [ADDR_WIDTH-1:0] r_addr
   );

   //signal declaration
   logic [ADDR_WIDTH-1:0] w_ptr_logic, w_ptr_next, w_ptr_succ;
   logic [ADDR_WIDTH-1:0] r_ptr_logic, r_ptr_next, r_ptr_succ;
   logic full_logic, empty_logic, full_next, empty_next;

   // body
   // fifo control logic
   always_ff @(posedge clk, posedge reset)
   begin
      if (reset)
         begin
            w_ptr_logic <= 0;
            r_ptr_logic <= 0;
            full_logic <= 1'b0;
            empty_logic <= 1'b1;
         end
      else
         begin
            w_ptr_logic <= w_ptr_next;
            r_ptr_logic <= r_ptr_next;
            full_logic <= full_next;
            empty_logic <= empty_next;
         end
    end
   // next-state logic for read and write pointers
   always_comb 
   begin
      // successive pointer values
      w_ptr_succ = w_ptr_logic + 1;
      r_ptr_succ = r_ptr_logic + 1;
      // default: keep old values
      w_ptr_next = w_ptr_logic;
      r_ptr_next = r_ptr_logic;
      full_next = full_logic;
      empty_next = empty_logic;
      unique case ({wr, rd})
         2'b01: // read
            if (~empty_logic) // not empty
               begin
                  r_ptr_next = r_ptr_succ;
                  full_next = 1'b0;
                  if (r_ptr_succ==w_ptr_logic)
                     empty_next = 1'b1;
               end
         2'b10: // write
            if (~full_logic) // not full
               begin
                  w_ptr_next = w_ptr_succ;
                  empty_next = 1'b0;
                  if (w_ptr_succ==r_ptr_logic)
                     full_next = 1'b1;
               end
         2'b11: // write and read
            begin
               w_ptr_next = w_ptr_succ;
               r_ptr_next = r_ptr_succ;
            end
         default: ;  // 2'b00; null statement; no op
      endcase
   end

   // output
   assign w_addr = w_ptr_logic;
   assign r_addr = r_ptr_logic;
   assign full = full_logic;
   assign empty = empty_logic;
endmodule

Reg File

// Listing 7.2
module reg_file
   #(
    parameter DATA_WIDTH = 8, // number of bits
              ADDR_WIDTH = 2  // number of address bits
   )
   (
      (* dont_touch = "true" *)input  logic clk,
      (* dont_touch = "true" *)input  logic wr_en,
      (* dont_touch = "true" *)input  logic [ADDR_WIDTH-1:0] w_addr, r_addr,
      (* dont_touch = "true" *)input  logic [DATA_WIDTH-1:0] w_data,
      (* dont_touch = "true" *)output logic [DATA_WIDTH-1:0] r_data
   );

   // signal declaration
   logic [DATA_WIDTH-1:0] array_reg [0:2**ADDR_WIDTH-1];

   // body
   // write operation
   always_ff @(posedge clk)
   begin
      if (wr_en)
         array_reg[w_addr] <= w_data;
   end
   // read operation
   assign r_data = array_reg[r_addr];
endmodule

PS2 Core

(* keep_hierarchy = "yes" *)
module chu_ps2_core
   #(parameter W_SIZE = 6)   // # address bits in FIFO buffer
   (
      (* dont_touch = "true" *)input  logic clk,
      (* dont_touch = "true" *)input  logic reset,
    // slot interface
      (* dont_touch = "true" *)input  logic cs,
      (* dont_touch = "true" *)input  logic read,
      (* dont_touch = "true" *)input  logic write,
      (* dont_touch = "true" *)input  logic [4:0] addr,
      (* dont_touch = "true" *)input  logic [31:0] wr_data,
      (* dont_touch = "true" *)output logic [31:0] rd_data,
    // external ports    
      inout  tri ps2d, ps2c
   );

   // declaration
   logic [7:0] ps2_rx_data;
   logic rd_fifo, ps2_rx_buf_empty;
   logic wr_ps2, ps2_tx_idle;

   // body
   // instantiate PS2 controller   
   ps2_top #(.W_SIZE(W_SIZE)) ps2_unit
      (.clk(clk), .reset(reset), .wr_ps2(wr_ps2), .rd_ps2_packet(rd_fifo), .ps2_tx_data(wr_data[7:0]), .ps2_rx_data(ps2_rx_data), .ps2_tx_idle(ps2_tx_idle), .ps2_rx_buf_empty(ps2_rx_buf_empty), .ps2d(ps2d), .ps2c(ps2c)); 

   // decoding and read multiplexing
   // remove an item from FIFO  
   assign rd_fifo = cs & read & (addr[1:0]==2'b11);
   // write data to PS2 transmitting subsystem  
   assign wr_ps2 = cs & write & (addr[1:0]==2'b10);
   //  read data multiplexing
   assign rd_data = {22'b0, ps2_tx_idle, ps2_rx_buf_empty, ps2_rx_data}; 
endmodule  

PS2 Top

(* keep_hierarchy = "yes" *)
module ps2_top
   #(parameter W_SIZE = 6)   // # address bits in FIFO buffer
   (
     (* dont_touch = "true" *) input  logic clk, reset,
      (* dont_touch = "true" *)input  logic wr_ps2, rd_ps2_packet,
      (* dont_touch = "true" *)input  logic [7:0] ps2_tx_data,
      (* dont_touch = "true" *)output logic [7:0] ps2_rx_data,
      (* dont_touch = "true" *)output logic ps2_tx_idle, ps2_rx_buf_empty,
      inout  tri ps2d, ps2c
   );

   // declaration
   logic rx_idle, tx_idle, rx_done_tick;
   logic [7:0] rx_data;
   // body
   // instantiate ps2 transmitter
   ps2tx ps2_tx_unit
      (.clk(clk), .reset(reset), .wr_ps2(wr_ps2), .rx_idle(rx_idle), .din(ps2_tx_data), .tx_idle(tx_idle), .tx_done_tick(), .ps2d(ps2d), .ps2c(ps2c));
   // instantiate ps2 receiver
   ps2rx ps2_rx_unit
      (.clk(clk), .reset(reset), .ps2d(ps2d), .ps2c(ps2c), .rx_en(tx_idle), .rx_idle(rx_idle), .rx_done_tick(rx_done_tick), .dout(rx_data));

   // instantiate FIFO buffer
   fifo #(.DATA_WIDTH(8), .ADDR_WIDTH(W_SIZE)) fifo_unit
      (.clk(clk), .reset(reset), .rd(rd_ps2_packet),
       .wr(rx_done_tick), .w_data(rx_data), .empty(ps2_rx_buf_empty),
       .full(), .r_data(ps2_rx_data));
   //output 
   assign ps2_tx_idle = tx_idle;
endmodule

PS2 Tx

module ps2tx
   (
      (* dont_touch = "true" *)input  logic clk, reset,
      (* dont_touch = "true" *)input  logic wr_ps2, rx_idle,
      (* dont_touch = "true" *)input  logic [7:0] din,
      (* dont_touch = "true" *)output logic tx_idle, tx_done_tick,
      inout  tri ps2d, ps2c
   );
   // fsm state type 
   typedef enum {idle, waitr, rts, start, data, stop} state_type;

   // declaration
   state_type state_reg, state_next;
   logic [7:0] filter_reg;
   logic [7:0] filter_next;
   logic f_ps2c_reg;
   logic f_ps2c_next;
   logic [3:0] n_reg, n_next;
   logic [8:0] b_reg, b_next;
   logic [12:0] c_reg, c_next;
   logic par, fall_edge;
   logic ps2c_out, ps2d_out;
   logic tri_c, tri_d;

   // body
   //*****************************************************************
   // filter and falling-edge tick generation for ps2c
   //*****************************************************************
   always_ff @(posedge clk, posedge reset)
   begin
   if (reset)
      begin
         filter_reg <= 0;
         f_ps2c_reg <= 0;
      end
   else
      begin
         filter_reg <= filter_next;
         f_ps2c_reg <= f_ps2c_next;
      end
   end
   assign filter_next = {ps2c, filter_reg[7:1]};
   assign f_ps2c_next = (filter_reg==8'b11111111) ? 1'b1 :
                        (filter_reg==8'b00000000) ? 1'b0 :
                         f_ps2c_reg;
   assign fall_edge = f_ps2c_reg & ~f_ps2c_next;
   //*****************************************************************
   // FSMD
   //*****************************************************************
   // state & data registers
   always_ff @(posedge clk, posedge reset)
   begin
      if (reset) begin
         state_reg <= idle;
         c_reg <= 0;
         n_reg <= 0;
         b_reg <= 0;
      end
      else begin
         state_reg <= state_next;
         c_reg <= c_next;
         n_reg <= n_next;
         b_reg <= b_next;
      end
   end
   // odd parity bit
   assign par = ~(^din);
   // next-state logic
   always_comb
   begin
      state_next = state_reg;
      c_next = c_reg;
      n_next = n_reg;
      b_next = b_reg;
      tx_done_tick = 1'b0;
      ps2c_out = 1'b1;
      ps2d_out = 1'b1;
      tri_c = 1'b0;
      tri_d = 1'b0;
      tx_idle = 1'b0;
      case (state_reg)
         idle: begin
            tx_idle = 1'b1;
            if (wr_ps2) begin
               b_next = {par, din};
               c_next = 13'h1fff; // 2^13-1
               state_next = waitr;
            end
         end
         waitr:
            if (rx_idle)
               state_next = rts;         
         rts: begin  // request to send
            ps2c_out = 1'b0;
            tri_c = 1'b1;
            c_next = c_reg - 1;
            if (c_reg==0)
               state_next = start;
         end
         start: begin // assert start bit
            ps2d_out = 1'b0;
            tri_d = 1'b1;
            if (fall_edge)
            begin n_next = 4'h8;
               state_next = data;
            end
         end
         data: begin  //  8 data + 1 parity        
            ps2d_out = b_reg[0];
            tri_d = 1'b1;
            if (fall_edge) begin
               b_next = {1'b0, b_reg[8:1]};
               if (n_reg == 0)
                  state_next = stop;
               else
                  n_next = n_reg - 1;
            end
         end
         default:   // assume floating high for ps2d
            if (fall_edge) begin
              state_next = idle;
              tx_done_tick = 1'b1;
           end
      endcase
   end
   // tristate buffers
   assign ps2c = (tri_c) ? ps2c_out : 1'bz;
   assign ps2d = (tri_d) ? ps2d_out : 1'bz;
endmodule

PS2 Rx

module ps2rx
   (
      (* dont_touch = "true" *)input  logic clk, reset, rx_en,
      inout  tri ps2d, ps2c, 
      (* dont_touch = "true" *)output logic rx_idle, rx_done_tick,
      (* dont_touch = "true" *)output logic [7:0] dout
   );

   // fsm state type 
   typedef enum {idle, dps, load} state_type;

   // declaration
   state_type state_reg, state_next;
   logic [7:0] filter_reg;
   logic [7:0] filter_next;
   logic f_ps2c_reg;
   logic f_ps2c_next;
   logic [3:0] n_reg, n_next;
   logic [10:0] b_reg, b_next;
   logic fall_edge;

   // body
   //*****************************************************************
   // filter and falling-edge tick generation for ps2c
   //*****************************************************************
   always_ff @(posedge clk, posedge reset)
       begin
       if (reset) begin
          filter_reg <= 0;
          f_ps2c_reg <= 0;
       end
       else begin
          filter_reg <= filter_next;
          f_ps2c_reg <= f_ps2c_next;
       end
   end
   assign filter_next = {ps2c, filter_reg[7:1]};
   assign f_ps2c_next = (filter_reg==8'b11111111) ? 1'b1 :
                        (filter_reg==8'b00000000) ? 1'b0 :
                         f_ps2c_reg;
   assign fall_edge = f_ps2c_reg & ~f_ps2c_next;
   //*****************************************************************
   // FSMD
   //*****************************************************************
   // state & data registers
   always_ff @(posedge clk, posedge reset)
   begin
      if (reset) begin
         state_reg <= idle;
         n_reg <= 0;
         b_reg <= 0;
      end
      else begin
         state_reg <= state_next;
         n_reg <= n_next;
         b_reg <= b_next;
      end
   end

   // next-state logic
   always_comb
   begin
      state_next = state_reg;
      rx_idle = 1'b0;
      rx_done_tick = 1'b0;
      n_next = n_reg;
      b_next = b_reg;
      case (state_reg)
         idle: begin
            rx_idle = 1'b1;
            if (fall_edge & rx_en) begin
               // shift in start bit
               b_next = {ps2d, b_reg[10:1]};
               n_next = 4'b1001;
               state_next = dps;
            end
         end
         dps:  // 8 data + 1 parity + 1 stop
            if (fall_edge) begin
               b_next = {ps2d, b_reg[10:1]};
               if (n_reg==0)
                  state_next = load;
               else
                  n_next = n_reg - 1;
               end
         default: begin // 1 extra clock to complete last shift
            state_next = idle;
            rx_done_tick = 1'b1;
         end
      endcase
   end
   // output
   assign dout = b_reg[8:1];  // data bits
endmodule
Vahe
  • 171
  • 1
  • 11

1 Answers1

1

Pins D15 and D18 are connected to the DDR3 memory. I presume you read the table wrong in the manual as those are the pin names on the FMC connector itself, so try G39 for ps2d and P42 for ps2c.

Edit: try making ps2d and ps2c input instead of inout in the ps2 rx module. Better idea would be to replace each pin with three - input, output, and tristate/oe and then converting that to a tristate buffer with two assigns at the top level. Snaking tristate signals around a design is a recipe for weird stuff like this as tristate signals cannot be routed inside most FPGAs.

alex.forencich
  • 40,694
  • 1
  • 68
  • 109
  • I still receive the same critical synthesis error and DRC failure after modifying XDC file. Also, to clarify I want to use the first of two FMC connectors on the board. – Vahe Mar 06 '19 at 22:39
  • In that case, I think you're going to have to post some more code, following the problematic signal up the hierarchy. – alex.forencich Mar 06 '19 at 22:42
  • Errors Synthesis[Synth 8-5744] Inout buffer is not created at top module for ps2d/ps2c [DRC REQP-1582] /ps2_tx_unit/ps2c_IOBUF_inst pin IO drives one or more invalid loads. XDC Constraint File set_property -dict {PACKAGE_PIN AV40 IOSTANDARD LVCMOS18} [get_ports reset] set_property -dict {PACKAGE_PIN G39 IOSTANDARD LVCMOS18} [get_ports ps2d] set_property -dict {PACKAGE_PIN P42 IOSTANDARD LVCMOS18} [get_ports ps2c] – Vahe Mar 06 '19 at 23:43
  • Supporting info above – Vahe Mar 06 '19 at 23:43
  • Thank You, moving the tri states to top level module resolved the issue. Thanks! – Vahe Mar 07 '19 at 01:52