⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testing.v.txt

📁 verilog实例100多个
💻 TXT
📖 第 1 页 / 共 2 页
字号:
Some Examples of Verilog testbench techniques.



      1.0   Introduction

      2.0   Generating Periodic Signals

      3.0   Generating and Receiving Serial Characters

      4.0   Memories

      5.0   Bus Models





1.0   Introduction



A testbench is a verilog program that wraps around an actual design.  

The testbench is typically not part of the design and does not result 

in actual circuitry or gates.  Verilog code for testbenches may be 

much more "free style" than Verilog code that must be 

synthesized - anything goes.  Here are some tidbits from various

 projects I've worked on.  The code is not completely general nor 

perfect, but hopefully may provide ideas for designers just starting

 out with testbench design.  Oh, and the names have been changed

 to protect the innocent.  I hope I haven't introduced error in 

doctoring up these examples.  Again, none of the following  code 

is intended to be synthesizable!



2.0   Generating Periodic Signals.



Say you have a period signal.  Try tossing in a little random fluctuation

 on where the edges occur - you may catch a an unexpected bug! 

 But, be careful about using random because if you move on to 

manufacturing test, then your testbench may not be deterministic. 

 Often, for the sake of the tester, you must enforce transitions to 

occur in specific periods.  In this case, you may need to add 

statements that delay changes to fall in these periods.  Anyway,

 let's drive the foo1in signal.  We'll add in some random, count 

the transitions and print out a message.



initial begin

   #1 foo1in = 0;

      forever begin

         #(`PERIOD/2 + ($random % 10)*(` PERIOD/20)) foo1in = 1;

         foo1_input_count = foo1_input_count + 1;

         $display ("#Foo1 rising edges = %d", foo1_input_count);

         #(` PERIOD/2 + ($random % 10)*(` PERIOD/20)) foo1in = 0;

      end

end


Here's another code snippet - a task that generates a period message..

task generate_syncs;
   event	send_sync;
   begin
      syncdata = SYNC_START;
      syncstb  = 0;
   
      fork
         // Generate periodic event for sending the sync
         forever #(1000000000.0 * RATE) ->send_sync; // convert RATE to nanoseconds
         
         // Wait on send_sync event, and then send SYNC synchronized with clk
         forever begin
            @(send_sync);
            syncdata = syncdata + CMTS_FREQ * CMTS_RATE;
            $display ("... SYNC = %h at time %0t, Local Time = %h", syncdata, $time, local_time);
            @(posedge clk) #1;
            syncstb = 1;
            @(posedge clk) #1;
            syncstb = 0;
         end
      join
   end
endtask


3.0   Generating and Receiving Serial Characters



Say your design inputs or outputs serial characters.  Here is some 

code for both.  First, some defines:



/*  Serial Parameters used for send_serial task and its callers. */

`define PARITY_OFF   1'b0

`define PARITY_ON    1'b1

`define PARITY_ODD   1'b0

`define PARITY_EVEN  1'b1

`define NSTOPS_1     1'b0

`define NSTOPS_2     1'b1

`define BAUD_9600    2'b00

`define BAUD_4800    2'b01

`define BAUD_2400    2'b10

`define BAUD_1200    2'b11

`define NBITS_7      1'b0

`define NBITS_8      1'b1



Here's how you call it:



