Example 12-1 shows the Verilog source code used to describe the DUT router.
//****************************************************************/ //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