diff options
Diffstat (limited to 'techlibs/common/simlib.v')
-rw-r--r-- | techlibs/common/simlib.v | 210 |
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; |