send_serial (8'hAA, `BAUD_9600, `PARITY_EVEN, `PARITY_ON, `NSTOPS_1, `NBITS_7, 0);



Here's a task that sends a character.



task send_serial;

input [7:0] inputchar;

input baud;

input paritytype;

input parityenable;

input nstops;

input nbits;

input baud_error_factor;



reg       nbits;

reg       parityenable;

reg       paritytype;

reg [1:0] baud;

reg       nstops;

integer   baud_error_factor;  // e.g. +5 means 5% too fast and -5 means 5% too slow



reg   [7:0] char;

reg         parity_bit;

integer     bit_time;



begin

   char = inputchar;

   parity_bit = 1'b0;

   case (baud)

      `BAUD_9600: bit_time = 1000000000/(9600 + 96*baud_error_factor);

      `BAUD_4800: bit_time = 1000000000/(4800 + 48*baud_error_factor);

      `BAUD_2400: bit_time = 1000000000/(2400 + 24*baud_error_factor);

      `BAUD_1200: bit_time = 1000000000/(1200 + 12*baud_error_factor);

   endcase   



   $display ("Sending character %h, at %0d baud (err=%0d), %0d bits, %0s parity, %0d stops",

       (nbits == `NBITS_7) ? (char & 8'h7f) : char,

      1000000000/bit_time,

      baud_error_factor,

      (nbits == `NBITS_7) ? 7 : 8,

      (parityenable == `PARITY_OFF) ? "NONE" : (paritytype == `PARITY_EVEN) ? "EVEN" : "ODD",

      (nstops == `NSTOPS_1) ? 1 : 2

   );

      

   // Start bit

   serial_character = 1'b0;   // Start bit.

   #(bit_time);



   // Output data bits

   repeat ( (nbits == `NBITS_7) ? 7 : 8) begin

      serial_character = char[0];

      #(bit_time);

      char = {1'b0, char[7:1]};

   end

   

   if (parityenable == `PARITY_ON) begin

      parity_bit = (nbits == `NBITS_7) ? ^inputchar[6:0] : ^inputchar[7:0];

      if (paritytype == `PARITY_ODD)

         parity_bit = ~parity_bit; // even parity

         serial_character = parity_bit;

         #(bit_time);

      end

      serial_character = 1'b1;   // Stop bit.

      #(bit_time);

      if (nstops) // Second stop bit

         #(bit_time);

   end

endtask



Here's a task that receives serial characters.  This particular task was 

a bit messy in that it set some global variables in order to return a 

status, etc.  By all means - fix this up the way you like it!



reg [7:0] receive_serial_character_uart1;	// Global that receives tasks result



// ****  SERIAL CHARACTER LISTENER Task for UART1

//

//

task receive_serial_uart1;



input baud;

input paritytype;

input parityenable;

input nstops;

input nbits;



reg       nbits;

reg       parityenable;

reg       paritytype;

reg [1:0] baud;

reg       nstops;



integer     bit_time;



reg         expected_parity;



begin

receive_serial_result_uart1 = 0;

receive_serial_character_uart1 = 0;



case (baud)

   `BAUD_9600: bit_time = 1000000000/(9600);

   `BAUD_4800: bit_time = 1000000000/(4800);

   `BAUD_2400: bit_time = 1000000000/(2400);

   `BAUD_1200: bit_time = 1000000000/(1200);

endcase 

     

receive_serial_result_uart1 = `RECEIVE_RESULT_OK;  // Assume OK until bad things happen.



@(negedge uart1out);  // wait for start bit edge

#(bit_time/2);  // wait till center of start bit

if (uart1out != 0) // make sure its really a start bit

   receive_serial_result_uart1 = receive_serial_result_uart1 | `RECEIVE_RESULT_FALSESTART;

else begin

   repeat ( (nbits == `NBITS_7) ? 7 : 8) begin // get all the data bits (7 or 8)

      #(bit_time);  // wait till center

      // sample a data bit

      receive_serial_character_uart1 = {uart1out, receive_serial_character_uart1[7:1]};

   end



   // If we are only expecting 7 bits, go ahead and right-justify what we have

   if (nbits == `NBITS_7)

      receive_serial_character_uart1 = {1'b0, receive_serial_character_uart1[7:1]};

      

      #(bit_time);

      // now, we have either a parity bit, or a stop bit

      if (parityenable == `PARITY_ON) begin

         if (paritytype == `PARITY_EVEN)

            expected_parity = (nbits == `NBITS_7) ? (^receive_serial_character_uart1[6:0]) :            

                                                                               (^receive_serial_character_uart1[7:0]);

         else

            expected_parity = (nbits == `NBITS_7) ? (~(^receive_serial_character_uart1[6:0])) :  

                                                                               (~(^receive_serial_character_uart1[7:0]));

            if (expected_parity != uart1out)

               receive_serial_result_uart1 = receive_serial_result_uart1 | `RECEIVE_RESULT_BADPARITY;

         // wait for either 1 or 2 stop bits

      end

      else begin

			// this is a stop bit.

         if (uart1out != 1)

            receive_serial_result_uart1 = receive_serial_result_uart1 | `RECEIVE_RESULT_BADSTOP;

         else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -