diff --git a/presets/verilog/simple_cpu.v b/presets/verilog/simple_cpu.v new file mode 100644 index 00000000..18764978 --- /dev/null +++ b/presets/verilog/simple_cpu.v @@ -0,0 +1,196 @@ + +`define OP_LOAD_A 4'h0 +`define OP_LOAD_B 4'h1 +`define OP_ADD 4'h2 +`define OP_SUB 4'h3 +`define OP_INC 4'h4 +`define OP_DEC 4'h5 +`define OP_ASL 4'h6 +`define OP_LSR 4'h7 +`define OP_OR 4'h8 +`define OP_AND 4'h9 +`define OP_XOR 4'ha + +module ALU(A, B, Y, aluop); + + input [7:0] A; + input [7:0] B; + output [8:0] Y; + input [3:0] aluop; + + always @(*) + case (aluop) + `OP_LOAD_A: Y = {1'b0, A}; + `OP_LOAD_B: Y = {1'b0, B}; + `OP_ADD: Y = A + B; + `OP_SUB: Y = A - B; + `OP_INC: Y = A + 1; + `OP_DEC: Y = A - 1; + `OP_ASL: Y = {A[7], A + A}; + `OP_LSR: Y = {A[0], A >> 1}; + `OP_OR: Y = {1'b0, A | B}; + `OP_AND: Y = {1'b0, A & B}; + `OP_XOR: Y = {1'b0, A ^ B}; + default: Y = 9'bx; + endcase + +endmodule + +`define REG_A 1'b0 +`define REG_B 1'b1 +`define I_CONST(r,x) { 2'b00, r, x } +`define I_LOAD_ADDR(r,addr) { 3'b010, r, addr } +`define I_STORE_ADDR(r,addr) { 3'b011, r, addr } +`define I_COMPUTE(r,op) { 3'b100, r, op } +`define I_RESET 8'hff + +module CPU(clk, reset, address, data_in, data_out, write); + + input clk, reset; + output [7:0] address; + input [7:0] data_in; + output [7:0] data_out; + output write; + + reg [7:0] ip; + reg [7:0] opcode; + reg [3:0] aluop; + reg [7:0] A, B; + reg [8:0] Y; + reg [1:0] state; + reg [2:0] action; + + reg carry; + reg zero; + + localparam NOOP = 0; + localparam MAKE_CONST = 1; + localparam LOAD_ADDR = 2; + localparam STORE_ADDR = 3; + localparam COMPUTE = 4; + + wire load_const = opcode[3:1] == 3'b111; + + ALU alu(.A(A), .B(B), .Y(Y), .aluop(aluop)); + + always @(posedge clk) + if (reset) begin + state <= 0; + write <= 0; + end else begin + case (state) + // state 0: reset + 0: begin + ip <= 8'h80; + write <= 0; + state <= 1; + end + // state 1: select opcode address + 1: begin + address <= ip; + ip <= ip + 1; + write <= 0; + state <= 2; + end + // state 2: read/decode opcode + 2: begin + casez (data_in) + 8'b00??????: begin + action <= MAKE_CONST; + if (data_in[5]) + B <= {3'b0, data_in[4:0]}; + else + A <= {3'b0, data_in[4:0]}; + state <= 1; + end + 8'b010?????: begin + action <= LOAD_ADDR; + address <= {4'b0, data_in[3:0]}; + state <= 3; + end + 8'b011?????: begin + action <= STORE_ADDR; + address <= {4'b0, data_in[3:0]}; + state <= 3; + end + 8'b100?????: begin + action <= COMPUTE; + aluop <= data_in[3:0]; + state <= 3; + end + default: begin + action <= NOOP; + state <= 0; // reset + end + endcase + opcode <= data_in; + end + // state 3: perform action + 3: begin + if (action == LOAD_ADDR) begin + if (opcode[4]) + B <= data_in; + else + A <= data_in; + end else if (action == STORE_ADDR) begin + if (opcode[4]) + data_out <= B; + else + data_out <= A; + write <= 1; + end else if (action == COMPUTE) begin + if (opcode[4]) + B <= Y[7:0]; + else + A <= Y[7:0]; + carry <= Y[8]; + zero <= ~|Y; + end + state <= 1; // repeat loop at state 1 + end + endcase + end + +endmodule + +module test_CPU_top(clk, reset, address_bus, to_cpu, from_cpu, write_enable); + + input clk, reset; + output [7:0] address_bus; + output reg [7:0] to_cpu; + output [7:0] from_cpu; + output write_enable; + + reg [7:0] ram[128]; + reg [7:0] rom[128]; + + CPU cpu(.clk(clk), + .reset(reset), + .address(address_bus), + .data_in(to_cpu), + .data_out(from_cpu), + .write(write_enable)); + + // does not work as (posedge clk) + always @(*) + if (write_enable) + ram[address_bus[6:0]] = from_cpu; + else if (address_bus[7] == 0) + to_cpu = ram[address_bus[6:0]]; + else + to_cpu = rom[address_bus[6:0]]; + + initial begin + // address 0x80 + rom['h00] = `I_CONST(`REG_A, 5'h1f); + rom['h01] = `I_COMPUTE(`REG_A, `OP_ASL); + rom['h02] = `I_COMPUTE(`REG_A, `OP_ASL); + rom['h03] = `I_COMPUTE(`REG_A, `OP_ASL); + rom['h04] = `I_COMPUTE(`REG_A, `OP_ASL); + rom['h05] = `I_COMPUTE(`REG_B, `OP_LOAD_A); + rom['h06] = `I_STORE_ADDR(`REG_B, 4'd1); + rom['h07] = `I_LOAD_ADDR(`REG_B, 4'd1); + rom['h08] = `I_RESET; + end + +endmodule diff --git a/presets/verilog/sprite_multiple.v b/presets/verilog/sprite_multiple.v index d45bb5b9..c3e6f696 100644 --- a/presets/verilog/sprite_multiple.v +++ b/presets/verilog/sprite_multiple.v @@ -17,6 +17,7 @@ module sprite_multiple_top(clk, hsync, vsync, rgb, hpaddle, vpaddle); reg [7:0] paddle_y; reg [7:0] enemy_x = 128; reg [7:0] enemy_y = 128; + reg enemy_dir = 0; reg [15:0] track_pos = 0; reg [7:0] speed = 31; @@ -73,17 +74,29 @@ module sprite_multiple_top(clk, hsync, vsync, rgb, hpaddle, vpaddle); if (!vpaddle) paddle_y <= vpos[7:0]; end + wire enemy_hit_left = (enemy_x == 64); + wire enemy_hit_right = (enemy_x == 192); + wire enemy_hit_edge = enemy_hit_left || enemy_hit_right; + always @(posedge vsync) begin player_x <= paddle_x; player_y <= 180; track_pos <= track_pos + {11'b0,speed[7:4]}; enemy_y <= enemy_y + {3'b0, speed[7:4]}; + if (enemy_hit_edge) + enemy_dir <= !enemy_dir; + if (enemy_dir ^ enemy_hit_edge) + enemy_x <= enemy_x + 1; + else + enemy_x <= enemy_x - 1; // collision check? if (frame_collision) speed <= 16; - else if (speed < 255) + else if (speed < ~paddle_y) speed <= speed + 1; + else + speed <= speed - 1; end reg frame_collision; diff --git a/src/platform/verilog.js b/src/platform/verilog.js index 55599ed9..de1f8308 100644 --- a/src/platform/verilog.js +++ b/src/platform/verilog.js @@ -92,16 +92,17 @@ function VerilatorBase() { this.ticks = function() { return totalTicks; } this.setTicks = function(T) { totalTicks = T|0; } - var RESET_TICKS = 1000; - - this.reset2 = function() { + this.__reset = function() { if (this.reset !== undefined) { totalTicks = 0; this.reset = 0; this.tick2(); this.reset = 1; - for (var i=0; i1 ? v.len*2+8 : 8; var y2 = y1+ys; - var z = gen[v.name]; + var z = trace_buffer[j++]; var y = Math.round(y2 - ys*((z-lo)/hi)); yposlist[i] = y2; var ly = lasty[i]; @@ -279,22 +309,29 @@ var VerilogPlatform = function(mainElement, options) { idata[x + ly*videoWidth] = COLOR_TRANS_SIGNAL; } } + idata[x + y*videoWidth] = lastval[i]==z ? COLOR_SIGNAL : COLOR_BLIP_SIGNAL; lasty[i] = y; - //idata[x + y1*videoWidth] = COLOR_BORDER; - //idata[x + y2*videoWidth] = COLOR_BORDER; - idata[x + y*videoWidth] = COLOR_SIGNAL; + lastval[i] = z; y1 += ys+yb; } } + scope_max_y = y1; video.updateFrame(); // draw labels var ctx = video.getContext(); for (var i=0; i 0) { + ctx.fillRect(scope_time_x, 0, 1, 4000); + ctx.textAlign = 'right'; + var value = arr.length * scope_time_x + i; + ctx.fillText(""+trace_buffer[value], videoWidth-1, yposlist[i]); + } } } @@ -312,8 +349,25 @@ var VerilogPlatform = function(mainElement, options) { ctx.textAlign = "left"; setKeyboardFromMap(video, switches, VERILOG_KEYCODE_MAP); $(video.canvas).mousemove(function(e) { - paddle_x = clamp(8,240,Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 20)); - paddle_y = clamp(8,240,Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height() - 20)); + var new_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 20); + var new_y = Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height() - 20); + if (mouse_pressed) { + scope_y_offset = clamp(-scope_max_y, 0, scope_y_offset + new_y - paddle_y); + scope_time_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 16); + dirty = true; + } + paddle_x = clamp(8, 240, new_x); + paddle_y = clamp(8, 240, new_y); + }); + $(video.canvas).mousedown(function(e) { + scope_time_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 16); + mouse_pressed = true; + e.target.setCapture(); + dirty = true; + }); + $(video.canvas).mouseup(function(e) { + mouse_pressed = false; + e.target.releaseCapture(); }); audio = new SampleAudio(AUDIO_FREQ); idata = video.getFrameData(); @@ -354,6 +408,9 @@ var VerilogPlatform = function(mainElement, options) { gen = new mod(base); gen.__proto__ = base; current_output = output; + ports_and_signals = current_output.ports.concat(current_output.signals); + trace_buffer = new Uint32Array(0x10000); + trace_index = 0; this.poweron(); } @@ -374,7 +431,10 @@ var VerilogPlatform = function(mainElement, options) { this.reset(); } this.reset = function() { - gen.reset2(); + gen.__reset(); + trace_index = 0; + trace_buffer.fill(0); + dirty = true; } this.tick = function() { gen.tick2(); diff --git a/src/ui.js b/src/ui.js index d6372910..afacc424 100644 --- a/src/ui.js +++ b/src/ui.js @@ -37,6 +37,7 @@ var platform_id; var platform; // platform object var originalFileID; var originalText; +var userPaused; var toolbar = $("#controls_top"); @@ -508,7 +509,7 @@ function setCompileOutput(data) { try { //console.log("Loading ROM length", rom.length); platform.loadROM(getCurrentPresetTitle(), rom); - resume(); + if (!userPaused) resume(); current_output = rom; resetProfiler(); toolbar.removeClass("has-errors"); @@ -625,6 +626,7 @@ function _pause() { function pause() { clearBreakpoint(); _pause(); + userPaused = true; } function _resume() { @@ -640,6 +642,7 @@ function resume() { if (! platform.isRunning() ) editor.setSelection(editor.getCursor()); // TODO?? _resume(); + userPaused = false; } function singleStep() { @@ -765,7 +768,7 @@ function updateDisassembly() { var div = $("#disassembly"); if (div.is(':visible')) { var state = lastDebugState || platform.saveState(); - var pc = state.c.PC; + var pc = state.c ? state.c.PC : 0; if (assemblyfile && assemblyfile.text) { var asmtext = assemblyfile.text; if (platform_id == 'base_z80') { // TODO @@ -818,6 +821,9 @@ function updateDisassembly() { disasmview.setValue(text); disasmview.setCursor(selline, 0); jumpToLine(disasmview, selline); + } else if (current_output.code) { + // show verilog javascript + disasmview.setValue(current_output.code); } } } @@ -1253,7 +1259,7 @@ function setupDebugControls(){ if (platform.getProbe) { $("#dbg_profile").click(toggleProfileWindow).show(); } - if (platform.saveState && platform_id != 'verilog') { // TODO: only show if listing or disasm available + if (platform.saveState) { // TODO: only show if listing or disasm available $("#dbg_disasm").click(toggleDisassembly).show(); } $("#disassembly").hide(); diff --git a/src/worker/workermain.js b/src/worker/workermain.js index 61281920..9d0a3bce 100644 --- a/src/worker/workermain.js +++ b/src/worker/workermain.js @@ -1023,7 +1023,9 @@ function assembleNAKEN(code, platform) { } function detectModuleName(code) { - var m = /\bmodule\s+(\w+_top)/.exec(code) || /\bmodule\s+(\w+)/.exec(code); + var m = /\bmodule\s+(\w+_top)\b/.exec(code) + || /\bmodule\s+(top)\b/.exec(code) + || /\bmodule\s+(\w+)\b/.exec(code); return m ? m[1] : null; } diff --git a/test/cli/testverilog.js b/test/cli/testverilog.js index 9187d24b..0f4d8daa 100644 --- a/test/cli/testverilog.js +++ b/test/cli/testverilog.js @@ -55,6 +55,17 @@ describe('Verilog Worker', function() { testVerilator('presets/verilog/lfsr.v'); // TODO: how to include files? + //testVerilator('test/cli/verilog/t_tri_gate.v'); + testVerilator('test/cli/verilog/t_tri_gen.v', ['UNDRIVEN']); + testVerilator('test/cli/verilog/t_tri_graph.v', ['UNDRIVEN']); + testVerilator('test/cli/verilog/t_tri_ifbegin.v', ['UNDRIVEN']); + testVerilator('test/cli/verilog/t_tri_inout.v'); + testVerilator('test/cli/verilog/t_tri_inout2.v'); + testVerilator('test/cli/verilog/t_tri_pullup.v', ['UNDRIVEN']); + testVerilator('test/cli/verilog/t_tri_select_unsized.v', ['WIDTH']); + testVerilator('test/cli/verilog/t_tri_unconn.v', ['PINCONNECTEMPTY']); + testVerilator('test/cli/verilog/t_tri_various.v', ['UNDRIVEN']); + /* TODO: fix tests testVerilator('test/cli/verilog/t_order_doubleloop.v', ['BLKSEQ']); testVerilator('test/cli/verilog/t_alw_combdly.v'); diff --git a/test/cli/verilog/t_tri_gen.v b/test/cli/verilog/t_tri_gen.v new file mode 100644 index 00000000..ad70726b --- /dev/null +++ b/test/cli/verilog/t_tri_gen.v @@ -0,0 +1,43 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + tri z0; + tri z1; + + updown #(0) updown0 (.z(z0)); + updown #(1) updown1 (.z(z1)); + + always @ (posedge clk) begin + if (z0 !== 0) $stop; + if (z1 !== 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule + +module updown #(parameter UP=0) + (inout z); + generate + if (UP) begin + t_up sub (.z); + end + else begin + t_down sub (.z); + end + endgenerate +endmodule + +module t_up (inout tri1 z); +endmodule + +module t_down (inout tri0 z); +endmodule diff --git a/test/cli/verilog/t_tri_graph.v b/test/cli/verilog/t_tri_graph.v new file mode 100644 index 00000000..fde19535 --- /dev/null +++ b/test/cli/verilog/t_tri_graph.v @@ -0,0 +1,27 @@ +// DESCRIPTION: Verilator: Unsupported tristate constructur error +// +// This is a compile only regression test of tristate handling for bug514 +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Jeremy Bennett. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + wire [11:0] ck; + + assign ck[1:0] = {1'bz,{1{1'b0}}}; + + test i_test (.clk (ck[1:0])); + +endmodule + + +module test (clk); + + output wire [1:0] clk; + +endmodule // test diff --git a/test/cli/verilog/t_tri_ifbegin.v b/test/cli/verilog/t_tri_ifbegin.v new file mode 100644 index 00000000..00e21fad --- /dev/null +++ b/test/cli/verilog/t_tri_ifbegin.v @@ -0,0 +1,52 @@ +// DESCRIPTION: Verilator: Verilog Test module + +module top (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + tri pad_io_h; + tri pad_io_l; + + sub sub (.*); + +endmodule + + +module sub (/*AUTOARG*/ + // Inouts + pad_io_h, pad_io_l + ); + + parameter USE = 1'b1; + parameter DIFFERENTIAL = 1'b1; + parameter BIDIR = 1'b1; + + inout pad_io_h; + inout pad_io_l; + + wire [31:0] dqs_out_dtap_delay; + + generate + if (USE) begin: output_strobe + wire aligned_os_oe; + wire aligned_strobe; + + if (BIDIR) begin + reg sig_h_r = 1'b0; + reg sig_l_r = 1'b0; + always @* begin + sig_h_r = ~aligned_os_oe ? aligned_strobe : 1'bz; + if (DIFFERENTIAL) + sig_l_r = ~aligned_os_oe ? ~aligned_strobe : 1'bz; + end + assign pad_io_h = sig_h_r; + if (DIFFERENTIAL) + assign pad_io_l = sig_l_r; + end + end + endgenerate + +endmodule + diff --git a/test/cli/verilog/t_tri_inout.v b/test/cli/verilog/t_tri_inout.v new file mode 100644 index 00000000..7322cf43 --- /dev/null +++ b/test/cli/verilog/t_tri_inout.v @@ -0,0 +1,19 @@ +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2008 by Lane Brooks + +module top (input A, input B, input SEL, output Y1, output Y2, output Z); + io io1(.A(A), .OE( SEL), .Z(Z), .Y(Y1)); + pass io2(.A(B), .OE(!SEL), .Z(Z), .Y(Y2)); + assign Z = 1'bz; +endmodule + +module pass (input A, input OE, inout Z, output Y); + io io(.A(A), .OE(OE), .Z(Z), .Y(Y)); + assign Z = 1'bz; +endmodule + +module io (input A, input OE, inout Z, output Y); + assign Z = (OE) ? A : 1'bz; + assign Y = Z; + assign Z = 1'bz; +endmodule diff --git a/test/cli/verilog/t_tri_inout2.v b/test/cli/verilog/t_tri_inout2.v new file mode 100644 index 00000000..f0d4ae87 --- /dev/null +++ b/test/cli/verilog/t_tri_inout2.v @@ -0,0 +1,77 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2008 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + reg [2:0] in; + + + wire a,y,y_fixed; + wire b = in[0]; + wire en = in[1]; + + + pullup(a); + + ChildA childa ( .A(a), .B(b), .en(en), .Y(y),.Yfix(y_fixed) ); + + initial in=0; + initial en=0; + + // Test loop + always @ (posedge clk) begin + + + in <= in + 1; + + $display ( "a %d b %d en %d y %d yfix: %d)" , a, b, en, y, y_fixed); + if (en) begin + // driving b + // a should be b + // y and yfix should also be b + if (a!=b || y != b || y_fixed != b) begin + $display ( "Expected a %d y %b yfix %b" , a, y, y_fixed); + $stop; + end + + end else begin + // not driving b + // a should be 1 (pullup) + // y and yfix shold be 1 + if (a!=1 || y != 1 || y_fixed != 1) begin + $display( "Expected a,y,yfix == 1"); + $stop; + end + end + + if (in==3) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule + +module ChildA(inout A, input B, input en, output Y, output Yfix); + + // workaround + wire a_in = A; + + ChildB childB(.A(A), .Y(Y)); + assign A = en ? B : 1'bz; + + + ChildB childBfix(.A(a_in),.Y(Yfix)); + + +endmodule + +module ChildB(input A, output Y); + assign Y = A; +endmodule + diff --git a/test/cli/verilog/t_tri_pullup.v b/test/cli/verilog/t_tri_pullup.v new file mode 100644 index 00000000..68617da5 --- /dev/null +++ b/test/cli/verilog/t_tri_pullup.v @@ -0,0 +1,26 @@ +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2008 by Lane Brooks + +module top (input A, input OE, output X, output Y, output Z); + + pullup p1(Z); + assign Z = OE ? A : 1'bz; + + pulldown p2(Y); + assign Y = OE ? A : 1'bz; + + pass pass(.A(A), .OE(OE), .X(X)); + pullup_module p(X); +endmodule + +module pass (input A, input OE, inout X); + io io(.A(A), .OE(OE), .X(X)); +endmodule + +module io (input A, input OE, inout X); + assign X = (OE) ? A : 1'bz; +endmodule + +module pullup_module (output X); + pullup p1(X); +endmodule diff --git a/test/cli/verilog/t_tri_select_unsized.v b/test/cli/verilog/t_tri_select_unsized.v new file mode 100644 index 00000000..2e2dbde5 --- /dev/null +++ b/test/cli/verilog/t_tri_select_unsized.v @@ -0,0 +1,27 @@ +// DESCRIPTION: Verilator: Test of selection with unsized Z. +// +// Test selecting Z when size is not explicit. Issue 510. +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Jeremy Bennett. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + wire [1:0] b; + wire [1:0] c; + wire [0:0] d; // Explicit width due to issue 508 + wire [0:0] e; + + // This works if we use 1'bz, or 1'bx, but not with just 'bz or 'bx. It + // does require the tri-state Z. Since we get the same effect if b is + // dimensioned [0:0], this may be connected to issue 508. + assign b[1:0] = clk ? 2'bx : 'bz; + assign c[1:0] = clk ? 2'bz : 'bx; + assign d = clk ? 1'bx : 'bz; + assign e = clk ? 1'bz : 'bx; + +endmodule // t diff --git a/test/cli/verilog/t_tri_unconn.v b/test/cli/verilog/t_tri_unconn.v new file mode 100644 index 00000000..d90db96d --- /dev/null +++ b/test/cli/verilog/t_tri_unconn.v @@ -0,0 +1,124 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + integer cyc=0; + + wire one = '1; + wire z0 = 'z; + wire z1 = 'z; + wire z2 = 'z; + wire z3 = 'z; + wire tog = cyc[0]; + + // verilator lint_off PINMISSING + t_tri0 tri0a (.line(`__LINE__), .expval(1'b0)); // Pin missing + t_tri0 tri0b (.line(`__LINE__), .expval(1'b0), .tn()); + t_tri0 tri0z (.line(`__LINE__), .expval(1'b0), .tn(z0)); + t_tri0 tri0Z (.line(`__LINE__), .expval(1'b0), .tn(1'bz)); + t_tri0 tri0c (.line(`__LINE__), .expval(1'b0), .tn(1'b0)); + t_tri0 tri0d (.line(`__LINE__), .expval(1'b1), .tn(1'b1)); // Warning would be reasonable given tri0 connect + t_tri0 tri0e (.line(`__LINE__), .expval(1'b0), .tn(~one)); + t_tri0 tri0f (.line(`__LINE__), .expval(1'b1), .tn(one)); + t_tri0 tri0g (.line(`__LINE__), .expval(~cyc[0]), .tn(~tog)); + t_tri0 tri0h (.line(`__LINE__), .expval(cyc[0]), .tn(tog)); + + t_tri1 tri1a (.line(`__LINE__), .expval(1'b1)); // Pin missing + t_tri1 tri1b (.line(`__LINE__), .expval(1'b1), .tn()); + t_tri1 tri1z (.line(`__LINE__), .expval(1'b1), .tn(z1)); + t_tri1 tri1Z (.line(`__LINE__), .expval(1'b1), .tn(1'bz)); + t_tri1 tri1c (.line(`__LINE__), .expval(1'b0), .tn(1'b0)); // Warning would be reasonable given tri1 connect + t_tri1 tri1d (.line(`__LINE__), .expval(1'b1), .tn(1'b1)); + t_tri1 tri1e (.line(`__LINE__), .expval(1'b0), .tn(~one)); + t_tri1 tri1f (.line(`__LINE__), .expval(1'b1), .tn(one)); + t_tri1 tri1g (.line(`__LINE__), .expval(~cyc[0]), .tn(~tog)); + t_tri1 tri1h (.line(`__LINE__), .expval(cyc[0]), .tn(tog)); + + t_tri2 tri2a (.line(`__LINE__), .expval(1'b0)); // Pin missing + t_tri2 tri2b (.line(`__LINE__), .expval(1'b0), .tn()); + t_tri2 tri2z (.line(`__LINE__), .expval(1'b0), .tn(z2)); + t_tri2 tri2Z (.line(`__LINE__), .expval(1'b0), .tn(1'bz)); + t_tri2 tri2c (.line(`__LINE__), .expval(1'b0), .tn(1'b0)); + t_tri2 tri2d (.line(`__LINE__), .expval(1'b1), .tn(1'b1)); + t_tri2 tri2e (.line(`__LINE__), .expval(1'b0), .tn(~one)); + t_tri2 tri2f (.line(`__LINE__), .expval(1'b1), .tn(one)); + t_tri2 tri2g (.line(`__LINE__), .expval(~cyc[0]), .tn(~tog)); + t_tri2 tri2h (.line(`__LINE__), .expval(cyc[0]), .tn(tog)); + + t_tri3 tri3a (.line(`__LINE__), .expval(1'b1)); // Pin missing + t_tri3 tri3b (.line(`__LINE__), .expval(1'b1), .tn()); + t_tri3 tri3z (.line(`__LINE__), .expval(1'b1), .tn(z3)); + t_tri3 tri3Z (.line(`__LINE__), .expval(1'b1), .tn(1'bz)); + t_tri3 tri3c (.line(`__LINE__), .expval(1'b0), .tn(1'b0)); + t_tri3 tri3d (.line(`__LINE__), .expval(1'b1), .tn(1'b1)); + t_tri3 tri3e (.line(`__LINE__), .expval(1'b0), .tn(~one)); + t_tri3 tri3f (.line(`__LINE__), .expval(1'b1), .tn(one)); + t_tri3 tri3g (.line(`__LINE__), .expval(~cyc[0]), .tn(~tog)); + t_tri3 tri3h (.line(`__LINE__), .expval(cyc[0]), .tn(tog)); + // verilator lint_on PINMISSING + + // Test loop + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc==99) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule + +module t_tri0 + (line, expval, tn); + input integer line; + input expval; + input tn; // Illegal to be inout; spec requires net connection to any inout + tri0 tn; + wire clk = t.clk; + always @(posedge clk) if (tn !== expval) begin + $display("%%Error: from line %0d got=%x exp=%x",line,tn,expval); $stop; + end +endmodule + +module t_tri1 + (line, expval, tn); + input integer line; + input expval; + input tn; + tri1 tn; + wire clk = t.clk; + always @(posedge clk) if (tn !== expval) begin + $display("%%Error: from line %0d got=%x exp=%x",line,tn,expval); $stop; + end +endmodule + +module t_tri2 + (line, expval, tn); + input integer line; + input expval; + input tn; + pulldown(tn); + wire clk = t.clk; + always @(posedge clk) if (tn !== expval) begin + $display("%%Error: from line %0d got=%x exp=%x",line,tn,expval); $stop; + end +endmodule + +module t_tri3 + (line, expval, tn); + input integer line; + input expval; + input tn; + pullup(tn); + wire clk = t.clk; + always @(negedge clk) if (tn !== expval) begin + $display("%%Error: from line %0d got=%x exp=%x",line,tn,expval); $stop; + end +endmodule diff --git a/test/cli/verilog/t_tri_various.v b/test/cli/verilog/t_tri_various.v new file mode 100644 index 00000000..8a336729 --- /dev/null +++ b/test/cli/verilog/t_tri_various.v @@ -0,0 +1,211 @@ +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2008 by Lane Brooks + +module t (clk); + input clk; + + reg [31:0] state; initial state=0; + + wire A = state[0]; + wire OE = state[1]; + wire Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9; + wire [3:0] Z10; + wire Z11; + + Test1 test1(/*AUTOINST*/ + // Inouts + .Z1 (Z1), + // Inputs + .OE (OE), + .A (A)); + + Test2 test2(/*AUTOINST*/ + // Inouts + .Z2 (Z2), + // Inputs + .OE (OE), + .A (A)); + + Test3 test3(/*AUTOINST*/ + // Inouts + .Z3 (Z3), + // Inputs + .OE (OE), + .A (A)); + + Test4 test4(/*AUTOINST*/ + // Outputs + .Z4 (Z4), + // Inouts + .Z5 (Z5)); + + Test5 test5(/*AUTOINST*/ + // Inouts + .Z6 (Z6), + .Z7 (Z7), + .Z8 (Z8), + .Z9 (Z9), + // Inputs + .OE (OE)); + + Test6 test6(/*AUTOINST*/ + // Inouts + .Z10 (Z10[3:0]), + // Inputs + .OE (OE)); + + Test7 test7(/*AUTOINST*/ + // Outputs + .Z11 (Z11), + // Inputs + .state (state[2:0])); + + always @(posedge clk) begin + state <= state + 1; +`ifdef TEST_VERBOSE + $write("[%0t] state=%d Z1=%b 2=%b 3=%b 4=%b 5=%b 6=%b 7=%b 8=%b 9=%b 10=%b 11=%b\n", + $time, state, Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9,Z10,Z11); +`endif + + if(state == 0) begin + if(Z1 !== 1'b1) $stop; // tests pullups + if(Z2 !== 1'b1) $stop; + if(Z3 !== 1'b1) $stop; +`ifndef VERILATOR + if(Z4 !== 1'b1) $stop; +`endif + if(Z5 !== 1'b1) $stop; + if(Z6 !== 1'b1) $stop; + if(Z7 !== 1'b0) $stop; + if(Z8 !== 1'b0) $stop; + if(Z9 !== 1'b1) $stop; + if(Z10 !== 4'b0001) $stop; + if(Z11 !== 1'b0) $stop; + end + else if(state == 1) begin + if(Z1 !== 1'b1) $stop; // tests pullup + if(Z2 !== 1'b1) $stop; + if(Z3 !== 1'b1) $stop; +`ifndef VERILATOR + if(Z4 !== 1'b1) $stop; +`endif + if(Z5 !== 1'b1) $stop; + if(Z6 !== 1'b1) $stop; + if(Z7 !== 1'b0) $stop; + if(Z8 !== 1'b0) $stop; + if(Z9 !== 1'b1) $stop; + if(Z10 !== 4'b0001) $stop; + if(Z11 !== 1'b1) $stop; + end + else if(state == 2) begin + if(Z1 !== 1'b0) $stop; // tests output driver low + if(Z2 !== 1'b0) $stop; + if(Z3 !== 1'b1 && Z3 !== 1'bx) $stop; // Conflicts +`ifndef VERILATOR + if(Z4 !== 1'b1) $stop; +`endif + if(Z5 !== 1'b1) $stop; + if(Z6 !== 1'b0) $stop; + if(Z7 !== 1'b1) $stop; + if(Z8 !== 1'b1) $stop; + if(Z9 !== 1'b0) $stop; + if(Z10 !== 4'b0010) $stop; + //if(Z11 !== 1'bx) $stop; // Doesn't matter + end + else if(state == 3) begin + if(Z1 !== 1'b1) $stop; // tests output driver high + if(Z2 !== 1'b1) $stop; + if(Z3 !== 1'b1) $stop; +`ifndef VERILATOR + if(Z4 !== 1'b1) $stop; +`endif + if(Z5 !== 1'b1) $stop; + if(Z6 !== 1'b0) $stop; + if(Z7 !== 1'b1) $stop; + if(Z8 !== 1'b1) $stop; + if(Z9 !== 1'b0) $stop; + if(Z10 !== 4'b0010) $stop; + if(Z11 !== 1'b1) $stop; + end + else if(state == 4) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + pullup(Z1); + pullup(Z2); + pullup(Z3); + pullup(Z4); + pullup(Z5); + pullup(Z6); + pulldown(Z7); + pullup(Z8); + pulldown(Z9); + pulldown pd10[3:0] (Z10); +endmodule + + +module Test1(input OE, input A, inout Z1); + assign Z1 = (OE) ? A : 1'bz; +endmodule + +module Test2(input OE, input A, inout Z2); + assign Z2 = (OE) ? A : 1'bz; +endmodule + + +// mixed low-Z and tristate +module Test3(input OE, input A, inout Z3); + assign Z3 = (OE) ? A : 1'bz; + assign Z3 = 1'b1; +endmodule + + +// floating output and inout +`ifndef VERILATOR +// Note verilator doesn't know to make Z4 a tristate unless marked an inout +`endif +module Test4(output Z4, inout Z5); +endmodule + + +// AND gate tristates +module Test5(input OE, inout Z6, inout Z7, inout Z8, inout Z9); + assign Z6 = (OE) ? 1'b0 : 1'bz; + assign Z7 = (OE) ? 1'b1 : 1'bz; + assign Z8 = (OE) ? 1'bz : 1'b0; + assign Z9 = (OE) ? 1'bz : 1'b1; +endmodule + +// AND gate tristates +module Test6(input OE, inout [3:0] Z10); + wire [1:0] i; + Test6a a (.OE(OE), .Z({Z10[0],Z10[1]})); + Test6a b (.OE(~OE), .Z({Z10[2],Z10[0]})); +endmodule + +module Test6a(input OE, inout [1:0] Z); + assign Z = (OE) ? 2'b01 : 2'bzz; +endmodule + +module Test7(input [2:0] state, output reg Z11); + always @(*) begin + casez (state) + 3'b000: Z11 = 1'b0; + 3'b0?1: Z11 = 1'b1; + default: Z11 = 1'bx; + endcase + end +endmodule + +// This is not implemented yet +//module Test3(input OE, input A, inout Z3); +// always @(*) begin +// if(OE) begin +// Z3 = A; +// end else begin +// Z3 = 1'bz; +// end +// end +//endmodule +