1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-04 11:29:28 +00:00

verilog: scope updates, show js code, simple cpu

This commit is contained in:
Steven Hugg 2017-11-27 21:08:19 -05:00
parent a541b3c4e6
commit 80588fcb31
15 changed files with 921 additions and 27 deletions

View File

@ -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

View File

@ -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;

View File

@ -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; i<RESET_TICKS; i++)
this.tick2();
}
}
this.__unreset = function() {
if (this.reset !== undefined) {
this.reset = 0;
}
}
@ -169,6 +170,18 @@ var VerilogPlatform = function(mainElement, options) {
var switches = [0];
var inspect_obj, inspect_sym;
var inspect_data = new Uint32Array(videoWidth * videoHeight);
var scope_time_x = 0;
var scope_y_offset = 0;
var scope_max_y = 0;
var yposlist = [];
var lasty = [];
var lastval = [];
var ports_and_signals;
var trace_buffer;
var trace_index;
var mouse_pressed;
var dirty = false;
this.getPresets = function() { return VERILOG_PRESETS; }
@ -243,14 +256,31 @@ var VerilogPlatform = function(mainElement, options) {
video.updateFrame();
updateInspectionPostFrame();
self.restartDebugState();
gen.__unreset();
}
var yposlist = [];
var lasty = [];
function fillTraceBuffer(count) {
var arr = ports_and_signals;
var max_index = Math.min(trace_buffer.length, trace_index + count);
while (trace_index < max_index) {
gen.clk ^= 1;
gen.eval();
for (var i=0; i<arr.length; i++) {
var v = arr[i];
var z = gen[v.name];
trace_buffer[trace_index++] = z;
}
dirty = true;
}
gen.__unreset();
}
function updateScopeFrame() {
var arr = current_output.ports;
var arr = ports_and_signals;
if (!arr) return;
fillTraceBuffer(Math.floor(videoWidth/4) * arr.length);
if (!dirty) return;
dirty = false;
for (var i=0; i<idata.length; i++) {
if (idata[i])
idata[i] = 0; //<<= 1;
@ -258,18 +288,18 @@ var VerilogPlatform = function(mainElement, options) {
var COLOR_SIGNAL = 0xff22ff22;
var COLOR_BORDER = 0xff662222;
var COLOR_TRANS_SIGNAL = 0xff226622;
var COLOR_BLIP_SIGNAL = 0xff226622;
var j = 0;
for (var x=0; x<videoWidth; x++) {
gen.clk ^= 1;
gen.eval();
var yb = 8;
var y1 = 0;
var y1 = scope_y_offset;
for (var i=0; i<arr.length; i++) {
var v = arr[i];
var lo = 0; // TODO? v.ofs?
var hi = v.len ? ((2 << v.len)-1) : 1;
var ys = hi>1 ? 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<arr.length; i++) {
var v = arr[i];
ctx.fillStyle = v.name == inspect_sym ? "yellow" : "white";
ctx.fillText(v.name, 1, yposlist[i]);
//ctx.textAlign = 'right';
//ctx.fillText(""+gen[v.name], videoWidth-1, yposlist[i]);
var name = v.name;
ctx.fillStyle = name == inspect_sym ? "yellow" : "white";
name = name.replace(/__DOT__/g,'.');
ctx.textAlign = 'left';
ctx.fillText(name, 1, yposlist[i]);
if (scope_time_x > 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();

View File

@ -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();

View File

@ -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;
}

View File

@ -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');

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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