%#`include "<%= options[:top] %>" // To create the big fonts - http://patorjk.com/software/taag/#p=display&f=Big `timescale 1ns/1ns // _____ _ _ _ _ _____ _ _____ _ // | __ \(_) (_) | | | | __ (_) | __ \ (_) // | | | |_ __ _ _| |_ __ _| | | |__) | _ __ | | | |_ __ ___ _____ _ __ // | | | | |/ _` | | __/ _` | | | ___/ | '_ \ | | | | '__| \ \ / / _ \ '__| // | |__| | | (_| | | || (_| | | | | | | | | | | |__| | | | |\ V / __/ | // |_____/|_|\__, |_|\__\__,_|_| |_| |_|_| |_| |_____/|_| |_| \_/ \___|_| // __/ | // |___/ // 0 - Data // 1 - Reserved // // 0 - Drive // // 0 - Compare // // 0 - Force data 0 // 1 - Force data 1 // // Parameter init_drive // 0 - Initialize drive and assign to 0 // 1 - Initialize drive and assign to 1 // 2 - Don't initialize drive and assign to Z (default) // -1 - Don't initialize drive or assign. Pin will be left unknown module pin_driver(pin, sync); parameter init_drive = 2; // Which means don't drive initially, set to 0 or 1 to drive parameter pin_name = "undefined_name"; inout pin; input sync; reg error; reg [1:0] data = 0; reg [1:0] force_data = 0; reg compare = 0; reg drive = 0; reg capture = 0; //reg [1023:0] memory = 0; reg [127:0] memory = 0; reg [127:0] memory_reversed = 0; reg [127:0] sync_memory = 0; wire drive_data = force_data[0] ? 0 : (force_data[1] ? 1 : data[0]); wire contention = drive ? (pin !== drive_data ? 1 : 0) : 0; if (init_drive != -1) begin assign pin = drive ? drive_data : 1'bz; end // Debug signal to show the expected data in the waves wire expect_data = compare ? data[0] : 1'bz; always @(*) begin error = (compare && !capture) ? (pin == data[0] ? 0 : 1) : 0; end // pin compare failure logger always @(posedge error) begin //$display("!4![%t] Miscompare on pin %s, expected %d received %d", $time, pin_name, data[0], pin); $bridge_on_miscompare(pin_name, data[0], pin); end // SMcG - needs more work, causes non-genuine fails in OrigenSim test case //// pin contention logger //always @(posedge contention) begin // $display("OrigenSim Error: contention on pin %s, tester drives %d beginning at %t", pin_name, drive_data, $time); //end always @(posedge capture) begin if (sync == 1) begin sync_memory[127:1] <= sync_memory[126:0]; sync_memory[0] <= pin; end else begin memory[127:1] <= memory[126:0]; memory[0] <= pin; memory_reversed[126:0] <= memory_reversed[127:1]; memory_reversed[127] <= pin; end end initial begin // Set the timescale to ns (-9) with 0 decimal place precision, 20 chars //$timeformat(-9, 0, "", 20); if (init_drive == 1) begin drive = 1; data[0] = 1; end else if (init_drive == 0) begin drive = 1; data[0] = 0; end end endmodule `ifdef ORIGEN_WREAL // _ _____ _ _____ _ // /\ | | | __ (_) | __ \ (_) // / \ _ __ __ _| | ___ __ _ | |__) | _ __ | | | |_ __ ___ _____ _ __ // / /\ \ | '_ \ / _` | |/ _ \ / _` | | ___/ | '_ \ | | | | '__| \ \ / / _ \ '__| // / ____ \| | | | (_| | | (_) | (_| | | | | | | | | | |__| | | | |\ V / __/ | // /_/ \_\_| |_|\__,_|_|\___/ \__, | |_| |_|_| |_| |_____/|_| |_| \_/ \___|_| // __/ | // |___/ // A simple WREAL pin driver that can drive real value on a pin or else hi-Z, when the driver is in // hi-Z mode the value applied by any other driver connected to the pin can be measured by peeking // the value on pin module ana_pin_driver(pin); inout pin; wreal pin; reg drive_en = 0; real drive = 0.0; // Value that will be driven on pin when drive is enabled assign pin = drive_en ? drive : `wrealZState; endmodule `endif // _____ _ __ __ _ _ // | __ (_) | \/ | | | | | // | |__) | _ __ ___ | \ / | ___ __| |_ _| | ___ // | ___/ | '_ \/ __| | |\/| |/ _ \ / _` | | | | |/ _ \ // | | | | | | \__ \ | | | | (_) | (_| | |_| | | __/ // |_| |_|_| |_|___/ |_| |_|\___/ \__,_|\__,_|_|\___| // This module groups all pin drivers together and will be instantiated as origen.pins, individual pin // drivers are therefore accessible via origen.pins.my_pin_name module pin_drivers(<%= dut.rtl_pins.map { |n, p, o| "#{p.id}_o" }.join(', ') %>); % dut.rtl_pins.each do |name, pin, options| % if pin.type == :analog `ifdef ORIGEN_WREAL inout <%= pin.id %>_o; `else output <%= pin.id %>_o; `endif % else output <%= pin.id %>_o; % end % end `ifdef ORIGEN_WREAL % dut.rtl_pins(type: :analog).each do |name, pin, options| wreal <%= pin.id %>_o; % end `endif reg sync = 0; % dut.rtl_pins.each do |name, pin, options| % unless pin.meta[:origen_sim_init_pin_state] == -2 % if pin.type == :analog `ifdef ORIGEN_WREAL ana_pin_driver <%= pin.id %>(.pin(<%= pin.id %>_o)); `else pin_driver #(<%= pin.meta[:origen_sim_init_pin_state].nil? ? '' : ".init_drive(#{pin.meta[:origen_sim_init_pin_state]}), "%>.pin_name("<%= pin.id %>")) <%= pin.id %>(.pin(<%= pin.id %>_o), .sync(sync)); `endif % else pin_driver #(<%= pin.meta[:origen_sim_init_pin_state].nil? ? '' : ".init_drive(#{pin.meta[:origen_sim_init_pin_state]}), "%>.pin_name("<%= pin.id %>")) <%= pin.id %>(.pin(<%= pin.id %>_o), .sync(sync)); % end % end % end endmodule // __ __ _ _ _ // | \/ | | | | | | | // | \ / | ___| |_ __ _ __| | __ _| |_ __ _ // | |\/| |/ _ \ __/ _` |/ _` |/ _` | __/ _` | // | | | | __/ || (_| | (_| | (_| | || (_| | // |_| |_|\___|\__\__,_|\__,_|\__,_|\__\__,_| // Placeholder for user notes. This will be an empty module if no notes were given module user_details; parameter _AVAILABLE_DETAILS_ = "<%= options[:user_details].empty? ? "" : options[:user_details].keys.join(',') %>"; % options[:user_details].each do |name, note| parameter <%= name %> = "<%= note %>"; % end endmodule // SnapshotDetails module. Just stores some traceability details into the snapshot // that can be queried by OrigenSim or viewed in the waveform viewer. module snapshot_details; // Add a parameter that lists the available parameters. OrigenSim can use this known parameter to query any others that are // added here. parameter _AVAILABLE_DETAILS_ = "ORIGEN_SIM_VERSION,COMPILATION_TIME_STAMP,COMPILATION_PATH,DEVICE_NAME,REVISION,REVISION_NOTE,TESTBENCH_VERSION,AUTHOR"; parameter ORIGEN_SIM_VERSION = "<%= OrigenSim::VERSION %>"; parameter COMPILATION_TIME_STAMP = "<%= Time.now %>"; parameter COMPILATION_PATH = "<%= Dir.pwd %>"; parameter DEVICE_NAME = "<%= options[:device_name] || 'No --device_name specified' %>"; parameter REVISION = "<%= options[:revision] || 'No --revision specified' %>"; parameter REVISION_NOTE = "<%= options[:revision_note] || 'No --revision_note specified' %>"; parameter TESTBENCH_VERSION = "<%= options[:parent_tb_version] || 'No --testbench_version specified' %>"; parameter AUTHOR = "<%= options[:author] || Origen.current_user.username %>"; user_details user_details(); endmodule // _____ _ // | __ \ | | // | | | | ___| |__ _ _ __ _ // | | | |/ _ \ '_ \| | | |/ _` | // | |__| | __/ |_) | |_| | (_| | // |_____/ \___|_.__/ \__,_|\__, | // __/ | // |___/ // Instantiated as origen.debug, this module contains the error count, current pattern name and comments, // metadata associated with the snapshot build, and other debug information module debug; reg [31:0] errors = 0; reg [15:0] marker = 0; reg [31:0] match_errors = 0; reg [1023:0] pattern = 0; % OrigenSim::NUMBER_OF_COMMENT_LINES.times do |i| reg [1023:0] comments<%= i %> = 'h20; // Contain a space by default % end reg handshake; snapshot_details snapshot_details(); `ifdef ORIGEN_WREAL reg wreal_enabled = 1; `else reg wreal_enabled = 0; `endif endmodule // _______ _ _ _______ ____ // |__ __| | | | | |__ __| _ \ // | | ___ _ __ ______| | _____ _____| | | | | |_) | // | |/ _ \| '_ \______| | / _ \ \ / / _ \ | | | | _ < // | | (_) | |_) | | |___| __/\ V / __/ | | | | |_) | // |_|\___/| .__/ |______\___| \_/ \___|_| |_| |____/ // | | // |_| module origen; reg finish = 0; % dut.rtl_pins.each do |name, pin, options| % if pin.type == :analog `ifdef ORIGEN_WREAL wreal <%= pin.id %>; `else wire <%= pin.id %>; `endif % else wire <%= pin.id %>; % end % end pin_drivers pins ( % dut.rtl_pins.each_with_index do |(name, pin, options), i| .<%= pin.id %>_o(<%= pin.id %>)<%= i == dut.rtl_pins.size - 1 ? '' : ',' %> % end ); // Instantiate the DUT <%= options[:top].sub(/\..*/, '') %> dut ( % dut.power_pins.each do |name, pin, options| .<%= pin.id %>(<%= pin.id %>), % end % dut.ground_pins.each do |name, pin, options| .<%= pin.id %>(<%= pin.id %>), % end % # Keep track of the primary groups seen. % seen_groups = [] % dut.rtl_pins.each_with_index do |(name, pin, options), i| % if options[:group] % unless seen_groups.include?(pin.primary_group) .<%= pin.primary_group.id %>({ % pin.primary_group.each_with_index do |pin, i| <%= pin.id %><%= i == (pin.primary_group.size - 1) ? '' : ',' %> % end })<%= (i + pin.primary_group.size) == dut.rtl_pins.size ? '' : ',' %> % seen_groups << pin.primary_group % end % else .<%= pin.rtl_name %>(<%= pin.id %>)<%= i == (dut.rtl_pins.size - 1) ? '' : ',' %> % end % end ); debug debug (); initial begin `ifdef ORIGEN_VCS $origen_vcs_init; `endif `ifdef ORIGEN_VCD $dumpvars(0,origen); `endif `ifdef ORIGEN_VPD $vcdplusfile("origen.vpd"); $vcdpluson; $vcdplusmemon; `endif `ifdef ORIGEN_FSDB $fsdbDumpfile("origen.fsdb"); $fsdbDumpvars(0, "+all"); `endif end always @(posedge finish) begin $finish(2); end % Array(options[:incl]).each do |f| `include "<%= "#{f}" %>" % end endmodule