aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/common/simlib.v
diff options
context:
space:
mode:
authorAhmed Irfan <irfan@levert.(none)>2015-04-03 16:38:07 +0200
committerAhmed Irfan <irfan@levert.(none)>2015-04-03 16:38:07 +0200
commitbdf6b2b19ab2206f5957ad5b2ec582c2730d45ee (patch)
tree1d02541701054a1c3b1cdb66478d0cbc31c2d38f /techlibs/common/simlib.v
parent8acdd90bc918b780ad45cdac42b3baf84d2cc476 (diff)
parent4b4490761949e738dee54bdfc52e080e0a5c9067 (diff)
downloadyosys-bdf6b2b19ab2206f5957ad5b2ec582c2730d45ee.tar.gz
yosys-bdf6b2b19ab2206f5957ad5b2ec582c2730d45ee.tar.bz2
yosys-bdf6b2b19ab2206f5957ad5b2ec582c2730d45ee.zip
Merge branch 'master' of https://github.com/cliffordwolf/yosys
Diffstat (limited to 'techlibs/common/simlib.v')
-rw-r--r--techlibs/common/simlib.v238
1 files changed, 138 insertions, 100 deletions
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index 2d8088adb..abd2af521 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -1160,12 +1160,51 @@ module \$assert (A, EN);
input A, EN;
+`ifndef SIMLIB_NOCHECKS
always @* begin
if (A !== 1'b1 && EN === 1'b1) begin
- $display("Assertation failed!");
- $finish;
+ $display("Assertation %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
+`endif
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$equiv (A, B, Y);
+
+input A, B;
+output Y;
+
+assign Y = (A !== 1'bx && A !== B) ? 1'bx : A;
+
+`ifndef SIMLIB_NOCHECKS
+always @* begin
+ if (A !== 1'bx && A !== B) begin
+ $display("Equivalence failed!");
+ $stop;
end
end
+`endif
endmodule
@@ -1217,6 +1256,25 @@ end
endmodule
// --------------------------------------------------------
+
+module \$dffe (CLK, EN, D, Q);
+
+parameter WIDTH = 0;
+parameter CLK_POLARITY = 1'b1;
+parameter EN_POLARITY = 1'b1;
+
+input CLK, EN;
+input [WIDTH-1:0] D;
+output reg [WIDTH-1:0] Q;
+wire pos_clk = CLK == CLK_POLARITY;
+
+always @(posedge pos_clk) begin
+ if (EN == EN_POLARITY) Q <= D;
+end
+
+endmodule
+
+// --------------------------------------------------------
`ifndef SIMLIB_NOSR
module \$dffsr (CLK, SET, CLR, D, Q);
@@ -1287,7 +1345,7 @@ output reg [WIDTH-1:0] Q;
always @* begin
if (EN == EN_POLARITY)
- Q <= D;
+ Q = D;
end
endmodule
@@ -1315,11 +1373,11 @@ generate
for (i = 0; i < WIDTH; i = i+1) begin:bit
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
@@ -1430,6 +1488,7 @@ parameter WIDTH = 8;
parameter CLK_ENABLE = 0;
parameter CLK_POLARITY = 0;
+parameter TRANSPARENT = 0;
input CLK;
input [ABITS-1:0] ADDR;
@@ -1454,6 +1513,7 @@ parameter WIDTH = 8;
parameter CLK_ENABLE = 0;
parameter CLK_POLARITY = 0;
+parameter PRIORITY = 0;
input CLK;
input [WIDTH-1:0] EN;
@@ -1471,13 +1531,36 @@ endmodule
// --------------------------------------------------------
+module \$meminit (ADDR, DATA);
+
+parameter MEMID = "";
+parameter ABITS = 8;
+parameter WIDTH = 8;
+
+parameter PRIORITY = 0;
+
+input [ABITS-1:0] ADDR;
+input [WIDTH-1:0] DATA;
+
+initial begin
+ if (MEMID != "") begin
+ $display("ERROR: Found non-simulatable instance of $meminit!");
+ $finish;
+ end
+end
+
+endmodule
+
+// --------------------------------------------------------
+
module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
parameter MEMID = "";
-parameter SIZE = 256;
+parameter SIZE = 4;
parameter OFFSET = 0;
-parameter ABITS = 8;
+parameter ABITS = 2;
parameter WIDTH = 8;
+parameter signed INIT = 1'bx;
parameter RD_PORTS = 1;
parameter RD_CLK_ENABLE = 1'b1;
@@ -1497,107 +1580,62 @@ input [WR_PORTS*WIDTH-1:0] WR_EN;
input [WR_PORTS*ABITS-1:0] WR_ADDR;
input [WR_PORTS*WIDTH-1:0] WR_DATA;
-reg [WIDTH-1:0] data [SIZE-1:0];
-reg update_async_rd;
+reg [WIDTH-1:0] memory [SIZE-1:0];
-genvar i;
-generate
+integer i, j;
+reg [WR_PORTS-1:0] LAST_WR_CLK;
+reg [RD_PORTS-1:0] LAST_RD_CLK;
+
+function port_active;
+ input clk_enable;
+ input clk_polarity;
+ input last_clk;
+ input this_clk;
+ begin
+ casez ({clk_enable, clk_polarity, last_clk, this_clk})
+ 4'b0???: port_active = 1;
+ 4'b1101: port_active = 1;
+ 4'b1010: port_active = 1;
+ default: port_active = 0;
+ endcase
+ end
+endfunction
- for (i = 0; i < RD_PORTS; i = i+1) begin:rd
- if (RD_CLK_ENABLE[i] == 0) begin:rd_noclk
- always @(RD_ADDR or update_async_rd)
- RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
- end else
- if (RD_TRANSPARENT[i] == 1) begin:rd_transparent
- reg [ABITS-1:0] addr_buf;
- if (RD_CLK_POLARITY[i] == 1) begin:rd_trans_posclk
- always @(posedge RD_CLK[i])
- addr_buf <= RD_ADDR[i*ABITS +: ABITS];
- end else begin:rd_trans_negclk
- always @(negedge RD_CLK[i])
- addr_buf <= RD_ADDR[i*ABITS +: ABITS];
- end
- always @(addr_buf or update_async_rd)
- RD_DATA[i*WIDTH +: WIDTH] <= data[addr_buf - OFFSET];
- end else begin:rd_notransparent
- if (RD_CLK_POLARITY[i] == 1) begin:rd_notrans_posclk
- always @(posedge RD_CLK[i])
- RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
- end else begin:rd_notrans_negclk
- always @(negedge RD_CLK[i])
- RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
- end
+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])) 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:wr
- integer k, n;
- reg found_collision, run_update;
- if (WR_CLK_ENABLE[i] == 0) begin:wr_noclk
- always @(WR_ADDR or WR_DATA or WR_EN) begin
- run_update = 0;
- for (n = 0; n < WIDTH; n = n+1) begin
- if (WR_EN[i*WIDTH + n]) begin
- found_collision = 0;
- for (k = i+1; k < WR_PORTS; k = k+1)
- if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS])
- found_collision = 1;
- if (!found_collision) begin
- data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n];
- run_update = 1;
- end
- end
- end
- if (run_update) begin
- update_async_rd <= 1;
- update_async_rd <= 0;
+ 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]) 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
- end else
- if (WR_CLK_POLARITY[i] == 1) begin:rd_posclk
- always @(posedge WR_CLK[i]) begin
- run_update = 0;
- for (n = 0; n < WIDTH; n = n+1) begin
- if (WR_EN[i*WIDTH + n]) begin
- found_collision = 0;
- for (k = i+1; k < WR_PORTS; k = k+1)
- if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS])
- found_collision = 1;
- if (!found_collision) begin
- data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n];
- run_update = 1;
- end
- end
- end
- if (run_update) begin
- update_async_rd <= 1;
- update_async_rd <= 0;
- end
- end
- end else begin:rd_negclk
- always @(negedge WR_CLK[i]) begin
- run_update = 0;
- for (n = 0; n < WIDTH; n = n+1) begin
- if (WR_EN[i*WIDTH + n]) begin
- found_collision = 0;
- for (k = i+1; k < WR_PORTS; k = k+1)
- if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS])
- found_collision = 1;
- if (!found_collision) begin
- data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n];
- run_update = 1;
- end
- end
- end
- if (run_update) begin
- update_async_rd <= 1;
- update_async_rd <= 0;
- end
- 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])) 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
-endgenerate
+ LAST_RD_CLK <= RD_CLK;
+ LAST_WR_CLK <= WR_CLK;
+end
endmodule