0% found this document useful (0 votes)
148 views

Router

This document describes the design and verification of a simple switch module. The switch module has one input interface to receive packets and four output interfaces to send packets to their destination ports based on the packet header. The module contains a top-level switch module instance with a port state machine module and four FIFO queue modules. A verification environment is also specified containing modules to drive and receive test packets and check results.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
148 views

Router

This document describes the design and verification of a simple switch module. The switch module has one input interface to receive packets and four output interfaces to send packets to their destination ports based on the packet header. The module contains a top-level switch module instance with a port state machine module and four FIFO queue modules. A verification environment is also specified containing modules to drive and receive test packets and check results.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 21

............DUT SPECIFICATION ..................... Configuration ..................... Interface Specification ..................... Memory Interface ..................... Input Interface .....................

Output Interface ............RTL ............TOP ..................... Verification Environment ..................... Top Module ............PACKET ............DRIVER ............RECIEVER ............SCOREBOARD ............ENV

DUT SPECIFICATION
This DUT is a simple switch, which can drive the incoming packet to destination ports based on the address contained in the packet. The dut contain one input interface from which the packet enters the dut. It has four output interfaces where the packet is driven out.

Packet format: Packet contains Header, data and frame check sequence. Packet width is 8 bits and the length of the packet can be between 4 bytes to 259 bytes. Packet header: Packet header contains three fields DA, SA and length. DA: Destination address of the packet. It is 8 bits. The switch drives the packet to respective ports based on this destination address of the packets. SA: Source address of the packet from where it originate. Length: This is the length of the data. It can be from 0 to 255. Data: Data should be in terms of bytes. It can be between 0 to 255 bytes. FCS: This field contains the security check of the packet. It is calculated over the header and data.

Configuration: Dut has four output ports. These output ports have to be configure to a address. Dut matches the DA field of the packet with this configured port address and sends the packet on to that port. To configure the dut, a memory interface is provided. The address of the ports should be unique. It is 8 bits wide. Memory address (0,1,2,3) contains the address of port(0,1,2,4) respectively. Interface Specification: The dut has one input Interface, from where the packet enters the dut and 4 output interfaces from where the packet comes out and one memory interface, through the port address can be configured. Memory Interface: Through memory interfaced output port address are configured. It accepts 8 bit data to be written to memory. It has 8 bit address inputs. Address 0,1,2,3 contains the address of the port 0,1,2,3 respectively. If the DA feild in the packet matches with the confugured address of any port ,then the packet comes out of that port. Input Interface: The status signal has to be high when data is when packet is sent on to the dut it has to become low after sending last byte of the packet. When the dut is busy, and if it is not in a position to accept any more data, it will assert busy signal. Data which is sent during this busy signal is lost if input is driving when busy is high Output Interface: There are 4 ports, each having data, ready and read signals. When the data is ready to be sent out from the port, dut makes the ready signal high

indicating that data is ready to be sent. If the read signal is made high when ready is high, then the data comes out of the data signal.

