/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf * * 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 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * --- * * The Simulation Library. * * 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 * by the different frontends and passes. * * Note that memory can only be simulated when all $memrd and $memwr cells * have been merged to stand-alone $mem cells (this is what the "memory_collect" * pass is doing). * */ // -------------------------------------------------------- // |---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; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = ~$signed(A); end else begin:BLOCK2 assign Y = ~A; end endgenerate 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; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = $signed(A); end else begin:BLOCK2 assign Y = A; end endgenerate 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; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = -$signed(A); end else begin:BLOCK2 assign Y = -A; end endgenerate 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; parameter B_SIGNED = 0; parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED && B_SIGNED) begin:BLOCK1 assign Y = $signed(A) & $signed(B); end else begin:BLOCK2 assign Y = A & B; end endgenerate 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; parameter B_SIGNED = 0; parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED && B_SIGNED) begin:BLOCK1 assign Y = $signed(A) | $signed(B); end else begin:BLOCK2 assign Y = A | B; end endgenerate 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; parameter B_SIGNED = 0; parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED && B_SIGNED) begin:BLOCK1 assign Y = $signed(A) ^ $signed(B); end else begin:BLOCK2 assign Y = A ^ B; end endgenerate 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; parameter B_SIGNED = 0; parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED && B_SIGNED) begin:BLOCK1 assign Y = $signed(A) ~^ $signed(B); end else begin:BLOCK2 assign Y = A ~^ B; end endgenerate 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; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = &$signed(A); end else begin:BLOCK2 assign Y = &A; end endgenerate 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; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = |$signed(A); end else begin:BLOCK2 assign Y = |A; end endgenerate 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; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = ^$signed(A); end else begin:BLOCK2 assign Y = ^A; end endgenerate 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; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = ~^$signed(A); end else begin:BLOCK2 assign Y = ~^A; end endgenerate 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; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = !(!$signed(A)); end else begin:BLOCK2 assign Y = !(!A); end endgenerate endmodule // -------------------
/*
             LUFA Library
     Copyright (C) Dean Camera, 2017.

  dean [at] fourwalledcubicle [dot] com
           www.lufa-lib.org
*/

/*
  Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, distribute, and sell this
  software and its documentation for any purpose is hereby granted
  without fee, provided that the above copyright notice appear in
  all copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.

  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 any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

/** \file
 *
 *  Header file for XPROGProtocol.c.
 */

