310 likes | 450 Views
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. For Loops In Hardware. Can use fixed-length for loops in modules
E N D
ECE 551Digital System Design & Synthesis Lecture 06 Loops Non-synthesizable Constructs File I/O
Topics • FOR Loops in non-testbench modules • Review • Invalid/non-synthesizable hardware • Testbenchoutput methods • File I/O
For Loops In Hardware • Can use fixed-length for loops in modules reg [15:0] countmem [0:7]; integeri; always @(posedgeclk) 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.
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
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.
Variable-Size For Loops • Using a forloop 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!
Instantiating in an Always Block • Cannot synthesize (or simulate): • Conceptually, why is this a problem? • Later we will learn about generate-if statements, which allow us to do something similar to this. module bad(input a, b, c, output d); always@(a,b,c) if (c) and(d, a, b); else or(d, a, b); endmodule
Cannot Detect x or z • Cannot Synthesize: modulefind_x(inputa, output b); always@(a) if(a === x) b = 1’b1; else b = 1’b0; endmodule
Cannot Detect x or z • Cannot Synthesize: • What if we had used casex? What would have been synthesized? modulefind_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
Feedback In Combinational Logic • What happenshere? • How can we fix it? // update the state always@(posedgeclk) begin if (rst) begin state <= 1’b0; count <= 8’d0; end else state <= next; end // find next state and // count the 3’b101 values always@(input, count) begin if (input == 3’b101) begin count = count + 1; next = 1’b1; endelsebegin next = 1’b0; end end
Fixing The Example // update the state and count always@(posedgeclk) begin if (rst) begin state <= 1’b0; count <= 8’d0; endelsebegin state <= next; count <= nextcount; end end // find next state and // count the 3’b101 values always@(state, input, count) begin if (input == 3’b101) begin nextcount = count + 1; next = 1’b1; endelsebegin nextcount = count; next = 1’b0; end end
We’ll cover a few more examples of code that doesn’t synthesize later in the semester
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)
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 initialforever @(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);
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);
%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]); initialbegin for (in = 0; in < 8; in = in + 1) #5; end endmodule module a(outputreg out, input a, b); always @(a, b) begin out = a & b; $display("%m: out=%b a=%b b=%b", out, a, b); end endmodule
%m Example [2] • Simulation results: … # mexample: out0=0 out1=0 in=010 # mexample.a0: out=0 a=0 b=1 // in=011 # mexample: out0=0 out1=0 in=011 # mexample.a0: out=0 a=1 b=0 // in=100 # mexample.a1: out=0 a=1 b=0 # mexample: out0=0 out1=0 in=100 # mexample.a0: out=1 a=1 b=1 // in=101 # mexample: out0=1 out1=0 in=101 # mexample.a0: out=0 a=1 b=0 // in=110 # mexample.a1: out=1 a=1 b=1 # mexample: out0=0 out1=1 in=110 # mexample.a0: out=1 a=1 b=1 // in 111 # mexample: out0=1 out1=1 in=111 …
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
Opening/Closing Files • $fopen opens a file and returns a descriptor • Syntax: integerdesc = $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. • integerfd = $fopen(“filename”, “r”); • If no mode is specified, $fopen opens the file for writing and returns a “multi-channel” descriptor • integermcd = $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);
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);
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
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; integerfd = $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
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
`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]; File I/O Example [1]
initialbegin //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? File I/O Example [2]
//event control block regclk, reset; initialbegin 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 File I/O Example [3]
// 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 File I/O Example [4]
Time: 0 Address: 0 Data: 01 Time: 10 Address: 1 Data: 02 Time: 20 Address: 2 Data: 04 Time: 30 Address: 3 Data: 08 Time: 40 Address: 4 Data: 10 Time: 50 Address: 5 Data: 20 Time: 60 Address: 6 Data: 40 Time: 70 Address: 7 Data: 80 Time: 80 Address: 8 Data: fe Time: 90 Address: 9 Data: fd Time: 100 Address: 10 Data: fb File I/O Example: Results Memory Dump Using $fstrobe Time: 110 Address: 11 Data: f7 Time: 120 Address: 12 Data: ef Time: 130 Address: 13 Data: df Time: 140 Address: 14 Data: bf Time: 150 Address: 15 Data: 7f Time: 160 Address: 16 Data: cf Time: 170 Address: 17 Data: xx Time: 180 Address: 18 Data: 16 Time: 190 Address: 19 Data: xx Time: 200 Address: 20 Data: 03
moduletest_and; integer file, i, code; reg a, b, expect, clock; wire out; parameter CYCLE = 20; and #4 a0(out, a, b); // Circuit under test initialbegin : 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 Testbench Example
$finish(n), $stop(n) • Can print statistics about simulation at end • n=0: prints nothing • n=1: prints simulation time, location • n=2: 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
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 flip-flop? 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?