0
votes

I am looking to design a serial to parallel converter in Verilog which converts a fast clock serial input to a slower clock parallel input. I tried the following code which works in RTL but does not verify on Cadence Conformal. nclk is 16 times faster than clk. The serial data comes in at nclk and the parallel data is intended to come out at clk rate.

sEEG - Serial Input eegOut - Parallel output

I can only have clk and nclk as my operation references due to tape-out bond pad limitations.

Following is the code that I have come up with which works well in functional simulation but Formal Verification fails.

module deserializer(sEEG, nclk, clk, eegOut);
    input sEEG;
    input nclk,clk;
    reg [15:0] temp;
    output reg [15:0] eegOut;
    reg [4:0] i;
    
    always @(negedge nclk) begin
        temp[i] = sEEG;
        i = i + 1;
    end

    always@(posedge clk) begin
        i<=0;
        eegOut <= temp;
    end
endmodule
1

1 Answers

0
votes

I feel you should use four bits in order to index 16 elements. If you parameterize the module, this could be done with:

# (parameter WIDTH = 16)

then later use it as:

localparam BIT_SEL = $clog2(WIDTH); //..this should give you "4" if WIDTH = 16
reg [BIT_SEL-1:0] i;

Also, you might want to include a clock synchronizer, you don't want metastability problems, an easy way to do this is to include "double-triggers", practically is to buffer the data and replicate it to the next slow clock cycle (adds 1 slow clock cycle latency). So, maybe this works:

module deserializer
# (parameter WIDTH = 16)
(sEEG, nclk, clk, eegOut);
    input sEEG;
    input nclk,clk;
    reg [WIDTH-1:0] temp;
    reg [WIDTH-1:0] temp_reg; //..synchronizer
    output reg [WIDTH-1:0] eegOut;
    
    always @(negedge nclk) begin
        temp[WIDTH-2:0] <= temp[WIDTH-1:1];
        temp[WIDTH-1]   <= sEEG;
    end

    always@(posedge clk) begin
        temp_reg <= temp;
        eegOut   <= temp_reg;
    end
endmodule