//////////////////////////////////////////////////////////////////////////////// // /// LSU EE 4755 Fall 2014 Homework 4 // /// Assignment http://www.ece.lsu.edu/koppel/v/2014f/hw04.pdf /// Instructions: // // (1) Find the undergraduate workstation laboratory, room 126 EE // Building. // // (2) Locate your account. If you did not get an account please // E-mail: koppel@ece.lsu.edu // // (3) Log in to a Linux workstation. // The account should start up with a WIMP interface (windows, icons, // mouse, pull-down menus) ( :-) ) but one or two things need // to be done from a command-line shell. If you need to brush up // on Unix commands follow http://www.ece.lsu.edu/koppel/v/4ltrwrd/. // // (4) If you haven't already, follow the account setup instructions here: // http://www.ece.lsu.edu/koppel/v/proc.html // // (5) Copy this assignment, local path name // /home/faculty/koppel/pub/ee4755/hw/2014f/hw04 // to a directory ~/hw04 in your class account. (~ is your home // directory.) Use this file for your solution. // // (6) Solve the problems. // // Your entire Verilog solution should be in this file. // Put answers to written questions in this file or submit them // by E-mail or on paper. // // Do not change module names. // // (7) Your solution will automatically be copied from your account by // the TA-bot. /// Additional Resources // // Verilog Documentation // The Verilog Standard // http://standards.ieee.org/getieee/1800/download/1800-2012.pdf // Introductory Treatment (Warning: Does not include SystemVerilog) // Brown & Vranesic, Fundamentals of Digital Logic with Verilog, 3rd Ed. // // Account Setup and Emacs (Text Editor) Instructions // http://www.ece.lsu.edu/koppel/v/proc.html // To learn Emacs look for Emacs tutorial. // // Help with Cadence Verilog Simulator and Synthesis Programs // http://www.ece.lsu.edu/v/ref.html // UserID is ee3755, password was given in class. // // Unix Help // http://www.ece.lsu.edu/koppel/v/4ltrwrd/ typedef enum { Char_escape = 1, Char_0 = 48, Char_9 = 57 } Chars_Special; module asc_to_bin #( int size_lg = 4, int max_chars = 4, int size = 1 << size_lg ) ( output [7:0] char_out, output can_insert, can_remove, input [7:0] char_in, input insert_req, remove_req, input reset, clk); logic [7:0] storage [size]; logic [size_lg:1] head, tail; uwire is_digit = char_in >= Char_0 && char_in <= Char_9; uwire empty = head == tail; uwire full = tail + 1 == head; assign can_insert = !full; assign can_remove = !empty; assign char_out = storage[head]; // cadence translate_off initial for ( int i=0; i<size; i++ ) storage[i] = 255; // cadence translate_on always @( posedge clk ) if ( reset ) begin tail <= 0; end else begin if ( insert_req ) begin storage[tail] <= char_in; tail <= tail + 1; end end always @( posedge clk ) if ( reset ) begin head <= 0; end else if ( remove_req ) begin head <= head + 1; end endmodule // cadence translate_off module testbench(); localparam int elts_lg = 4; localparam int elts = 1 << elts_lg; localparam int int_chars = 2; uwire [7:0] char_out; uwire can_insert, can_remove; logic [7:0] char_in; logic insert_req, remove_req, reset, clk; asc_to_bin #(elts_lg,int_chars) b1 (char_out,can_insert,can_remove,char_in,insert_req,remove_req,reset,clk); int cycle_num; initial begin clk = 0; cycle_num = 0; fork forever #1 clk = !clk; forever @( posedge clk ) cycle_num++; join end string in_str = "One 1 two 12 three 317 four 1234 six 123456 ten 1234567890. There are 60 seconds in a minute and 31536000 in a year."; string out_str = ""; initial begin automatic int insert_finished_cyc = 0; automatic int out_size = 0; automatic bit tb_insert_done = 0; automatic bit tb_remove_done = 0; /// Reset the module. // reset = 0; insert_req = 0; remove_req = 0; @( negedge clk ) reset = 1; @( negedge clk ) reset = 0; @( negedge clk ); /// Check for one possible error. // if ( can_insert !== 1 ) begin $display("Module did not reset, can_insert: %h\n", can_insert); $fatal(1); end /// Start Main Testing Loops // fork /// Watchdog -- Stop simulation if it's taking too long. // fork begin automatic int cyc_limit = in_str.len() * 100; fork wait ( cycle_num == cyc_limit ); wait ( tb_insert_done && tb_remove_done ); join_any if ( cycle_num >= cyc_limit ) begin $display("Exceeded cycle limit, exiting.\n"); $fatal(1); end end join_none /// Trace Execution -- Print Signal Values After Interesting Changes // while ( !tb_insert_done || !tb_remove_done ) begin @( insert_req or remove_req or can_insert or can_remove or b1.tail or b1.head or tb_insert_done or tb_remove_done ); @( negedge clk ); /// Trace execution by showing removed character and /// related information. // $display( "c In %c Out %d = %c tail %d head %d ", char_in, char_out, char_out, b1.tail, b1.head); end /// Insert Characters // begin automatic int in_pos = 0; while ( in_pos < in_str.len() ) begin @( negedge clk ); // Flip a coin, and if it comes up tails send a character // in if module is ready for one. // if ( {$random} & 'h1 && can_insert ) begin char_in = in_str[in_pos++]; insert_req = 1; end else begin insert_req = 0; end end @( negedge clk ); insert_req = 0; insert_finished_cyc = cycle_num; $display("Done feeding inputs."); tb_insert_done = 1; end /// Remove Characters // begin int buffer; automatic int bytes_remaining = 0; while ( insert_finished_cyc == 0 || cycle_num < insert_finished_cyc + elts * 10 ) begin @( negedge clk ); if ( {$random} & 1 && can_remove ) begin remove_req = 1; out_size++; if ( bytes_remaining > 0 ) begin buffer = ( buffer << 8 ) + char_out; bytes_remaining--; if ( bytes_remaining == 0 ) begin // Convert binary number back to ASCII. string iasc; iasc.itoa(buffer); out_str = {out_str,iasc}; end end else if ( char_out == Char_escape ) begin bytes_remaining = int_chars; buffer = 0; end else begin out_str = {out_str,char_out}; end end else begin remove_req = 0; end end $display("Done gathering outputs.\n"); tb_remove_done = 1; end join if ( in_str != out_str ) $display("** Error - strings don't match.\n"); else $display("Correct output, strings match. %s", ( in_str.len() == out_size ) ? "But no compression!" : ""); $display("In size %d bytes, out size %d bytes.\n", in_str.len(), out_size); $display("In - %s\nOut- %s\n", in_str, out_str); $finish(2); end endmodule // cadence translate_on