#ifndef _XPROG_PROTOCOL_
#define _XPROG_PROTOCOL_

	/* Includes: */
		#include <avr/io.h>
		#include <util/delay.h>
		#include <stdio.h>

		#include <LUFA/Drivers/USB/USB.h>

		#include "../V2Protocol.h"
		#include "XMEGANVM.h"
		#include "TINYNVM.h"
		#include "Config/AppConfig.h"

	/* Preprocessor Checks: */
		#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
			/* On the XPLAIN board, we only need PDI programming
			   for the ATXMEGA128A1 - disable ISP to prevent hardware
			   damage and force-enable XPROG.
			 */
			#undef ENABLE_ISP_PROTOCOL

			#if !defined(ENABLE_XPROG_PROTOCOL)
				#define ENABLE_XPROG_PROTOCOL
			#endif
		#endif

	/* Macros: */
		#define XPROG_CMD_ENTER_PROGMODE             0x01
		#define XPROG_CMD_LEAVE_PROGMODE             0x02
		#define XPROG_CMD_ERASE                      0x03
		#define XPROG_CMD_WRITE_MEM                  0x04
		#define XPROG_CMD_READ_MEM                   0x05
		#define XPROG_CMD_CRC                        0x06
		#define XPROG_CMD_SET_PARAM                  0x07

		#define XPROG_MEM_TYPE_APPL                  1
		#define XPROG_MEM_TYPE_BOOT                  2
		#define XPROG_MEM_TYPE_EEPROM                3
		#define XPROG_MEM_TYPE_FUSE                  4
		#define XPROG_MEM_TYPE_LOCKBITS              5
		#define XPROG_MEM_TYPE_USERSIG               6
		#define XPROG_MEM_TYPE_FACTORY_CALIBRATION   7

		#define XPROG_ERASE_CHIP                     1
		#define XPROG_ERASE_APP                      2
		#define XPROG_ERASE_BOOT                     3
		#define XPROG_ERASE_EEPROM                   4
		#define XPROG_ERASE_APP_PAGE                 5
		#define XPROG_ERASE_BOOT_PAGE                6
		#define XPROG_ERASE_EEPROM_PAGE              7
		#define XPROG_ERASE_USERSIG                  8

		#define XPROG_MEM_WRITE_ERASE                0
		#define XPROG_MEM_WRITE_WRITE                1

		#define XPROG_CRC_APP                        1
		#define XPROG_CRC_BOOT                       2
		#define XPROG_CRC_FLASH                      3

		#define XPROG_ERR_OK                         0
		#define XPROG_ERR_FAILED                     1
		#define XPROG_ERR_COLLISION                  2
		#define XPROG_ERR_TIMEOUT                    3

		#define XPROG_PARAM_NVMBASE                  0x01
		#define XPROG_PARAM_EEPPAGESIZE              0x02
		#define XPROG_PARAM_NVMCMD_REG               0x03
		#define XPROG_PARAM_NVMCSR_REG               0x04
		#define XPROG_PARAM_UNKNOWN_1                0x05

		#define XPROG_PROTOCOL_PDI                   0x00
		#define XPROG_PROTOCOL_JTAG                  0x01
		#define XPROG_PROTOCOL_TPI                   0x02

		#define XPROG_PAGEMODE_WRITE                 (1 << 1)
		#define XPROG_PAGEMODE_ERASE                 (1 << 0)

	/* External Variables: */
		extern uint32_t XPROG_Param_NVMBase;
		extern uint16_t XPROG_Param_EEPageSize;
		extern uint8_t  XPROG_Param_NVMCSRRegAddr;
		extern uint8_t  XPROG_Param_NVMCMDRegAddr;

	/* Function Prototypes: */
		void XPROGProtocol_SetMode(void);
		void XPROGProtocol_Command(void);

		#if (defined(INCLUDE_FROM_XPROGPROTOCOL_C) && defined(ENABLE_XPROG_PROTOCOL))
			static void XPROGProtocol_EnterXPROGMode(void);
			static void XPROGProtocol_LeaveXPROGMode(void);
			static void XPROGProtocol_SetParam(void);
			static void XPROGProtocol_Erase(void);
			static void XPROGProtocol_WriteMemory(void);
			static void XPROGProtocol_ReadMemory(void);
			static void XPROGProtocol_ReadCRC(void);
		#endif

