aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/common/simlib.v
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/common/simlib.v')
-rw-r--r--techlibs/common/simlib.v210
1 files changed, 189 insertions, 21 deletions
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index d0feadd81..342555024 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -19,7 +19,7 @@
*
* The Simulation Library.
*
- * This verilog library contains simple simulation models for the internal
+ * This Verilog library contains simple simulation models for the internal
* cells ($not, ...) generated by the frontends and used in most passes.
*
* This library can be used to verify the internal netlists as generated
@@ -33,6 +33,12 @@
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $not (A, Y)
+//-
+//- A bit-wise inverter. This corresponds to the Verilog unary prefix '~' operator.
+//-
module \$not (A, Y);
parameter A_SIGNED = 0;
@@ -55,6 +61,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $pos (A, Y)
+//-
+//- A buffer. This corresponds to the Verilog unary prefix '+' operator.
+//-
module \$pos (A, Y);
parameter A_SIGNED = 0;
@@ -76,6 +88,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $neg (A, Y)
+//-
+//- An arithmetic inverter. This corresponds to the Verilog unary prefix '-' operator.
+//-
module \$neg (A, Y);
parameter A_SIGNED = 0;
@@ -97,6 +115,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $and (A, B, Y)
+//-
+//- A bit-wise AND. This corresponds to the Verilog '&' operator.
+//-
module \$and (A, B, Y);
parameter A_SIGNED = 0;
@@ -121,6 +145,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $or (A, B, Y)
+//-
+//- A bit-wise OR. This corresponds to the Verilog '|' operator.
+//-
module \$or (A, B, Y);
parameter A_SIGNED = 0;
@@ -145,6 +175,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $xor (A, B, Y)
+//-
+//- A bit-wise XOR. This corresponds to the Verilog '^' operator.
+//-
module \$xor (A, B, Y);
parameter A_SIGNED = 0;
@@ -169,6 +205,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $xnor (A, B, Y)
+//-
+//- A bit-wise XNOR. This corresponds to the Verilog '~^' operator.
+//-
module \$xnor (A, B, Y);
parameter A_SIGNED = 0;
@@ -193,6 +235,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $reduce_and (A, B, Y)
+//-
+//- An AND reduction. This corresponds to the Verilog unary prefix '&' operator.
+//-
module \$reduce_and (A, Y);
parameter A_SIGNED = 0;
@@ -214,6 +262,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $reduce_or (A, B, Y)
+//-
+//- An OR reduction. This corresponds to the Verilog unary prefix '|' operator.
+//-
module \$reduce_or (A, Y);
parameter A_SIGNED = 0;
@@ -235,6 +289,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $reduce_xor (A, B, Y)
+//-
+//- A XOR reduction. This corresponds to the Verilog unary prefix '^' operator.
+//-
module \$reduce_xor (A, Y);
parameter A_SIGNED = 0;
@@ -256,6 +316,12 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $reduce_xnor (A, B, Y)
+//-
+//- A XNOR reduction. This corresponds to the Verilog unary prefix '~^' operator.
+//-
module \$reduce_xnor (A, Y);
parameter A_SIGNED = 0;
@@ -277,6 +343,13 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $reduce_bool (A, B, Y)
+//-
+//- An OR reduction. This cell type is used instead of $reduce_or when a signal is
+//- implicitly converted to a boolean signal, e.g. for operands of '&&' and '||'.
+//-
module \$reduce_bool (A, Y);
parameter A_SIGNED = 0;
@@ -1156,6 +1229,48 @@ endmodule
`endif
// --------------------------------------------------------
+module \$sop (A, Y);
+
+parameter WIDTH = 0;
+parameter DEPTH = 0;
+parameter TABLE = 0;
+
+input [WIDTH-1:0] A;
+output reg Y;
+
+integer i, j;
+reg match;
+
+always @* begin
+ Y = 0;
+ for (i = 0; i < DEPTH; i=i+1) begin
+ match = 1;
+ for (j = 0; j < WIDTH; j=j+1) begin
+ if (TABLE[2*WIDTH*i + 2*j + 0] && A[j]) match = 0;
+ if (TABLE[2*WIDTH*i + 2*j + 1] && !A[j]) match = 0;
+ end
+ if (match) Y = 1;
+ end
+end
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$tribuf (A, EN, Y);
+
+parameter WIDTH = 0;
+
+input [WIDTH-1:0] A;
+input EN;
+output [WIDTH-1:0] Y;
+
+assign Y = EN ? A : 'bz;
+
+endmodule
+
+// --------------------------------------------------------
+
module \$assert (A, EN);
input A, EN;
@@ -1163,7 +1278,24 @@ input A, EN;
`ifndef SIMLIB_NOCHECKS
always @* begin
if (A !== 1'b1 && EN === 1'b1) begin
- $display("Assertation failed!");
+ $display("Assertion %m failed!");
+ $stop;
+ end
+end
+`endif
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$assume (A, EN);
+
+input A, EN;
+
+`ifndef SIMLIB_NOCHECKS
+always @* begin
+ if (A !== 1'b1 && EN === 1'b1) begin
+ $display("Assumption %m failed!");
$stop;
end
end
@@ -1208,7 +1340,7 @@ wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
genvar i;
generate
- for (i = 0; i < WIDTH; i = i+1) begin:bit
+ for (i = 0; i < WIDTH; i = i+1) begin:bitslices
always @(posedge pos_set[i], posedge pos_clr[i])
if (pos_clr[i])
Q[i] <= 0;
@@ -1277,7 +1409,7 @@ wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
genvar i;
generate
- for (i = 0; i < WIDTH; i = i+1) begin:bit
+ for (i = 0; i < WIDTH; i = i+1) begin:bitslices
always @(posedge pos_set[i], posedge pos_clr[i], posedge pos_clk)
if (pos_clr[i])
Q[i] <= 0;
@@ -1328,7 +1460,7 @@ output reg [WIDTH-1:0] Q;
always @* begin
if (EN == EN_POLARITY)
- Q <= D;
+ Q = D;
end
endmodule
@@ -1353,14 +1485,14 @@ wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
genvar i;
generate
- for (i = 0; i < WIDTH; i = i+1) begin:bit
+ for (i = 0; i < WIDTH; i = i+1) begin:bitslices
always @*
if (pos_clr[i])
- Q[i] <= 0;
+ Q[i] = 0;
else if (pos_set[i])
- Q[i] <= 1;
+ Q[i] = 1;
else if (pos_en)
- Q[i] <= D[i];
+ Q[i] = D[i];
end
endgenerate
@@ -1463,7 +1595,7 @@ endmodule
// --------------------------------------------------------
`ifndef SIMLIB_NOMEM
-module \$memrd (CLK, ADDR, DATA);
+module \$memrd (CLK, EN, ADDR, DATA);
parameter MEMID = "";
parameter ABITS = 8;
@@ -1473,7 +1605,7 @@ parameter CLK_ENABLE = 0;
parameter CLK_POLARITY = 0;
parameter TRANSPARENT = 0;
-input CLK;
+input CLK, EN;
input [ABITS-1:0] ADDR;
output [WIDTH-1:0] DATA;
@@ -1514,24 +1646,49 @@ endmodule
// --------------------------------------------------------
-module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
+module \$meminit (ADDR, DATA);
parameter MEMID = "";
-parameter SIZE = 256;
-parameter OFFSET = 0;
parameter ABITS = 8;
parameter WIDTH = 8;
+parameter WORDS = 1;
+
+parameter PRIORITY = 0;
+
+input [ABITS-1:0] ADDR;
+input [WORDS*WIDTH-1:0] DATA;
-parameter RD_PORTS = 1;
+initial begin
+ if (MEMID != "") begin
+ $display("ERROR: Found non-simulatable instance of $meminit!");
+ $finish;
+ end
+end
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
+
+parameter MEMID = "";
+parameter signed SIZE = 4;
+parameter signed OFFSET = 0;
+parameter signed ABITS = 2;
+parameter signed WIDTH = 8;
+parameter signed INIT = 1'bx;
+
+parameter signed RD_PORTS = 1;
parameter RD_CLK_ENABLE = 1'b1;
parameter RD_CLK_POLARITY = 1'b1;
parameter RD_TRANSPARENT = 1'b1;
-parameter WR_PORTS = 1;
+parameter signed WR_PORTS = 1;
parameter WR_CLK_ENABLE = 1'b1;
parameter WR_CLK_POLARITY = 1'b1;
input [RD_PORTS-1:0] RD_CLK;
+input [RD_PORTS-1:0] RD_EN;
input [RD_PORTS*ABITS-1:0] RD_ADDR;
output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
@@ -1561,25 +1718,36 @@ function port_active;
end
endfunction
+initial begin
+ for (i = 0; i < SIZE; i = i+1)
+ memory[i] = INIT >>> (i*WIDTH);
+end
+
always @(RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin
`ifdef SIMLIB_MEMDELAY
#`SIMLIB_MEMDELAY;
`endif
for (i = 0; i < RD_PORTS; i = i+1) begin
- if ((!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i]))
+ if (!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i] && RD_EN[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin
+ // $display("Read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]);
RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
+ end
end
for (i = 0; i < WR_PORTS; i = i+1) begin
if (port_active(WR_CLK_ENABLE[i], WR_CLK_POLARITY[i], LAST_WR_CLK[i], WR_CLK[i]))
for (j = 0; j < WIDTH; j = j+1)
- if (WR_EN[i*WIDTH+j])
+ if (WR_EN[i*WIDTH+j]) begin
+ // $display("Write to %s: addr=%b data=%b", MEMID, WR_ADDR[i*ABITS +: ABITS], WR_DATA[i*WIDTH+j]);
memory[WR_ADDR[i*ABITS +: ABITS] - OFFSET][j] = WR_DATA[i*WIDTH+j];
+ end
end
for (i = 0; i < RD_PORTS; i = i+1) begin
- if ((RD_TRANSPARENT[i] || !RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i]))
+ if ((RD_TRANSPARENT[i] || !RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin
+ // $display("Transparent read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]);
RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
+ end
end
LAST_RD_CLK <= RD_CLK;