// // Template for solution to LSU EE 4702-1 Spring 2000 Homework 6. // // Name: // Instructions: // // // Copy this file to a file named hw06sol.v in your class directory, // and use it for your solution. // // Use the module names provided in this file. The solution, named // width_change, must be the first module in the file and it must // compile without having to modify any defines. // // The files will be copied from the class accounts soon after the // assignment is due. module width_change(out,full,complete,empty,outclk,in,inclk,reset); input outclk, in, inclk, reset; output out, full, complete, empty; parameter storage = 32; wire [7:0] out; wire [3:0] in; wire inclk, outclk, full, empty, complete; reg [storage-1:0] sto; reg [5:0] amt; initial begin amt = 0; sto = 0; end assign complete = amt >= 8; assign full = amt + 4 > storage; assign empty = amt === 0; assign out = sto[7:0]; always @( reset or amt or sto ) if( reset ) begin amt = 0; sto = 0; end always @( posedge outclk ) begin sto = sto >> 8; amt = amt < 8 ? 0 : amt - 8; end always @( posedge inclk ) if( !full ) begin sto = sto | in << amt; amt = amt + 4; end endmodule // width_change module wc_test(); // If non-zero, stop simulation when an error is encountered. // If zero, when an error is encountered simulation will proceed // and a count of errors will be displayed. parameter stop_on_err = 1; wire [7:0] out; wire full, empty, comp; reg outclk, inclk, reset; reg [3:0] indata; reg [31:0] shadow; reg shadow_full, shadow_comp, shadow_empty; reg [7:0] shadow_head; integer shadow_occ; reg check; integer phasecount; time remove_delay_limit_short, remove_delay_limit_long; time remove_delay_limit; time fill_delay_limit; time next_empty; integer allow_simultaneous_clocks; integer allow_overlapping_clocks; integer error_out_t, error_out; integer error_empty_t, error_empty; integer error_comp_t, error_comp; integer error_full_t, error_full; integer error_test, error_test_t; width_change wc(out,full,comp,empty,outclk,indata,inclk,reset); function [31:0] randi; input [31:0] limit; randi = ( $random >> 1 ) % limit; endfunction // randi initial begin indata = 0; outclk = 0; inclk = 0; reset = 0; shadow_empty = 1; shadow_comp = 0; shadow_full = 0; shadow_head = 0; check = 0; shadow = 0; shadow_occ = 0; phasecount = 0; fill_delay_limit = 20; remove_delay_limit_short = 0.5 * fill_delay_limit * 2; remove_delay_limit_long = 2 * fill_delay_limit * 2; // Start filling. remove_delay_limit = remove_delay_limit_long; allow_overlapping_clocks = 0; allow_simultaneous_clocks = 0; error_out = 0; error_out_t = 0; error_empty = 0; error_empty_t = 0; error_comp = 0; error_comp_t = 0; error_full = 0; error_full_t = 0; error_test = 0; error_test_t = 0; reset = 1; #10 reset = 0; #10; fork:TESTLOOP forever begin:FILL integer clk_fall_delay; integer clk_rise_delay; clk_fall_delay = allow_overlapping_clocks ? randi(fill_delay_limit)+1 : 1; clk_rise_delay = randi(fill_delay_limit)+1; indata <= #(10*randi(clk_rise_delay)) $random; #(10*clk_rise_delay); // Special case: if FIFO is full or empty and data is // simultaneously clocked in and out there's no way to // tell if FIFO rejected the data begin clocked in. while( next_empty == $time && ( !allow_simultaneous_clocks || shadow_occ >= 20 || shadow_occ < 12 )) #10; inclk = 1; check <= #1 !check; shadow_empty = 0; if( !shadow_full ) begin shadow_occ = shadow_occ + 4; shadow = { indata, shadow[31:4] }; if( shadow_occ > 28 ) begin shadow_full = 1; if( remove_delay_limit === remove_delay_limit_long ) begin remove_delay_limit = remove_delay_limit_short; phasecount = phasecount + 1; end end if( shadow_occ > 7 ) shadow_comp = 1; end shadow_head = shadow >> ( 32 - shadow_occ ); indata <= #(10*randi(clk_fall_delay)) $random; inclk = #(10*clk_fall_delay) 0; end forever begin:EMPTY integer clk_fall_delay; integer clk_rise_delay; clk_fall_delay = allow_overlapping_clocks ? randi(remove_delay_limit)+1 : 1; clk_rise_delay = randi(remove_delay_limit)+1; next_empty = $time + 10 * clk_rise_delay; outclk = #(10*clk_rise_delay) 1; check <= #1 !check; shadow_full = 0; if( !shadow_empty ) begin if( shadow_occ <= 8 ) begin shadow_occ = 0; shadow_empty = 1; remove_delay_limit = remove_delay_limit_long; end else begin shadow_occ = shadow_occ - 8; end shadow_head = shadow >> ( 32 - shadow_occ ); if( shadow_occ < 8 ) shadow_comp = 0; end outclk = #(10*clk_fall_delay) 0; end // block: EMPTY forever @( out or check ) #1 if( out !== shadow_head ) begin if( stop_on_err ) begin $display("Wrong output."); #2 $stop; end error_out = error_out + 1; end forever @( empty or check ) #1 if( empty !== shadow_empty ) begin if( stop_on_err ) begin $display("Wrong empty."); #2 $stop; end error_empty = error_empty + 1; end forever @( comp or check ) #1 if( comp !== shadow_comp ) begin if( stop_on_err ) begin $display("Wrong complete."); #2 $stop; end error_comp = error_comp + 1; end forever @( full or check ) #1 if( full !== shadow_full ) begin if( stop_on_err ) begin $display("Wrong full."); #2 $stop; end error_full = error_full + 1; end forever @( phasecount ) begin:P reg [84:0] test_name; if( phasecount == 200 || phasecount == 400 || phasecount == 600 ) begin error_test = error_out + error_empty + error_comp + error_full; error_test_t = error_test_t + error_test; error_out_t = error_out_t + error_out; error_empty_t = error_empty_t + error_empty; error_comp_t = error_comp_t + error_comp; error_full_t = error_full_t + error_full; case( phasecount ) 200:test_name = "No Overlap"; 400:test_name = "Not Simult"; 600:test_name = "Full Test"; endcase // case( phasecount ) $display("Test %s. Total Errors %d. Errors by type:", test_name, error_test); $display(" Output %d, empty %d, compl %d, full %d", error_out, error_empty, error_comp, error_full); if( phasecount == 200 ) begin allow_overlapping_clocks = 1; if( error_test === 0 ) $display("Passed all non-overlapping tests!!"); end else if ( phasecount == 400 ) begin allow_simultaneous_clocks = 1; if( error_test === 0 ) $display("Passed all overlapping-but-not-simultaneous tests!!!!!"); end else if ( phasecount == 600 ) begin if( error_test === 0 ) $display("Passed all simultaneous clock tests!!!!!!!"); if( error_test_t === 0 ) $display("Passed EVERY test! PERFECT!!!!!!!!!!!!!!!"); else $display("Failed %d tests. :-(",error_test_t); disable TESTLOOP; end error_out = 0; error_empty = 0; error_comp = 0; error_full = 0; error_test = 0; end // if ( phasecount == 200 || phasecount == 400 || phasecount == 600 ) end join end // initial begin endmodule // wc_test