#endif
(A, Y); parameter A_SIGNED = 0; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED) begin:BLOCK1 assign Y = !$signed(A); end else begin:BLOCK2 assign Y = !A; end endgenerate endmodule // -------------------------------------------------------- module \$logic_and (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED && B_SIGNED) begin:BLOCK1 assign Y = $signed(A) && $signed(B); end else begin:BLOCK2 assign Y = A && B; end endgenerate endmodule // -------------------------------------------------------- module \$logic_or (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 0; parameter B_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; generate if (A_SIGNED && B_SIGNED) begin:BLOCK1 assign Y = $signed(A) || $signed(B); end else begin:BLOCK2 assign Y = A || B; end endgenerate endmodule // -------------------------------------------------------- module \$slice (A, Y); parameter OFFSET = 0; parameter A_WIDTH = 0; parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; assign Y = A >> OFFSET; endmodule // -------------------------------------------------------- module \$concat (A, B, Y); parameter A_WIDTH = 0; parameter B_WIDTH = 0; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [A_WIDTH+B_WIDTH-1:0] Y; assign Y = {B, A}; endmodule // -------------------------------------------------------- module \$mux (A, B, S, Y); parameter WIDTH = 0; input [WIDTH-1:0] A, B; input S; output reg [WIDTH-1:0] Y; always @* begin if (S) Y = B; else Y = A; end endmodule // -------------------------------------------------------- module \$pmux (A, B, S, Y); parameter WIDTH = 0; parameter S_WIDTH = 0; input [WIDTH-1:0] A; input [WIDTH*S_WIDTH-1:0] B; input [S_WIDTH-1:0] S; output reg [WIDTH-1:0] Y; integer i; reg found_active_sel_bit; always @* begin Y = A; found_active_sel_bit = 0; for (i = 0; i < S_WIDTH; i = i+1) if (S[i]) begin Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i); found_active_sel_bit = 1; end end endmodule // -------------------------------------------------------- `ifndef SIMLIB_NOLUT module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; input [WIDTH-1:0] A; output reg Y; wire lut0_out, lut1_out; generate if (WIDTH <= 1) begin:simple assign {lut1_out, lut0_out} = LUT; end else begin:complex \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .A(A[WIDTH-2:0]), .Y(lut0_out) ); \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .A(A[WIDTH-2:0]), .Y(lut1_out) ); end if (WIDTH > 0) begin:lutlogic always @* begin casez ({A[WIDTH-1], lut0_out, lut1_out}) 3'b?11: Y = 1'b1; 3'b?00: Y = 1'b0; 3'b0??: Y = lut0_out; 3'b1??: Y = lut1_out; default: Y = 1'bx; endcase end end endgenerate 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 \$specify2 (EN, SRC, DST); parameter FULL = 0; parameter SRC_WIDTH = 1; parameter DST_WIDTH = 1; parameter SRC_DST_PEN = 0; parameter SRC_DST_POL = 0; parameter T_RISE_MIN = 0; parameter T_RISE_TYP = 0; parameter T_RISE_MAX = 0; parameter T_FALL_MIN = 0; parameter T_FALL_TYP = 0; parameter T_FALL_MAX = 0; input EN; input [SRC_WIDTH-1:0] SRC; input [DST_WIDTH-1:0] DST; localparam SD = SRC_DST_PEN ? (SRC_DST_POL ? 1 : 2) : 0; `ifdef SIMLIB_SPECIFY specify if (EN && SD==0 && !FULL) (SRC => DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && SD==0 && FULL) (SRC *> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && SD==1 && !FULL) (SRC +=> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && SD==1 && FULL) (SRC +*> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && SD==2 && !FULL) (SRC -=> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && SD==2 && FULL) (SRC -*> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); endspecify `endif endmodule // -------------------------------------------------------- module \$specify3 (EN, SRC, DST, DAT); parameter FULL = 0; parameter SRC_WIDTH = 1; parameter DST_WIDTH = 1; parameter EDGE_EN = 0; parameter EDGE_POL = 0; parameter SRC_DST_PEN = 0; parameter SRC_DST_POL = 0; parameter DAT_DST_PEN = 0; parameter DAT_DST_POL = 0; parameter T_RISE_MIN = 0; parameter T_RISE_TYP = 0; parameter T_RISE_MAX = 0; parameter T_FALL_MIN = 0; parameter T_FALL_TYP = 0; parameter T_FALL_MAX = 0; input EN; input [SRC_WIDTH-1:0] SRC; input [DST_WIDTH-1:0] DST, DAT; localparam ED = EDGE_EN ? (EDGE_POL ? 1 : 2) : 0; localparam SD = SRC_DST_PEN ? (SRC_DST_POL ? 1 : 2) : 0; localparam DD = DAT_DST_PEN ? (DAT_DST_POL ? 1 : 2) : 0; `ifdef SIMLIB_SPECIFY specify // DD=0 if (EN && DD==0 && SD==0 && ED==0 && !FULL) ( SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==0 && ED==0 && FULL) ( SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==1 && ED==0 && FULL) ( SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==2 && ED==0 && FULL) ( SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==0 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); // DD=1 if (EN && DD==1 && SD==0 && ED==0 && !FULL) ( SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==0 && ED==0 && FULL) ( SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==1 && ED==0 && FULL) ( SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==2 && ED==0 && FULL) ( SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==1 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); // DD=2 if (EN && DD==2 && SD==0 && ED==0 && !FULL) ( SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==0 && ED==0 && FULL) ( SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==1 && ED==0 && FULL) ( SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==2 && ED==0 && FULL) ( SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); if (EN && DD==2 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); endspecify `endif endmodule // -------------------------------------------------------- module \$specrule (EN_SRC, EN_DST, SRC, DST); parameter TYPE = ""; parameter T_LIMIT = 0; parameter T_LIMIT2 = 0; parameter SRC_WIDTH = 1; parameter DST_WIDTH = 1; parameter SRC_PEN = 0; parameter SRC_POL = 0; parameter DST_PEN = 0; parameter DST_POL = 0; input EN_SRC, EN_DST; input [SRC_WIDTH-1:0] SRC; input [DST_WIDTH-1:0] DST; `ifdef SIMLIB_SPECIFY specify // TBD endspecify `endif endmodule // -------------------------------------------------------- module \$assert (A, EN); input A, EN; `ifndef SIMLIB_NOCHECKS always @* begin if (A !== 1'b1 && EN === 1'b1) begin $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 `endif endmodule // -------------------------------------------------------- module \$live (A, EN); input A, EN; endmodule // -------------------------------------------------------- module \$fair (A, EN); input A, EN; endmodule // -------------------------------------------------------- module \$cover (A, EN); input A, EN; endmodule // -------------------------------------------------------- module \$initstate (Y); output reg Y = 1; reg [3:0] cnt = 1; reg trig = 0; initial trig <= 1; always @(cnt, trig) begin Y <= |cnt; cnt <= cnt + |cnt; end endmodule // -------------------------------------------------------- module \$anyconst (Y); parameter WIDTH = 0; output [WIDTH-1:0] Y; assign Y = 'bx; endmodule // -------------------------------------------------------- module \$anyseq (Y); parameter WIDTH = 0; output [WIDTH-1:0] Y; assign Y = 'bx; endmodule // -------------------------------------------------------- module \$allconst (Y); parameter WIDTH = 0; output [WIDTH-1:0] Y; assign Y = 'bx; endmodule // -------------------------------------------------------- module \$allseq (Y); parameter WIDTH = 0; output [WIDTH-1:0] Y; assign Y = 'bx; 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 // -------------------------------------------------------- `ifndef SIMLIB_NOSR module \$sr (SET, CLR, Q); parameter WIDTH = 0; parameter SET_POLARITY = 1'b1; parameter CLR_POLARITY = 1'b1; input [WIDTH-1:0] SET, CLR; output reg [WIDTH-1:0] Q; wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; genvar i; generate 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; else if (pos_set[i]) Q[i] <= 1; end endgenerate endmodule `endif // -------------------------------------------------------- `ifdef SIMLIB_FF module \$ff (D, Q); parameter WIDTH = 0; input [WIDTH-1:0] D; output reg [WIDTH-1:0] Q; always @($global_clk) begin Q <= D; end endmodule `endif // -------------------------------------------------------- module \$dff (CLK, D, Q); parameter WIDTH = 0; parameter CLK_POLARITY = 1'b1; input CLK; input [WIDTH-1:0] D; output reg [WIDTH-1:0] Q; wire pos_clk = CLK == CLK_POLARITY; always @(posedge pos_clk) begin Q <= D; 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); parameter WIDTH = 0; parameter CLK_POLARITY = 1'b1; parameter SET_POLARITY = 1'b1; parameter CLR_POLARITY = 1'b1; input CLK; input [WIDTH-1:0] SET, CLR, D; output reg [WIDTH-1:0] Q; wire pos_clk = CLK == CLK_POLARITY; wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; genvar i; generate 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; else if (pos_set[i]) Q[i] <= 1; else Q[i] <= D[i]; end endgenerate endmodule `endif // -------------------------------------------------------- module \$adff (CLK, ARST, D, Q); parameter WIDTH = 0; parameter CLK_POLARITY = 1'b1; parameter ARST_POLARITY = 1'b1; parameter ARST_VALUE = 0; input CLK, ARST; input [WIDTH-1:0] D; output reg [WIDTH-1:0] Q; wire pos_clk = CLK == CLK_POLARITY; wire pos_arst = ARST == ARST_POLARITY; always @(posedge pos_clk, posedge pos_arst) begin if (pos_arst) Q <= ARST_VALUE; else Q <= D; end endmodule // -------------------------------------------------------- module \$dlatch (EN, D, Q); parameter WIDTH = 0; parameter EN_POLARITY = 1'b1; input EN; input [WIDTH-1:0] D; output reg [WIDTH-1:0] Q; always @* begin if (EN == EN_POLARITY) Q = D; end endmodule // -------------------------------------------------------- `ifndef SIMLIB_NOSR module \$dlatchsr (EN, SET, CLR, D, Q); parameter WIDTH = 0; parameter EN_POLARITY = 1'b1; parameter SET_POLARITY = 1'b1; parameter CLR_POLARITY = 1'b1; input EN; input [WIDTH-1:0] SET, CLR, D; output reg [WIDTH-1:0] Q; wire pos_en = EN == EN_POLARITY; wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; genvar i; generate for (i = 0; i < WIDTH; i = i+1) begin:bitslices always @* if (pos_clr[i]) Q[i] = 0; else if (pos_set[i]) Q[i] = 1; else if (pos_en) Q[i] = D[i]; end endgenerate endmodule `endif // -------------------------------------------------------- module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); parameter NAME = ""; parameter CLK_POLARITY = 1'b1; parameter ARST_POLARITY = 1'b1; parameter CTRL_IN_WIDTH = 1; parameter CTRL_OUT_WIDTH = 1; parameter STATE_BITS = 1; parameter STATE_NUM = 1; parameter STATE_NUM_LOG2 = 1; parameter STATE_RST = 0; parameter STATE_TABLE = 1'b0; parameter TRANS_NUM = 1; parameter TRANS_TABLE = 4'b0x0x; input CLK, ARST; input [CTRL_IN_WIDTH-1:0] CTRL_IN; output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT; wire pos_clk = CLK == CLK_POLARITY; wire pos_arst = ARST == ARST_POLARITY; reg [STATE_BITS-1:0] state; reg [STATE_BITS-1:0] state_tmp; reg [STATE_BITS-1:0] next_state; reg [STATE_BITS-1:0] tr_state_in; reg [STATE_BITS-1:0] tr_state_out; reg [CTRL_IN_WIDTH-1:0] tr_ctrl_in; reg [CTRL_OUT_WIDTH-1:0] tr_ctrl_out; integer i; task tr_fetch; input [31:0] tr_num; reg [31:0] tr_pos; reg [STATE_NUM_LOG2-1:0] state_num; begin tr_pos = (2*STATE_NUM_LOG2+CTRL_IN_WIDTH+CTRL_OUT_WIDTH)*tr_num; tr_ctrl_out = TRANS_TABLE >> tr_pos; tr_pos = tr_pos + CTRL_OUT_WIDTH; state_num = TRANS_TABLE >> tr_pos; tr_state_out = STATE_TABLE >> (STATE_BITS*state_num); tr_pos = tr_pos + STATE_NUM_LOG2; tr_ctrl_in = TRANS_TABLE >> tr_pos; tr_pos = tr_pos + CTRL_IN_WIDTH; state_num = TRANS_TABLE >> tr_pos; tr_state_in = STATE_TABLE >> (STATE_BITS*state_num); tr_pos = tr_pos + STATE_NUM_LOG2; end endtask always @(posedge pos_clk, posedge pos_arst) begin if (pos_arst) begin state_tmp = STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; for (i = 0; i < STATE_BITS; i = i+1) if (state_tmp[i] === 1'bz) state_tmp[i] = 0; state <= state_tmp; end else begin state_tmp = next_state; for (i = 0; i < STATE_BITS; i = i+1) if (state_tmp[i] === 1'bz) state_tmp[i] = 0; state <= state_tmp; end end always @(state, CTRL_IN) begin next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; CTRL_OUT <= 'bx; // $display("---"); // $display("Q: %b %b", state, CTRL_IN); for (i = 0; i < TRANS_NUM; i = i+1) begin tr_fetch(i); // $display("T: %b %b -> %b %b [%d]", tr_state_in, tr_ctrl_in, tr_state_out, tr_ctrl_out, i); casez ({state, CTRL_IN}) {tr_state_in, tr_ctrl_in}: begin // $display("-> %b %b <- MATCH", state, CTRL_IN); {next_state, CTRL_OUT} <= {tr_state_out, tr_ctrl_out}; end endcase end end endmodule // -------------------------------------------------------- `ifndef SIMLIB_NOMEM module \$memrd (CLK, EN, ADDR, DATA); parameter MEMID = ""; parameter ABITS = 8; parameter WIDTH = 8; parameter CLK_ENABLE = 0; parameter CLK_POLARITY = 0; parameter TRANSPARENT = 0; input CLK, EN; input [ABITS-1:0] ADDR; output [WIDTH-1:0] DATA; initial begin if (MEMID != "") begin $display("ERROR: Found non-simulatable instance of $memrd!"); $finish; end end endmodule // -------------------------------------------------------- module \$memwr (CLK, EN, ADDR, DATA); parameter MEMID = ""; parameter ABITS = 8; parameter WIDTH = 8; parameter CLK_ENABLE = 0; parameter CLK_POLARITY = 0; parameter PRIORITY = 0; input CLK; input [WIDTH-1:0] EN; input [ABITS-1:0] ADDR; input [WIDTH-1:0] DATA; initial begin if (MEMID != "") begin $display("ERROR: Found non-simulatable instance of $memwr!"); $finish; end end endmodule // -------------------------------------------------------- module \$meminit (ADDR, DATA); parameter MEMID = ""; parameter ABITS = 8; parameter WIDTH = 8; parameter WORDS = 1; parameter PRIORITY = 0; input [ABITS-1:0] ADDR; input [WORDS*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_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 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; input [WR_PORTS-1:0] WR_CLK; 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] memory [SIZE-1:0]; 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 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] && 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]) 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])) 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; LAST_WR_CLK <= WR_CLK; end endmodule `endif // --------------------------------------------------------