RTL
CODE: switch.v module fifo (clk, reset, write_enb, read, data_in, data_out, empty, full); input clk; input reset; input write_enb; input read; input [7:0] data_in; output [7:0] data_out; output empty; output full; wire clk; wire write_enb; wire read; wire [7:0] data_in; reg [7:0] data_out; wire empty; wire full; reg [7:0] ram[0:25]; reg tmp_empty; reg tmp_full; integer write_ptr; integer read_ptr; always@(negedge reset) 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 clk) begin 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 end if ((read == 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 end end endmodule //fifo module port_fsm (clk, reset, write_enb, ffee, hold, data_status, data_in, data_out, mem0, mem1, mem2, mem3, addr); input clk; input reset; input [7:0] mem0; input [7:0] mem1; input [7:0] mem2; input [7:0] mem3; output[3:0] write_enb; input ffee; input hold; input data_status; input[7:0] data_in; output[7:0] data_out; output [7:0] addr; reg [7:0] data_out; reg [7:0] addr; reg [3:0] write_enb_r; reg fsm_write_enb; reg [3:0] state_r; reg [3:0] state; reg [7:0] parity;

reg reg

[7:0] parity_delayed; sus_data_in,error; ADDR_WAIT = 4'b0000; DATA_LOAD = 4'b0001; PARITY_LOAD = 4'b0010; HOLD_STATE = 4'b0011; BUSY_STATE = 4'b0100;

parameter parameter parameter parameter parameter

always@(negedge reset) begin error = 1'b0; data_out = 8'b0000_0000; addr = 8'b00000000; 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 busy = sus_data_in; always @(data_status) begin : addr_mux if (data_status == 1'b1) begin case (data_in) mem0 : begin write_enb_r[0] = 1'b1; write_enb_r[1] = 1'b0; write_enb_r[2] = 1'b0; write_enb_r[3] = 1'b0; end mem1 : begin write_enb_r[0] = 1'b0; write_enb_r[1] = 1'b1; write_enb_r[2] = 1'b0; write_enb_r[3] = 1'b0; end mem2 : begin write_enb_r[0] = 1'b0; write_enb_r[1] = 1'b0; write_enb_r[2] = 1'b1; write_enb_r[3] = 1'b0; end mem3 : begin write_enb_r[0] write_enb_r[1] write_enb_r[2] write_enb_r[3] = 1'b0; = 1'b0; = 1'b0; = 1'b1;

end default :write_enb_r = 3'b000; endcase // $display(" data_inii %d ,mem0 %d ,mem1 %d ,mem2 %d mem3",data_in,mem0,mem1,mem2,mem3); end //if end //addr_mux; always @(posedge clk) begin : fsm_state state_r <= state; end //fsm_state; always @(state_r or data_status or ffee or hold or data_in) begin : fsm_core state = state_r; //Default state assignment case (state_r) ADDR_WAIT : begin if ((data_status == 1'b1) && ((mem0 == data_in)||(mem1 == data_in)||(mem3 == data_in) ||(mem2 == data_in))) begin if (ffee == 1'b1) begin state = DATA_LOAD; end else begin state = BUSY_STATE; end //if end //if; sus_data_in = !ffee; if ((data_status == 1'b1) && ((mem0 == data_in)||(mem1 == data_in)||(mem3 == data_in) ||(mem2 == data_in)) && (ffee == 1'b1)) begin addr = data_in; 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 state = ADDR_WAIT; data_out = data_in; fsm_write_enb = 1'b0; end // of case PARITY_LOAD DATA_LOAD : begin if ((data_status == 1'b1) && (hold == 1'b0)) begin state = DATA_LOAD; end

else if ((data_status == 1'b0) && (hold == 1'b0)) begin state = PARITY_LOAD; end else begin state = HOLD_STATE; end //if sus_data_in = 1'b0; if ((data_status == 1'b1) && (hold == 1'b0)) begin data_out = data_in; fsm_write_enb = 1'b1; end else if ((data_status == 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 if (hold == 1'b1) begin state = HOLD_STATE; end else if ((hold == 1'b0) && (data_status == 1'b0)) begin state = PARITY_LOAD; end else begin state = DATA_LOAD; end //if 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 if (ffee == 1'b0) begin state = BUSY_STATE; end else begin state = DATA_LOAD; end //if if (ffee == 1'b0) begin sus_data_in = 1'b1;

end else begin addr = data_in; // hans data_out = data_in; fsm_write_enb = 1'b1; end //if end //end of case BUSY_STATE endcase end //fsm_core assign assign assign assign write_enb[0] write_enb[1] write_enb[2] write_enb[3] = write_enb_r[0] = write_enb_r[1] = write_enb_r[2] = write_enb_r[3] & fsm_write_enb; & fsm_write_enb; & fsm_write_enb; & fsm_write_enb;

endmodule //port_fsm module switch (clk, reset, data_status, data, port0, port1, port2, port3, ready_0, ready_1, ready_2, ready_3, read_0, read_1, read_2, read_3, mem_en, mem_rd_wr, mem_add, mem_data); input clk; input reset; input data_status; input [7:0] data; input mem_en; input mem_rd_wr; input [1:0] mem_add; input [7:0] mem_data; output [7:0] port0; output [7:0] port1; output [7:0] port2; output [7:0] port3; output ready_0; output ready_1;

output ready_2; output ready_3; input read_0; input read_1; input read_2; input read_3; wire [7:0] data_out_0; wire [7:0] data_out_1; wire [7:0] data_out_2; wire [7:0] data_out_3; wire ll0; wire ll1; wire ll2; wire ll3; wire empty_0; wire empty_1; wire empty_2; wire empty_3; wire ffee; wire ffee0; wire ffee1; wire ffee2; wire ffee3; wire ld0; wire ld1; wire ld2; wire ld3; wire hold; wire [3:0] write_enb; wire [7:0] data_out_fsm; wire [7:0] addr; reg [7:0]mem[3:0]; wire reset; fifo queue_0 (.clk (clk), .reset (reset), .write_enb (write_enb[0]), .read (read_0), .data_in (data_out_fsm), .data_out (data_out_0), .empty (empty_0), .full (ll0)); fifo queue_1 (.clk (clk), .reset (reset), .write_enb (write_enb[1]), .read (read_1), .data_in (data_out_fsm), .data_out (data_out_1), .empty (empty_1),

.full

(ll1));

fifo queue_2 (.clk (clk), .reset (reset), .write_enb (write_enb[2]), .read (read_2), .data_in (data_out_fsm), .data_out (data_out_2), .empty (empty_2), .full (ll2)); fifo queue_3 (.clk (clk), .reset (reset), .write_enb (write_enb[3]), .read (read_3), .data_in (data_out_fsm), .data_out (data_out_3), .empty (empty_3), .full (ll3));

port_fsm in_port (.clk (clk), .reset (reset), .write_enb (write_enb), .ffee (ffee), .hold (hold), .data_status (data_status), .data_in (data), .data_out (data_out_fsm), .mem0 (mem[0]), .mem1 (mem[1]), .mem2 (mem[2]), .mem3 (mem[3]), .addr (addr)); assign port0 = data_out_0; //make note assignment only for //consistency with vlog env assign port1 = data_out_1; assign port2 = data_out_2; assign port3 = data_out_3; assign assign assign assign assign assign assign assign ready_0 ready_1 ready_2 ready_3 ffee0 ffee1 ffee2 ffee3 = = = = ~empty_0; ~empty_1; ~empty_2; ~empty_3; |( |( |( |( addr addr addr addr != != != != mem[0])); mem[1])); mem[2])); mem[3]));

= (empty_0 = (empty_1 = (empty_2 = (empty_3

assign ffee = ffee0 & ffee1 & ffee2 & ffee3; assign assign assign assign ld0 ld1 ld2 ld3 = = = = (ll0 (ll1 (ll2 (ll3 & (addr & (addr & (addr & (addr == == == == mem[0])); mem[1])); mem[2])); mem[3]));

assign hold = ld0 | ld1 | ld2 | ld3; always@(posedge clk) begin if(mem_en) if(mem_rd_wr) begin mem[mem_add]=mem_data; ///$display("%d %d %d %d %d",mem_add,mem[0],mem[1],mem[2],mem[3]); end end endmodule //router

TOP
Verification Environment: This is simple verification environment. It has top,tb,packet,Driver, Scoreboard and Receiver components.

Top Module: Top module contains the instance of the Dut and verification environment. It also has the clock generator. For more information about clock generation, go through TB_CONCEPTS in this website. Do reset and Confgure the dut port address. CODE: top module top(); reg clock; wire packet_valid; wire [7:0] data; wire [7:0] data_0; wire [7:0] data_1; wire [7:0] data_2; wire [7:0] data_3; wire ready_0; wire ready_1; wire ready_2; wire ready_3; wire read_0; wire read_1; wire read_2; wire read_3; reg reg reg reg reg reg reset; mem_en; mem_rd_wr; [7:0] mem_data; [1:0] mem_add; [7:0] mem[3:0];

// take istance of testbench sw_tb tb (clock, packet_valid, data, data_0, data_1, data_2, data_3, ready_0, ready_1, ready_2, ready_3, read_0, read_1, read_2, read_3);

// take instance dut switch dut (clock, reset, packet_valid, data, data_0, data_1, data_2, data_3, ready_0, ready_1, ready_2, ready_3, read_0, read_1, read_2, read_3, mem_en, mem_rd_wr, mem_add, mem_data); //Clock generator initial clock = 0; always begin #5 clock = !clock; end // Do reset and configure the dut port address initial begin $dumpon; mem[0]=$random; mem[1]=$random; mem[2]=$random; mem[3]=$random; mem_en = 0; @(posedge clock); #2 reset = 1; @(posedge clock); #2 reset =0; mem_en = 1; @(negedge clock); mem_rd_wr = 1; mem_add = 0; mem_data = mem[0]; @(negedge clock); mem_rd_wr = 1;

mem_add = 1; mem_data = mem[1]; @(negedge clock); mem_rd_wr = 1; mem_add = 2; mem_data = mem[2]; @(negedge clock); mem_rd_wr = 1; mem_add = 3; mem_data = mem[3]; @(negedge clock); mem_en=0; mem_rd_wr = 0; mem_add = 0; mem_data = 0; end endmodule //top

DRIVER
Take an instance of packet Define task to generate the packet and call the drive task. This task first, calls randomize task in the packet then calls the pack to packing the packet. Calls the drive packet wich drives the packet to dut. Then add the sent packet to score board. CODE:driver.v module driver(clock,packet_valid,data,busy); output packet_valid; output [7:0] data; input busy; input clock; reg packet_valid; reg [7:0] data; integer delay; // Take an instance of packet pktgen gen(); //Define task to generate the packet and call the drive task task gen_and_drive(input integer no_of_pkts); integer i; begin for(i=0;i<no_of_pkts;i=i+1) begin delay={$random()}%4; $display("DRIVER gen and drive pkt_no = %d delay %d",i,delay);

repeat (delay)@(negedge clock); // randomize the packet gen.randomize(); //pack the packet gen.packing(); // call the drive packet task. @(negedge clock); drive_packet(); // add the sent packet to score board top.tb.sb.add_pkt(i); end end endtask

task drive_packet() ; integer i; begin $display("DRIVER Starting to drive packet to port %0d len %0d ",gen.Da,gen.len); repeat(4)@(negedge clock); for (i=0;i<gen.len+4;i=i+1) begin @ (negedge clock); packet_valid = 1 ; data[7:0] = gen.pkt[i]; $display("[DRIVER] data %b at i %d",gen.pkt[i],i); end @ (negedge clock); packet_valid = 0 ; @(negedge clock); end endtask endmodule

RECIEVER
Build a receiver which can collect a packet on single port. Define a task to unpack the recived packet. Define a task to check whether the received packet and sent packet are same are not. In the initial block Start collecting packet. Do unpacking,Call the checker task Checker Checks whether the packet is coming on the proper port or not, then checker gets the packet from scoreboard and comares the recived packet with the sent packet. If any error is there then error is asserted.

CODE:receiver.v module receiver(clk,data, ready, read, port); input ready; input clk; input [7:0]data; input port; output read; reg read; reg [0:7] mem [0:65]; wire [31:0] port; integer j,delay; reg[7:0] rec_address; // Start collecting packet initial begin while(1) begin begin @(posedge ready) delay= {$random()}%5+1; repeat(delay)@(negedge clk); j=0; @(negedge clk); read=1'b1; while(ready==1'b1) begin @(negedge clk); mem[j]=data; j=j+1; $display(" RECV BYTE at PORT[%d] %b",port,data); end//while read=1'b0; end // Do unpacking unpacking(); // Call the checker task checker((j-1)); end end // Do unpack of the packet recived. task unpacking; reg [7:0]rec_parity;

reg [7:0]rec_paclen; reg [7:0]separate; reg [7:0]rec_data[0:63]; begin rec_paclen=mem[2]; rec_parity=mem[rec_paclen+3]; rec_address=mem[0]; $display("rec_parity=%b rec_paclen=%0d %b, rec_address=%b header %b",rec_parity,rec_paclen, rec_paclen, rec_address,mem[0]); end endtask task checker(input integer size); integer i; begin $display("[CHECKER] Checker started for pkt_no %d ",top.tb.sb.pkt_no ); if(rec_address!=top.mem[port]) begin ->top.tb.error; // Check whether the packet is coming on the proper port or not $display("[CHECKER] ERROR PKT RECIVED ON PORT %d,PKT ADDRESS is %d",top.mem[port],rec_address); end for(i=0;i<size;i=i+1) // get the packet from score board and comare the recived packet with the sent packet. if(top.tb.sb.sent_pkt[i][top.tb.sb.pkt_no]!== mem[i]) begin $display("[CHECKER] ERROR at %d pkt no %d ",i,top.tb.sb.pkt_no); $display("[CHECKER] at %d sentbyte %b rcevbyte %b",i,top.tb.sb.sent_pkt[i] [top.tb.sb.pkt_no], mem[i]); ->top.tb.error; end else begin $display("[CHECKER] at %d sentbyte %b rcevbyte %b",i,top.tb.sb.sent_pkt[i] [top.tb.sb.pkt_no], mem[i]); end top.tb.sb.pkt_no=top.tb.sb.pkt_no+1; end endtask endmodule

SCOREBOARD
The expected packets are stored in scored board by driver.

Declare a memory to store sent packets task to add packets to scoreboard CODE: scoreboard.v module scoreboard(); // Declare a memory to store sent packets reg [0:7]sent_pkt [0:64][0:10]; integer pkt_no; initial pkt_no=0; // task to add packets to scoreboard task add_pkt(input integer pkt_no); integer i; begin for(i=0;i<65;i=i+1) sent_pkt[i][pkt_no]=top.tb.dv.gen.pkt[i]; end endtask endmodule

ENV
Env is a module which contains all the components of verification. A logic to increment the error counter. Take a Driver instance and creat four reciever instancess. connect it to specific port. Creat instance of scoreboard Call then packet gen and drive task in driver Creat a finish task which display the tesults of the test. CODE:env.v module sw_tb(clock, packet_valid, data , data_0 , data_1 , data_2 , data_3 , ready_0 , ready_1 , ready_2 , ready_3 , read_0 , read_1 , read_2 , read_3

); input clock; output packet_valid; output [7:0] data; input [7:0] data_0; input [7:0] data_1; input [7:0] data_2; input [7:0] data_3; input ready_0; input ready_1; input ready_2; input ready_3; output read_0; output read_1; output read_2; output read_3; reg pkt_status; integer error_count=0; event error; //Incriment the error counter on error. always@(error) begin #0 error_count=error_count+1; $display(" ERROR RECIVED"); end // Driver instance driver dv(clock,packet_valid,data,busy); // Make four reciever instancess. connect it to specific port. receiver rec0(.clk(clock),.data(data_0), .ready(ready_0), .read(read_0), .port(0) ); receiver rec1(.clk(clock),.data(data_1), .ready(ready_1), .read(read_1), .port(1) ); receiver rec2(.clk(clock),.data(data_2), .ready(ready_2), .read(read_2), .port(2) ); receiver rec3(.clk(clock),.data(data_3), .ready(ready_3), .read(read_3), .port(3) ); // Creat instance of scoreboard scoreboard sb();

// Call then packet gen and drive task in driver initial begin #100; dv.gen_and_drive(9); #1000; finish; end // finish task which display the tesults of the test. task finish(); begin if(error_count!=0) $display("############# TEST FAILED ###############"); else $display("############# TEST PASSED ###############"); $finish; end endtask endmodule

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy