CSE 370 Solution Set #9
Spring 2000
Total Points 20


In case you've already forgotten, here was the top level schematic you were given to start with showing the receipt of a good packet...

And here's the waveforms, which show the correct operation of the 4 modules, Framer, Destuff, S2P, & Chksum, which you had to fill in. All the relevant signals from those modules are bundled together in a single display. You could turn-in 3 waveforms like this or separate each module so there would be 4 sets of 3 waveforms. The 3 cases the waveforms show below are for a good packet, bad length packet, & bad checksum packet.

Good Packet:

Bad Length:

Bad Checksum:

 
 

Here's sample solutions to the verilog code for each of the 4 modules:

The Framer )
Here's a verilog implementation of the framer (you were not asked to do this in Verilog) It contains 2 4-bit shift registers. One watches the data for the start & stop flags, while the other shifts out the Pval output.

module framer(Sin, Reset, Clk, Sout, Pval)
     input Sin, Reset, Clk;
     output Sout, Pval;
     reg Sout, Pval;

     reg valid;
     ref[3:0] data_shift, next_dshift, valid_shift, next_vshift;

     assign Sout = next_dshift[0];
     assign Pval = next_vshift[0];

     always@(posedge Clk) begin
          if(Reset) begin
               data_shift = 4'b0000;
               valid_shift = 4'b0000;
               valid = 0;
          end
          else begin
               data_shift = next_dshift;
               valid_shift = next_vshift;
          end
     end

     always@(Sin or data_shift or valid_shift) begin
          next_dshift = {Sin, data_shift[3:1]};
          next_vshift = {valid, valid_shift[3:1]};

          if(next_dshift == 4'b0111) begin
               case(valid)
                    1'b0: valid = 1'b1;
                    1'b1: begin
                         valid = 1'b0;
                         next_vshift = 4'b0000;
                    end
               endcase
          end
     end
endmodule

Here is a schematic implementation of the Framer (which you were asked for):

The Destuffer )
This verilog module is very similar to last weeks except now we have an additional counter to track the length of the packet. Here's the state diagram from last week's HW where the input is Sin, Z is Sout & V is Sval. We reset the FSM when Pval is low.

module destuff(Clk, Reset, Pval, Sin, Sval, Sout, LenOK)
        input Clk, Reset, Pval, Sin;
        output Sval, Sout, LenOK;

        assign Sout = (next_state[1] && Pval); //data output is encoded in state bit 1
        assign Sval = (next_state[0] && Pval); //valid output is encoded in state bit 0
        assign LenOK = (~Pval && count == 20); //If Pval deasserts early the count doesn't reach 20

        reg [2:0] state, next_state;
        reg [4:0] count, next_count;

       `define S0 3'b001
       `define S1 3'b011
       `define S2 3'b111
       `define S3 3'b010
       `define SX 3'b000

       always @(posedge Clock) begin
           if(Reset) begin
              state = `S0;
              count = 5'b00000;
           end
           else begin
              state = next_state;
              if(Pval)
                    count = next_count;
              else
                    count = 5'b00000;
           end
        end

        always @(Sin or Pval or count or state) begin
            if(Pval) begin
                    case(state)
                    `S0: begin
                           if(Sin)
                                next_state = `S1;
                           else
                                next_state = `S0;
                    end

                   `S1: begin
                           if(Sin)
                                next_state = `S2;
                            else
                                next_state = `S0;
                    end

                    `S2: begin
                            if(Sin)
                                next_state = `SX;
                            else
                                next_state = `S3;
                     end

                     `S3: begin
                            if(Sin)
                                next_state = `S1;
                            else
                                 next_state = 'S0;
                      end

                    `SX: begin
                            if(Sin)
                                next_state = `SX;
                            else
                                next_state = `S3;
                    end

                default:
                      next_state = `S0;
                  endcase

                  if(Sval)
                        next_count = count + 1
                  else
                       next_count = count;

             end
             else begin
                     next_state = 'S0;
                     next_count = 5'b00001;
             end

        end // always block

endmodule

The S2P )
Here's a Verilog implementation of the S2P component (you were not asked for this). It has a 4-bit shift register that converts the serial signal to a 4-bit parallel value. The load values for the registers are controlled by a counter.

module s2p(Sin, Sval, D0, D1, D2, D3, Ld1, Ld2, Ld3, Ld4, LdChk, Reset, Clk);

     input Sin, Sval, Reset, Clk;
     output D0, D1, D2, D3, Ld1, Ld2, Ld3, Ld4, LdChk;

     reg D0, D1, D2, D3;
     reg[3:0] data_shift, next_dshift;
     reg[4:0] count, next_count, Load;

     always@(posedge Clk) begin
          if(Reset || next_count > 20) begin
               Load = 5'b00000;
               data_shift = 4'b0000;
               D3 = 0; D2 = 0; D1 = 0; D0 = 0;
               count = 4'b0001;
          end
          else begin
               count = next_count;
               data_shift = {next_dshift[3], next_dshift[2], next_dshift[1], next_dshift[0]};
          end
     end

     always@(Sin or count or data_shift) begin
          if(Sval) begin
               Load = 5'b00000;
               next_dshift = {Sin, data_shift[3], data_shift[2], data_shift[1]};
               D3 = data_shift[1];
               D2 = data_shift[2];
               D1 = data_shift[3];
               D0 = Sin;

               if(count == 4)
                    Load = 5'b00001;
               else if(count == 8)
                    Load = 5'b00010;
               else if(count = 12)
                    Load = 5'b00100;
               else if(count == 16)
                    Load = 5'b01000;
               else if(count == 20)
                    Load = 5'b10000;

               next_count = count + 1;
          end
     end

     assign LdChk = Load[4];
     assign Ld4 = Load[3];
     assign Ld3 = Load[2];
     assign Ld2 = Load[1];
     assign Ld1 = Load[0];

endmodule

Here is a schematic implementation of the S2P module. It has two components: Shift4, which is a 4 bit shift register, and SelectLoad which generates the correct load signals. Below this diagram you will find details about these two components.


Here is the schematic Shift4:

Now, here is the schematic for the SelectLoad part. The idea is to have a counter that a 20 counter, and detect the appopriate count values: 4 for Ld1, 8 for Ld2, 12 for Ld3, 16 for Ld4 and 20 for LdChk.

Finally, here the schematic for the counter. We use a conter from primlog, and we reset it by loading in 0 when it gets to 20. Note that we also reset the counter when Sval is low for two clock cycles or more (we do this with the two flip-flops at the bottom of the diagram). The reason for doing this is that during the transmission, Sval should never go low for more than one cycle, since we only insert one stuffing bit at a time. Thus, if Sval is low for more than one clock cycle, this is an indication that the patcket transmission has ended. In addition, the two flip-flops will also keep the counter reset to 0 until new data arrives.

The Chksum )
Here's the simple checksum module that controls the ALU based on the Ld input values. Each time we load a value we add it to the accumulator until LdChk is asserted. Then we subtract the 4-bit checksum from the accumulator to see if the result is zero (no error).

module chksum(LdChk, Ld4, Ld3, Ld2, Ld1, Zero, ChkOK, PktRcvd, OP0, OP1, Load, Clk, Reset);

     input LdChk, Ld4, Ld3, Ld2, Ld1, Zero, Clk, Reset;
     output ChkOK, PktRcvd, OP0, OP1, Load;

     reg OP0, OP1;

     assign Load = (Ld1 || Ld2 || Ld3 || Ld4 || LdChk);
     assign PktRcvd = LdChk;
     assign ChkOK = (Zero && LdChk);

     always@(posedge Clk) begin
          if(Reset) begin
               OP0 = 0;
               OP1 = 0;
          end
     end

     always@(Ld1 or Ld2 or Ld3 or Ld4 or LdChk) begin
          if(Ld1) begin
               OP0 = 0; OP1 = 1;
          end
          else if(Ld2 || Ld3 || Ld4) begin
               OP0 = 0; OP1 = 0;
          end
          else if(LdChk) begin
               OP0 = 1; OP1 = 0;

          end
     end
endmodule