Previous Section Next Section

12.2 DUT HDL Source Code

Example 12-1 shows the Verilog source code used to describe the DUT router.

Example 12-1 DUT HDL Source Code
//****************************************************************/
//Source code for the Router DUT
//Contains the following modules
//top: top level module that instantiates the router
//router: router DUT instantiates three fifo modules +
//        port_fsm(state machine)
//port_fsm: Implements the router state machine.
//fifo: Implements the fifo that holds data for each channel
//****************************************************************/
//****************************************************************/
//Source code for fifo module
module fifo (clock,
             write_enb,
             read_enb,
             data_in,
             data_out,
             empty,
             full);
input     clock;
input write_enb;
input read_enb;
input  [7:0] data_in;
output [7:0] data_out;
output empty;
output full;

// Port Signals
wire     clock;
wire write_enb;
wire read_enb;
wire   [7:0] data_in;
reg    [7:0] data_out;
wire empty;
wire full;

// Internal Signals
reg      [7:0] ram[0:15];
reg            tmp_empty;
reg            tmp_full;
integer        write_ptr;
integer        read_ptr;

// Processes
   initial begin
      data_out  = 8'b0000_0000;
      tmp_empty = 1'b1;
      tmp_full  = 1'b0;
      write_ptr = 0;
      read_ptr  = 0;
   end

   assign empty = tmp_empty;
   assign full  = tmp_full;
 always @(posedge clock) begin : fifo_core
      if ((write_enb == 1'b1) &&  (tmp_full == 1'b0)) begin
         ram[write_ptr] = data_in;
         tmp_empty <= 1'b0;
         write_ptr = (write_ptr + 1) % 16;
         if ( read_ptr == write_ptr ) begin
            tmp_full <= 1'b1;
         end //if
      end //if

 if ((read_enb == 1'b1) &&  (tmp_empty == 1'b0)) begin
         data_out <= ram[read_ptr];
         tmp_full <= 1'b0;
         read_ptr = (read_ptr + 1) % 16;
         if ( read_ptr == write_ptr ) begin
            tmp_empty <= 1'b1;
         end //if
      end //if
   end  //fifo_core;
endmodule //fifo

//**************************************************************/
//Source code for port_fsm module (DUT State Machine)
`define ADDR_WAIT    4'b0000
`define DATA_LOAD    4'b0001
`define PARITY_LOAD  4'b0010
`define HOLD_STATE   4'b0011
`define BUSY_STATE   4'b0100
module port_fsm (clock,
                 suspend_data_in,
                 err,
                 write_enb,
                 fifo_empty,
                 hold,
                 packet_valid,
                 data_in,
                 data_out,
                 addr);
input      clock;
output     suspend_data_in;
output     err;
output[2:0]  write_enb;
input  fifo_empty;
input      hold;
input      packet_valid;
input[7:0]  data_in;
output[7:0]  data_out;
output  [1:0]     addr;
reg [7:0]  data_out;
reg [1:0]  addr;
// Internal Signals
reg    [2:0] write_enb_r;
reg          fsm_write_enb;
reg    [3:0] state_r;
reg    [3:0] state;
reg    [7:0] parity;
reg    [7:0] parity_delayed;
reg          sus_data_in;
// Processes
  initial begin
       err            = 1'b0;
       data_out       = 8'b0000_0000;
       addr           = 2'b00;
       write_enb_r    = 3'b000;
       fsm_write_enb  = 1'b0;
       state_r        = 4'b0000;
       state          = 4'b0000;
       parity         = 8'b0000_0000;
       parity_delayed = 8'b0000_0000;
       sus_data_in    = 1'b0;
  end
  assign suspend_data_in = sus_data_in;
  always @(packet_valid) begin : addr_mux
    if (packet_valid == 1'b1) begin
      case (data_in[1:0])
      2'b00 :  begin
            write_enb_r[0] = 1'b1;
            write_enb_r[1] = 1'b0;
            write_enb_r[2] = 1'b0;
      end
      2'b01 :  begin
        write_enb_r[0] = 1'b0;
        write_enb_r[1] = 1'b1;
        write_enb_r[2] = 1'b0;
       end
      2'b10 :  begin
        write_enb_r[0] = 1'b0;
        write_enb_r[1] = 1'b0;
        write_enb_r[2] = 1'b1;
      end
      default :write_enb_r = 3'b000;
    endcase
    end //if
end //addr_mux;
 always @(posedge clock) begin : fsm_state
     state_r <= state;
  end //fsm_state;

  always @(state_r or packet_valid or fifo_empty or hold or data_in)
  begin : fsm_core
  state = state_r;   //Default state assignment
      case (state_r)
        `ADDR_WAIT :   begin
                  //transition//
                  if ((packet_valid == 1'b1) &&
                      (2'b00 <= data_in[1:0]) &&
                      (data_in[1:0] <= 2'b10)) begin
                     if (fifo_empty == 1'b1) begin
                       state = `DATA_LOAD;
                     end
                     else begin
                       state = `BUSY_STATE;
                     end //if
                   end //if;
                  //combinational//
                  sus_data_in = !fifo_empty;
                  if ((packet_valid == 1'b1) &&
                      (2'b00 <= data_in[1:0]) &&
                      (data_in[1:0] <= 2'b10) &&
                      (fifo_empty == 1'b1)) begin
                          addr = data_in[1:0];
                          data_out  = data_in;
                          fsm_write_enb = 1'b1;
                  end
                  else begin
                      fsm_write_enb = 1'b0;
                  end //if
                end // of case ADDR_WAIT
         `PARITY_LOAD : begin
                  //transition//
                  state = `ADDR_WAIT;
                  //combinational//
                  data_out = data_in;
                  fsm_write_enb = 1'b0;
                end // of case PARITY_LOAD
         `DATA_LOAD :   begin
              //transition//
              if ((packet_valid == 1'b1) &&
               (hold == 1'b0)) begin
                  state = `DATA_LOAD
              end
              else if ((packet_valid == 1'b0) &&
              (hold == 1'b0)) begin
                  state = `PARITY_LOAD;
              end
              else begin
                  state = `HOLD_STATE;
              end  //if
              //combinational//
             sus_data_in = 1'b0;
             if ((packet_valid == 1'b1) &&
               (hold == 1'b0)) begin
                  data_out = data_in;
                  fsm_write_enb = 1'b1;
             end
             else if ((packet_valid == 1'b0) &&
              (hold == 1'b0)) begin
                  data_out = data_in;
                  fsm_write_enb = 1'b1;
             end
             else begin
             fsm_write_enb = 1'b0;
             end //if
        end  //end of case DATA_LOAD
       `HOLD_STATE :  begin
                  //transition//
             if (hold == 1'b1) begin
                  state = `HOLD_STATE;
             end
             else if ((hold == 1'b0) && (packet_valid == 1'b0)) begin
                  state = `PARITY_LOAD;
             end
             else begin
                  state = `DATA_LOAD;
             end //if
                  //combinational
             if (hold == 1'b1) begin
                   sus_data_in = 1'b1;
                   fsm_write_enb = 1'b0
             end
             else begin
                   fsm_write_enb = 1'b1;
                   data_out = data_in;
             end //if
         end  //end of case HOLD_STATE
            `BUSY_STATE :  begin
             //transition//
             if (fifo_empty == 1'b0) begin
                   state = `BUSY_STATE;
             end
             else begin
                   state = `DATA_LOAD;
             end //if
             //combinational//
             if (fifo_empty == 1'b0) begin
                   sus_data_in = 1'b1;
             end
             else begin
                   addr = data_in[1:0]; // hans
                   data_out  = data_in;
                   fsm_write_enb = 1'b1;
             end //if
         end  //end of case BUSY_STATE
   endcase
  end //fsm_core

  assign write_enb[0] = write_enb_r[0] & fsm_write_enb;
  assign write_enb[1] = write_enb_r[1] & fsm_write_enb;
  assign write_enb[2] = write_enb_r[2] & fsm_write_enb;

  always @(posedge clock) begin : parity_calc
      parity_delayed <= parity;
      err <= 1'b0;
      if ((packet_valid == 1'b1) && (sus_data_in == 1'b0)) begin
        parity <= parity ^ data_in;
      end
      else if (packet_valid == 1'b0) begin
        if ((state_r == `PARITY_LOAD) && (parity_delayed != data_in))         begin
          err <= 1'b1;
        end
        else begin
          err <= 1'b0;
        end //if
    parity <= 8'b0000_0000;
    end //if
  end //parity_calc;
endmodule //port_fsm
//*******************************************************************/
//*******************************************************************/
//Source code for module router, instantiates 3 fifo modules +
//port_fsm (State machine for router)
module router (clock,
               packet_valid,
               data,
               channel0,
               channel1,
               channel2,
               vld_chan_0,
               vld_chan_1,
               vld_chan_2,
               read_enb_0,
               read_enb_1,
               read_enb_2,
               suspend_data_in,
               err);
input          clock;
input          packet_valid;
input    [7:0] data;
output   [7:0] channel0;
output   [7:0] channel1;
output   [7:0] channel2;
output         vld_chan_0;
output       vld_chan_1;
output       vld_chan_2;
input       read_enb_0;
input       read_enb_1;
input       read_enb_2;
output         suspend_data_in;
output         err;
// Internal Signals
wire   [7:0] data_out_0;
wire   [7:0] data_out_1;
wire   [7:0] data_out_2;
wire full_0;
wire full_1;
wire full_2;
wire empty_0;
wire empty_1;
wire empty_2;
wire fifo_empty;
wire fifo_empty0;
wire fifo_empty1;
wire fifo_empty2;
wire hold_0;
wire hold_1;
wire hold_2;
wire hold;
wire   [2:0] write_enb;
wire   [7:0] data_out_fsm;
wire   [1:0] addr;

// Instantiations
  fifo queue_0 (.clock     (clock),
                .write_enb (write_enb[0]),
                .read_enb  (read_enb_0),
                .data_in   (data_out_fsm),
                .data_out  (data_out_0),
                .empty     (empty_0),
                .full      (full_0));

  fifo queue_1 (.clock     (clock),
                .write_enb (write_enb[1]),
                .read_enb  (read_enb_1),
                .data_in   (data_out_fsm),
                .data_out  (data_out_1),
                .empty     (empty_1),
                .full      (full_1));

  fifo queue_2 (.clock     (clock),
                .write_enb (write_enb[2]),
                .read_enb  (read_enb_2),
                .data_in   (data_out_fsm),
                .data_out  (data_out_2),
                .empty     (empty_2),
                .full      (full_2));

  port_fsm in_port (.clock           (clock),
                    .suspend_data_in (suspend_data_in),
                    .err             (err),
                    .write_enb       (write_enb),
                    .fifo_empty      (fifo_empty),
                    .hold            (hold),
                    .packet_valid    (packet_valid),
                    .data_in         (data),
                    .data_out        (data_out_fsm),

                    .addr            (addr));
// Processes
  assign channel0 = data_out_0;   //make note assignment only for
                                  //consistency with vlog env
  assign channel1 = data_out_1;
  assign channel2 = data_out_2;

  assign vld_chan_0 = !empty_0;
  assign vld_chan_1 = !empty_1;
  assign vld_chan_2 = !empty_2;

  assign fifo_empty0 = (empty_0 | ( addr[1] |  addr[0])); //addr!=00
  assign fifo_empty1 = (empty_1 | ( addr[1] | !addr[0])); //addr!=01
  assign fifo_empty2 = (empty_2 | (!addr[1] |  addr[0])); //addr!=10

  assign fifo_empty  = fifo_empty0 & fifo_empty1 & fifo_empty2;

  assign hold_0 = (full_0 & (!addr[1] & !addr[0])); //addr=00
  assign hold_1 = (full_1 & (!addr[1] &  addr[0])); //addr=01
  assign hold_2 = (full_2 & ( addr[1] & !addr[0])); //addr=10
  assign hold   = hold_0 | hold_1 | hold_2;
endmodule //router
//*******************************************************************/
//Source code for top level module
//Instantiates the router module
module top();
  reg          clock;
  reg          packet_valid;
  reg    [7:0] data;
  wire   [7:0] channel0;
  wire   [7:0] channel1;
  wire   [7:0] channel2;
  wire         vld_chan_0;
  wire         vld_chan_1;
  wire         vld_chan_2;
  reg          read_enb_0;
  reg          read_enb_1;
  reg          read_enb_2;
  wire         suspend_data_in;
  wire         err;

  router router1 (.clock          (clock),
                  .packet_valid   (packet_valid),
                  .data           (data),
                  .channel0       (channel0),
                  .channel1       (channel1),
                  .channel2       (channel2),
                  .vld_chan_0     (vld_chan_0),
                  .vld_chan_1     (vld_chan_1),
                  .vld_chan_2     (vld_chan_2),
                  .read_enb_0     (read_enb_0),
                  .read_enb_1     (read_enb_1),
                   .read_enb_2     (read_enb_2),
                  .suspend_data_in(suspend_data_in),
                  .err            (err));
// Processes
   initial begin
      packet_valid = 1'b0;
      data         = 8'b0000_0000;
      read_enb_0   = 1'b0;
      read_enb_1   = 1'b0;
      read_enb_2   = 1'b0;
   end

   initial begin
      clock = 0;
      forever begin
         #50 clock = !clock;
      end
   end
endmodule //top
Previous Section Next Section