Possible Verilog encoding of Universal Asynchronous Receiver

Possible Verilog encoding of Universal Asynchronous Receiver

The following Verilog code has five major sub-modules:

As with all good synchronous modules, a global_reset signal is included so that the latches can be put into a known state at the start of testing.

The code follows:

        // Universal Asynchronous Receiver

        // Start detection
        module start_detect (valid, clk, reset, gl_reset, dIn);
        output       valid;
        input        clk, reset, gl_reset, dIn;
        reg    [3:0] shift_reg;

        always @ (posedge clk) begin
             if (reset | gl_reset)
                  shift_reg = 0;
             else
                  shift_reg = { shift_reg[2:0], dIn };
             end

        assign valid = (shift_reg [0] == 0) &
                       (shift_reg [2] == 0) &
                       (shift_reg [3] == 1);

        endmodule

        // controller
        module counter (count72, count8, clk, enable);
        output       count72, count8;
        input        clk, enable;
        wire         each8;
        reg    [8:0] count_reg;

        always @ (posedge clk)
             if (enable == 0)
                  count_reg <= 0;
             else begin
                  count_reg <= count_reg + 1;
             end

        assign each8   = ((count_reg % 8) == 7);
        assign count72 = (count_reg == 71);
        assign count8  = each8 & ~count72;

        endmodule

        // serial parallel converter
        module ser_par_conv (dOut, clk, enable, dIn);
        output [7:0] dOut;
        input        clk, enable, dIn;
        reg    [7:0] dOut;

        always @ (posedge clk)
             if (enable == 1)
                  dOut = {dIn, dOut[7:1]};

        endmodule

        // flags for ready and data error
        module flags (dReady, dError,  clk, set,  reset, dIn);
        output dReady, dError;
        input  clk, set,  reset, dIn;
        reg    dReady, dError;

        always @(posedge clk)
             if (reset == 1) begin
                  dReady = 0;
                  dError = 0;
                  end
             else if (set == 1) begin
                  dReady <= dIn;
                  dError <= ~dIn;
                  end

        initial $monitor("dReady %b %b", dReady, dError, $time);

        endmodule

        // generating the run signals
        module control (running, clk, reset, gl_reset, set);
        output running;
        input  clk, reset, gl_reset, set;
        reg    running;

        always @ (posedge clk)
             if ((reset == 1) | (gl_reset == 1))
                  running  =  0;
             else if (set == 1)
                  running = 1;
        endmodule

        // overall receiver definition
        module uar (dOut, dReady, dError, clk, gl_reset, dIn);
        output [7:0] dOut;
        output       dReady, dError;
        input        clk, gl_reset, dIn;

        wire         running, finish, count8, start;

        start_detect s_d (start, clk, running, gl_reset, dIn);
        counter      cov (finish, count8, clk, running);
        ser_par_conv s_p (dOut, clk, count8, dIn);
        flags        fla (dReady, dError, clk, finish, start, dIn);
        control      con (running, clk, finish, gl_reset, start);

        endmodule

        // test module
        module mytest;
        reg   clk, gl_reset, dIn;
        wire  [7:0] dOut;
        wire  dReady, dError;

        reg [7:0] inWord;

        uar mod1 (dOut, dReady, dError, clk, gl_reset, dIn);

        always #5 clk = ~clk;

        initial begin

             #0
             clk = 0;
             gl_reset = 1;
             inWord = 0;
             dIn = 1;
             #10
             gl_reset = 0;

             #80
             repeat (4) begin
                  // start of cycle

                  inWord = {$random} /2 % 128;
                  dIn = 1;

                  #80
                  dIn = 0;
                  #80
                  $display ("inWord = %b", inWord, $time);
                  repeat (8) begin
                       dIn    <= inWord[0];
                       inWord <= inWord >> 1;
                       #80;
                       end
                  $display ("outWord = %b (%b %b)", dOut, dReady, dError);
                  end
             // error condition 1
             dIn = 1;
             #80
             dIn = 0;
             #800
             $display ("outWord = %b (%b %b)", dOut, dReady, dError);
             $finish;
             end
        endmodule