ECE 551 Digital System Design & Synthesis Lecture 06 Loops Non-synthesizable Constructs File I/O Topics FOR Loops in non-testbench modules Review Invalid/non-synthesizable hardware Testbench output methods File I/O 2 For Loops In Hardware Can use fixed-length for loops in modules reg [15:0] countmem [0:7]; integer i; always @(posedge clk) begin for (i = 0; i < 8; i = i + 1) begin countmem[i] <= countmem[i] + 1’b1; end end These loops are unrolled prior to synthesis That’s why they must be fixed in length! Using integer because i is not actually synthesized Example creates eight 16-bit incrementers. 3 For Loops In Hardware Using a For loop to design a variable size decoder parameter NUM_BITS = 16; reg [(NUM_BITS – 1):0] decoded; integer i; always @(coded_in) begin for (i = 0; i < NUM_BITS; i = i + 1) begin decoded_out[i] = 1’b0; end decoded_out[coded_in] = 1’b1; end Parameter values are fixed from compile/elaboration time Yes, this synthesizes 4 Behavioral Verilog Pitfalls Behavioral Verilog gives us more flexibility than Structural or RTL This extra flexibility also makes it easier for us to write descriptions that do not synthesize. The next few slides cover a few things that people commonly try to do that cannot be synthesized. 5 Variable-Size For Loops Using a for loop to design a variable size bitmask generator input [4:0] mask_size reg [31:0] mask; integer i; always @(mask_size) begin mask = 32’b0; for (i = 0; i < mask_size; i = i + 1) begin mask[i] = 1’b1; end end Cannot synthesize variable values in loop control, because they cannot be unrolled before Synthesis. This does not synthesize, but might work in simulation! 6 Instantiating in an Always Block Cannot synthesize (or simulate): module bad(input a, b, c, output d); always@(a,b,c) if (c) and(d, a, b); else or(d, a, b); endmodule Conceptually, why is this a problem? Later we will learn about generate-if statements, which allow us to do something similar to this. 7 Cannot Detect x or z Cannot Synthesize: module find_x(input a, output b); always@(a) if (a === x) b = 1’b1; else b = 1’b0; endmodule 8 Cannot Detect x or z Cannot Synthesize: module find_x_z(input a, output d); always@(a) case (a) 1’bx : d = 1’b1; 1’bz : d = 1’b1; default : d = 1’b0; endcase endmodule What if we had used casex? What would have been synthesized? 10 Feedback In Combinational Logic What happens here? // update the state always @(posedge clk) begin if (rst) begin state <= 1’b0; count <= 8’d0; end else state <= next; end How can we fix it? // find next state and // count the 3’b101 values always @(input, count) begin if (input == 3’b101) begin count = count + 1; next = 1’b1; end else begin next = 1’b0; end end 11 Fixing The Example // update the state and count always @(posedge clk) begin if (rst) begin state <= 1’b0; count <= 8’d0; end else begin // find next state and state <= next; // count the 3’b101 values count <= nextcount; always @(state, input, count) begin end if (input == 3’b101) begin end nextcount = count + 1; next = 1’b1; end else begin nextcount = count; next = 1’b0; end end 12 We’ll cover a few more examples of code that doesn’t synthesize later in the semester 13 Simulation I/O Modelsim Lists and Waves Waves visually appealing Convenient, but constrained formats Display/Strobe/Monitor Provide results to standard output Flexible text formats Sampling issues (Verilog Event Queue) File I/O Good for archiving results Flexible text formats Useful for self-checking testbenches Sampling issues (Verilog Event Queue) 14 Display Functions in Detail $display (and $write) $display adds newline, $write does not Occurs along with other active events, when encountered initial #5 $display ("a = %h, b = %b", a, b); $strobe Similar to $display, but displays data at the end of the current simulation time (i.e. after all events at that simulation cycle have been processed) – Region 4 Event initial forever @(negedge clock) $strobe ("Time=%t data=%h", $time, data); $monitor Displays data at end of current simulation time, whenever a variable in the argument list changes initial $monitor ("Time=%t data=%h", $time, data); 15 Interesting Format Specifier: %m Displays the hierarchical name of the module calling the $display function Useful when there are multiple instantiations of a module to tell which instance caused the display Doesn’t take a parameter $display(“%m: x=%b y=%b”, x, y); 16 %m Example [1] module mexample(); wire out0, out1; reg [3:0] in; a a0(out0, in[2], in[0]); a a1(out1, in[2], in[1]); initial $monitor("%m: out0=%b out1=%b in=%b", out0, out1, in[2:0]); initial begin for (in = 0; in < 8; in = in + 1) #5; end endmodule module a(output reg out, input a, b); always @(a, b) begin out = a & b; $display("%m: out=%b a=%b b=%b", out, a, b); end endmodule 17 %m Example [2] Simulation results: … # # # # # # # # # # # # # … mexample: out0=0 out1=0 in=010 mexample.a0: out=0 a=0 b=1 mexample: out0=0 out1=0 in=011 mexample.a0: out=0 a=1 b=0 mexample.a1: out=0 a=1 b=0 mexample: out0=0 out1=0 in=100 mexample.a0: out=1 a=1 b=1 mexample: out0=1 out1=0 in=101 mexample.a0: out=0 a=1 b=0 mexample.a1: out=1 a=1 b=1 mexample: out0=0 out1=1 in=110 mexample.a0: out=1 a=1 b=1 mexample: out0=1 out1=1 in=111 // in=011 // in=100 // in=101 // in=110 // in 111 18 File I/O – Why? If we don’t want to hard-code all information in the testbench, we can use input files Help automate testing One file with inputs One file with expected outputs Can have a software program generate data Create the inputs for testing Create “correct” output values for testing Can use files to “connect” hardware/software system 19 Opening/Closing Files $fopen opens a file and returns a descriptor Syntax: integer desc = $fopen(filename, type); If file can’t be opened, returns a 0. Use $ferror to determine cause. Can specify a mode (r, w, a+, etc) – see standard. If no mode is specified, $fopen opens the file for writing and returns a “multi-channel” descriptor integer fd = $fopen(“filename”, “r”); integer mcd = $fopen(“filename”); Can write to multiple multi-channel files simultaneously using bit-wise OR ( | ) of the descriptors Can only have 31 multi-channel files open at any time Easier to have “summary” and “detailed” results STDIN, STDOUT, STDERR are pre-opened $fclose closes the file: $fclose(fd); 20 Writing To Files Display statements have file equivalents $fdisplay() $fmonitor() No limit on number of $fmonitor tasks $fstrobe() $fwrite() $display without a newline These system calls take the file descriptor as the first argument $fdisplay(fd, “out=%b in=%b”, out, in); 21 Reading From Files Read a binary file: $fread(destination, fd); Can specify start address for loading into arrays Can specify a number of locations to load into array Returns number of bytes read, or 0 on error Formatted reading: $fscanf(fd, format, args); Very similar to C equivalent Reading characters/lines: $fgetc, $fgets Can use $sscanf after $fgets Other commands given in standard 22 Examples of Reading from Files reg [20:0] myreg; reg [7:0] character; reg [12*8:1] str reg [7:0] mem [15:0]; reg [3:0] a, b; integer code, start = 10, count = 20; integer fd = $fopen(“my_file”); character= $fgetc (fd); // returns -1 on error code = $fgets ( str, fd ); code = $sscanf(str, “%d %d \n", a, b); code = $fscanf(fd, “%d %d \n", a, b); code = $fread( myreg, fd); code = $fread( mem, fd); // reads binary data code = $fread( mem, fd, start, count); // See 17.2 of standard for more details 23 Loading Memory Data From Files Can read values from text file into a “memory” THIS IS NOT SYNTHESIZABLE $readmemb(“filename”, memname [, start [, stop]]); Reads binary (plain-text) numbers from text file $readmemh(“filename”, memname [, start [, stop]]); Reads hexadecimal (plain-text) numbers from text file White space and comments are ignored Can also specify addresses in the file itself @HH…HH Subsequent data will placed starting at the given address Can fill memory in ascending or decending order by changing the “start” and “stop” addresses 24 File I/O Example [1] `timescale 1 ns/ 100 ps module func_demo_nb_d0_clk_strobe; reg [7:0] memory[0:255]; // 256 byte memory integer descriptor; // used with fopen reg [7:0] address; wire [7:0] data; assign data = memory[address]; 25 File I/O Example [2] initial begin //read binary data into locations 0 through 15 of memory $readmemb("mem_data_in.txt", memory,0,15); // read hex data into all 256 bytes - overwrites $readmemh("mem_data_in_extra.txt", memory); //open file; capture descriptor descriptor = $fopen("mem_data_out.txt"); //close file at end of simulation run #210 $fclose(descriptor); $stop; end // Where might we use this type of file I/O? 26 File I/O Example [3] //event control block reg clk, reset; initial begin clk = 0; reset = 1; $fstrobe(descriptor, "Time: %d Address: %d Data: %h", $time, address, data); #2 reset = 0; #3 ; forever begin #5 clk = 1; $fstrobe(descriptor, "Time: %d Address: %d Data: %h", $time, address, data); #5 clk = 0; end end 27 File I/O Example [4] // Dump of memory locations 'd0 through 'd20 in hexadecimal always@(posedge clk or posedge reset) begin // save in file mem_data_out.txt if (reset) address <= 0; //initialize address else address <= address + 1; // advance address end endmodule 28 File I/O Example: Results Memory Dump Using $fstrobe Time: Time: Time: Time: Time: Time: Time: Time: Time: Time: Time: 0 Address: 10 Address: 20 Address: 30 Address: 40 Address: 50 Address: 60 Address: 70 Address: 80 Address: 90 Address: 100 Address: 0 Data: 01 1 Data: 02 2 Data: 04 3 Data: 08 4 Data: 10 5 Data: 20 6 Data: 40 7 Data: 80 8 Data: fe 9 Data: fd 10 Data: fb Time: Time: Time: Time: Time: Time: Time: Time: Time: Time: 110 120 130 140 150 160 170 180 190 200 Address: Address: Address: Address: Address: Address: Address: Address: Address: Address: 11 12 13 14 15 16 17 18 19 20 Data: Data: Data: Data: Data: Data: Data: Data: Data: Data: f7 ef df bf 7f cf xx 16 xx 03 29 Testbench Example module test_and; integer file, i, code; reg a, b, expect, clock; wire out; parameter CYCLE = 20; and #4 a0(out, a, b); // Circuit under test initial begin : file_block clock = 1’b0; file = $fopen("compare.txt", “r” ); for (i = 0; i < 4; i=i+1) begin @(posedge clock) // Read stimulus on rising clock code = $fscanf(file, "%b %b %b\n", a, b, expect); #(CYCLE - 1) // Compare just before end of cycle if (expect !== out) $strobe("%d %b %b %b %b", $time, a, b, expect, out); end // for $fclose(file); $stop; end // initial always #(CYCLE / 2) clock = ~clock; // Clock generator endmodule 30 $finish(n), $stop(n) Can print statistics about simulation at end n=0: n=1: n=2: prints nothing prints simulation time, location prints simulation time, location and CPU utilization, some statistics $finish causes simulation to stop Can cause tool to exit! $stop causes simulation to suspend Simulation may be resumed manually 31 Review Questions Why can’t the synthesizer process a “for” loop with the bounds determined by an input value? What is the difference between a latch and a flipflop? Why would we prefer one over the other? Give two reasons why, in a testbench, we might want to read from a file. Why are Verilog file commands not synthesizable? 32