module vram_RAMDP_20X16_GL_M1_E2 (
 w0_addr,
 w0_clk,
 w0_bwe,
 w0_din,
 r0_addr,
 r0_clk,
 r0_dout,
    clamp_o
);
parameter words = 20;
parameter bits = 16;
parameter addrs = 5;
input [addrs-1:0] w0_addr;
input w0_clk;
input [bits-1:0] w0_din;
input [bits-1:0] w0_bwe;
input [addrs-1:0] r0_addr;
input r0_clk;
input clamp_o;
output [bits-1:0] r0_dout;
integer a;
`ifndef SYNTHESIS
`ifdef FAULT_INJECTION
// regs for inducing faults
 reg [bits-1:0] fault_no_write; // block writes to this column
 reg [bits-1:0] fault_stuck_0; // column always reads as 0
 reg [bits-1:0] fault_stuck_1; // column always reads as 1
 reg [bits-1:0] bit_fault_stuck_0[0:words-1]; // column always reads as 0
 reg [bits-1:0] bit_fault_stuck_1[0:words-1]; // column always reads as 1
 initial begin : init_bit_fault_stuck
   integer i;
   integer j;
   fault_no_write = {bits{1'b0}};
   fault_stuck_0 = {bits{1'b0}};
   fault_stuck_1 = {bits{1'b0}};
   for (i=0; i<=words; i=i+1) begin
       bit_fault_stuck_0[i] = {bits{1'b0}};
       bit_fault_stuck_1[i] = {bits{1'b0}};
   end
 end
`endif //def FAULT_INJECTION
`ifdef MONITOR
//VCS coverage off
// monitor variables
reg monitor_on;
reg dump_monitor_result;
// this monitors coverage including redundancy cols
// 1'bx = not accessed
// 1'b0 = accessed as a 0
// 1'b1 = accessed as a 1
// 1'bz = accessed as both 0 and 1
reg [bits-1:0] bit_written[0:words-1];
reg [bits-1:0] bit_read[0:words-1];
initial begin : init_monitor
  monitor_on = 1'b0;
  dump_monitor_result = 1'b0;
  for(a=0;a<words;a=a+1) begin
      bit_written[a] = {bits{1'bx}};
      bit_read[a] = {bits{1'bx}};
  end
end
always @(dump_monitor_result) begin : dump_monitor
    integer r;
 integer c;
    integer b;
 reg [16-1:0] tmp_row;
     if (dump_monitor_result == 1'b1) begin
      $display("Exercised coverage summary:");
      $display("\t%m bits not written as 0:");
      for (r=0; r<20; r=r+1) begin
          tmp_row = bit_written[r];
       for (c=0; c<16; c=c+1) begin
        if (tmp_row[c] !== 1'b0 && tmp_row[c] !== 1'bz) $display("\t\t[row,col] [%d,%d]", r, c);
       end
      end
            $display("\t%m bits not written as 1:");
      for (r=0; r<20; r=r+1) begin
          tmp_row = bit_written[r];
       for (c=0; c<16; c=c+1) begin
        if (tmp_row[c] !== 1'b1 && tmp_row[c] !== 1'bz) $display("\t\t[row,col] [%d,%d]", r, c);
       end
      end
      $display("\t%m bits not read as 0:");
      for (r=0; r<20; r=r+1) begin
          tmp_row = bit_read[r];
       for (c=0; c<16; c=c+1) begin
        if (tmp_row[c] !== 1'b0 && tmp_row[c] !== 1'bz) $display("\t\t[row,col] [%d,%d]", r, c);
       end
      end
      $display("\t%m bits not read as 1:");
      for (r=0; r<20; r=r+1) begin
          tmp_row = bit_read[r];
       for (c=0; c<16; c=c+1) begin
        if (tmp_row[c] !== 1'b1 && tmp_row[c] !== 1'bz) $display("\t\t[row,col] [%d,%d]", r, c);
       end
      end
        end
 dump_monitor_result = 1'b0;
end
//VCS coverage on
`endif //MONITOR
`endif //ndef SYNTHESIS
//memory array
 reg [bits-1:0] array[0:words-1];
// Bit write enable
`ifndef SYNTHESIS
    `ifdef FAULT_INJECTION
        wire [bits-1:0] bwe_with_fault = w0_bwe & ~fault_no_write;
        wire [bits-1:0] re_with_fault = ~(bit_fault_stuck_1[r0_addr] | bit_fault_stuck_0[r0_addr]);
    `else
        wire [bits-1:0] bwe_with_fault = w0_bwe;
        wire [bits-1:0] re_with_fault = {bits{1'b1}};
    `endif //def FAULT_INJECTION
`else
    wire [bits-1:0] bwe_with_fault = w0_bwe;
`endif //SYNTHESIS
//write function
    wire [bits-1:0] bitclk = {bits{w0_clk}} & bwe_with_fault;
    genvar idx;
    generate
        for (idx=0; idx<bits; idx=idx+1)
        begin : write
            always @(bitclk[idx] or w0_clk or w0_addr or w0_din[idx])
            begin
                if (bitclk[idx] && w0_clk)
                begin
                    array[w0_addr][idx] <= w0_din[idx]; // spyglass disable SYNTH_5130, W18
                    `ifndef SYNTHESIS
                    `ifdef MONITOR
//VCS coverage off
                    if (monitor_on) begin
         case (bit_written[w0_addr][idx])
             1'bx: bit_written[w0_addr][idx] = w0_din[idx];
             1'b0: bit_written[w0_addr][idx] = w0_din[idx] == 1 ? 1'bz : 1'b0;
             1'b1: bit_written[w0_addr][idx] = w0_din[idx] == 0 ? 1'bz : 1'b1;
             1'bz: bit_written[w0_addr][idx] = 1'bz;
         endcase
                    end
//VCS coverage on
                    `endif //MONITOR	    
                    `endif //SYNTHESIS	
                end
            end
        end
    endgenerate
//read function
 wire [bits-1:0] r0_arr;
`ifndef SYNTHESIS
    `ifdef FAULT_INJECTION
     assign r0_arr = (array[r0_addr] | bit_fault_stuck_1[r0_addr]) & ~bit_fault_stuck_0[r0_addr]; //read fault injection
    `else
     assign r0_arr = array[r0_addr];
    `endif //def FAULT_INJECTION
`else
    assign r0_arr = array[r0_addr]; // spyglass disable SYNTH_5130
`endif //def SYNTHESIS
    wire r0_clk_d0p1, r0_clk_read, r0_clk_reset_collision;
    assign #0.1 r0_clk_d0p1 = r0_clk;
    assign r0_clk_read = r0_clk_d0p1 & r0_clk; // spyglass disable GatedClock
    assign r0_clk_reset_collision = r0_clk | r0_clk_d0p1; // spyglass disable W402b
`ifndef SYNTHESIS
`ifdef MONITOR
//VCS coverage off
    always @(r0_clk_read) begin
        if (monitor_on) begin
            for (a=0; a<bits; a=a+1) begin
             if (re_with_fault[a] && r0_clk_read) begin
                 case (bit_read[r0_addr][a])
               1'bx: bit_read[r0_addr][a] = array[r0_addr][a];
            1'b0: bit_read[r0_addr][a] = array[r0_addr][a] == 1 ? 1'bz : 1'b0;
            1'b1: bit_read[r0_addr][a] = array[r0_addr][a] == 0 ? 1'bz : 1'b1;
            1'bz: bit_read[r0_addr][a] = 1'bz;
              endcase
             end
         end
        end
    end
//VCS coverage on
`endif //MONITOR
`endif //SYNTHESIS
 reg [bits-1:0] collision_ff;
    wire [bits-1:0] collision_ff_clk = {bits{w0_clk}} & {bits{r0_clk_read}} & {bits{r0_addr==w0_addr}} & bwe_with_fault; //spyglass disable GatedClock
    genvar bw;
    generate
        for (bw=0; bw<bits; bw=bw+1)
        begin : collision
         always @(posedge collision_ff_clk[bw] or negedge r0_clk_reset_collision) begin
                if (!r0_clk_reset_collision)
                    begin
                        collision_ff[bw] <= 1'b0;
                    end
                else
                    begin
                        collision_ff[bw] <= 1'b1;
                    end
            end
        end
    endgenerate
 reg [bits-1:0] r0_dout_tmp;
 always @(*)
 begin
     if (r0_clk_read) begin
            for (a=0; a<bits; a=a+1) begin
                r0_dout_tmp[a] <= ( collision_ff[a] | (r0_addr==w0_addr & w0_clk & bwe_with_fault[a]) ) ? 1'bx : r0_arr[a] & ~clamp_o; //spyglass disable STARC-2.10.1.6, W18
            end
        end
    end
    wire [bits-1:0] r0_dout = r0_dout_tmp & {bits{~clamp_o}};
`ifndef SYNTHESIS
//VCS coverage off
task mem_wr_raw;
  input [addrs-1:0] addr;
  input [bits-1:0] data;
  begin
    array[addr] = data;
  end
endtask
function [bits-1:0] mem_read_raw;
input [addrs-1:0] addr;
 mem_read_raw = array[addr];
endfunction
`ifdef FAULT_INJECTION
// induce faults on columns
task mem_fault_no_write;
  input [bits-1:0] fault_mask;
   begin
    fault_no_write = fault_mask;
  end
endtask
task mem_fault_stuck_0;
  input [bits-1:0] fault_mask;
  integer i;
   begin
    for ( i=0; i<words; i=i+1 ) begin
      bit_fault_stuck_0[i] = fault_mask;
    end
  end
endtask
task mem_fault_stuck_1;
  input [bits-1:0] fault_mask;
  integer i;
   begin
    for ( i=0; i<words; i=i+1 ) begin
      bit_fault_stuck_1[i] = fault_mask;
    end
  end
endtask
task set_bit_fault_stuck_0;
  input r;
  input c;
  integer r;
  integer c;
  bit_fault_stuck_0[r][c] = 1;
endtask
task set_bit_fault_stuck_1;
  input r;
  input c;
  integer r;
  integer c;
  bit_fault_stuck_1[r][c] = 1;
endtask
task clear_bit_fault_stuck_0;
  input r;
  input c;
  integer r;
  integer c;
  bit_fault_stuck_0[r][c] = 0;
endtask
task clear_bit_fault_stuck_1;
  input r;
  input c;
  integer r;
  integer c;
  bit_fault_stuck_1[r][c] = 0;
endtask
//VCS coverage on
`endif //def FAULT_INJECTION
`endif //ndef SYNTHESIS
endmodule