Skip to content

Instantly share code, notes, and snippets.

@cfelton
Last active October 20, 2016 23:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cfelton/cc7e9cbabfa5c3d3435f to your computer and use it in GitHub Desktop.
Save cfelton/cc7e9cbabfa5c3d3435f to your computer and use it in GitHub Desktop.
MemTest VHDL to Verilog conversion example.
--**********************************************************************
-- Copyright (c) 1997-2014 by XESS Corp <http://www.xess.com>.
-- All rights reserved.
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 3.0 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library. If not, see
-- <http://www.gnu.org/licenses/>.
--**********************************************************************
--------------------------------------------------------------------
-- Memory-testing routine
--------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
--package MemTestPckg is
--
-- component MemTest is
-- generic(
-- PIPE_EN_G : boolean := false; -- enable pipelined operations
-- DATA_WIDTH_G : natural := 16; -- memory data width
-- ADDR_WIDTH_G : natural := 23; -- memory address width
-- BEG_TEST_G : natural := 16#00_0000#; -- beginning test range address
-- END_TEST_G : natural := 16#7F_FFFF# -- ending test range address
-- );
-- port(
-- clk_i : in std_logic; -- master clock input
-- rst_i : in std_logic; -- reset
-- doAgain_i : in std_logic; -- re-do memory test
-- begun_i : in std_logic; -- memory operation begun_i indicator
-- done_i : in std_logic; -- memory operation done_i indicator
-- dIn_i : in std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data from memory
-- rdPending_i : in std_logic; -- read operations in progress_o indicator
-- rd_o : out std_logic; -- memory read control signal
-- wr_o : out std_logic; -- memory write control signal
-- addr_o : out std_logic_vector(ADDR_WIDTH_G-1 downto 0); -- address to memory
-- dOut_o : out std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data to memory
-- progress_o : out std_logic_vector(1 downto 0); -- memory test progress_o indicator
-- err_o : out std_logic -- memory error flag
-- );
-- end component;
--
--end package;
library IEEE, XESS;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use XESS.CommonPckg.all;
use XESS.RandPckg.all;
entity MemTest is
generic(
PIPE_EN_G : boolean := false; -- enable pipelined operations
DATA_WIDTH_G : natural := 16; -- memory data width
ADDR_WIDTH_G : natural := 23 -- memory address width
--BEG_TEST_G : natural := 16#00_0000#; -- beginning test range address
--END_TEST_G : natural := 16#7F_FFFF# -- ending test range address
);
port(
clk_i : in std_logic; -- master clock input
rst_i : in std_logic; -- reset
doAgain_i : in std_logic; -- re-do memory test
begun_i : in std_logic; -- memory operation begun_i indicator
done_i : in std_logic; -- memory operation done_i indicator
dIn_i : in std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data from memory
rdPending_i : in std_logic; -- read operations in progress_o indicator
rd_o : out std_logic; -- memory read control signal
wr_o : out std_logic; -- memory write control signal
addr_o : out std_logic_vector(ADDR_WIDTH_G-1 downto 0); -- address to memory
dOut_o : out std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data to memory
progress_o : out std_logic_vector(1 downto 0); -- memory test progress_o indicator
err_o : out std_logic -- memory error flag
);
end entity;
architecture arch of MemTest is
-- states of the memory tester state machine
type testState is (
INIT, -- init
LOAD, -- load memory with pseudo-random data
COMPARE, -- compare memory contents with pseudo-random data
EMPTY_PIPE, -- empty read pipeline
STOP -- stop and indicate memory status
);
signal state_r, state_x : testState := INIT; -- state register and next state
-- registers
signal addr_r, addr_x : unsigned(addr_o'range); -- address register
signal err_r, err_x : std_logic := NO; -- error flag
-- internal signals
signal ld : std_logic; -- load random number gen with seed value
signal cke : std_logic; -- clock-enable for random number gen
signal rand, rand1 : std_logic_vector(dOut_o'range); -- random number from generator
signal seed : std_logic_vector(dIn_i'range); -- random number starting seed
begin
seed <= (others => '1'); -- random number seed is 111...111
-- random number generator module
u0 : randGen
port map(
clk_i => clk_i, -- input clock
cke_i => cke, -- clock-enable to control when new random num is computed
ld_i => ld, -- load seed control signal
seed_i => seed, -- random number seed
rand_o => rand1 -- random number output from generator
);
rand <= rand1;
-- rand <= (others=>'0');
-- rand <= std_logic_vector(addr_r(15 downto 0));
-- rand <= std_logic_vector(TO_UNSIGNED(17,16));
-- connect internal registers to external busses
-- memory address bus driven by memory address register
addr_o <= std_logic_vector(addr_r); -- linear memory addressing
-- addr_o <= std_logic_vector(addr_r(1 downto 0) & addr_r(addr_o'high downto 2)); -- linear addressing simultaneously through each bank
dOut_o <= rand; -- always output the current random number to the memory
err_o <= err_r; -- output the current memory error status
-- memory test controller state machine operations
combinatorial : process(state_r, err_r, addr_r, dIn_i, rand, begun_i, done_i, rdPending_i, doAgain_i)
begin
-- default operations (do nothing unless explicitly stated in the following case statement)
rd_o <= NO; -- no memory write
wr_o <= NO; -- no memory read
ld <= NO; -- don't load the random number generator
cke <= NO; -- don't generate a new random number
addr_x <= addr_r; -- next address is the same as current address
err_x <= err_r; -- error flag is unchanged
state_x <= state_r; -- no change in memory tester state
-- **** compute the next state and operations ****
case state_r is
------------------------------------------------------
-- initialize the memory test controller
------------------------------------------------------
when INIT =>
ld <= YES; -- load random number seed
cke <= YES; -- enable clocking of rand num gen so seed gets loaded
-- @todo: attributes don't convert
--addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
addr_x <= to_unsigned(BEG_TEST_G, 23);
err_x <= NO; -- clear memory error flag
state_x <= LOAD; -- next go to LOAD state and write pattern to memory
progress_o <= "00"; -- indicate the current controller state
when LOAD => -- load the memory with data from the random number generator
progress_o <= "01"; -- indicate the current controller state
if PIPE_EN_G = 1 then
wr_o <= YES;
if begun_i = YES then
if addr_r /= END_TEST_G then
addr_x <= addr_r + 1; -- so increment address
cke <= YES; -- and enable generator clock to get new random num
else
cke <= YES; -- enable generator clock and
ld <= YES; -- reload the generator with the seed value
-- @todo: attributes not supported
--addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- reset to start of test range
addr_x <= TO_UNSIGNED(BEG_TEST_G, 23); -- reset to start of test range
state_x <= COMPARE;
end if;
end if;
else
if done_i = NO then
wr_o <= YES;
elsif addr_r /= END_TEST_G then
addr_x <= addr_r + 1; -- so increment address
cke <= YES; -- and enable generator clock to get new random num
else
cke <= YES; -- enable generator clock and
ld <= YES; -- reload the generator with the seed value
--addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- reset to start of test range
addr_x <= TO_UNSIGNED(BEG_TEST_G, 23); -- reset to start of test range
state_x <= COMPARE;
end if;
end if;
when COMPARE => -- re-run the generator and compare it to memory contents
progress_o <= "10"; -- indicate the current controller state
if PIPE_EN_G = 1 then
rd_o <= YES;
if begun_i = YES then
addr_x <= addr_r + 1; -- increment address to check next memory location
end if;
if addr_r = END_TEST_G then
state_x <= EMPTY_PIPE;
end if;
if done_i = YES then
if dIn_i /= rand then -- compare value from memory to random number
err_x <= YES; -- error if they don't match
end if;
cke <= YES; -- enable generator clock to get next random num
end if;
else
if done_i = NO then -- current read operation is not complete
rd_o <= YES; -- keep read signal active since memory read is not done_i
else -- current read operation is complete
if dIn_i /= rand then -- compare value from memory to random number
err_x <= YES; -- error if they don't match
end if;
if addr_r = END_TEST_G then
state_x <= STOP; -- go to STOP state once entire range has been checked
else
addr_x <= addr_r + 1; -- increment address to check next memory location
end if;
cke <= YES; -- and enable generator clock to get next random num
end if;
end if;
when EMPTY_PIPE =>
progress_o <= "10"; -- indicate the current controller state
if done_i = YES then
if dIn_i /= rand then -- compare value from memory to random number
err_x <= YES; -- error if they don't match
end if;
cke <= YES; -- enable generator clock to get next random num
end if;
if rdPending_i = NO then
state_x <= STOP;
--addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
addr_x <= TO_UNSIGNED(BEG_TEST_G, 23); -- load starting mem address
end if;
when others => -- memory test is complete
progress_o <= "11"; -- indicate the current controller state
if doAgain_i = YES then
ld <= YES; -- load random number seed
cke <= YES; -- enable clocking of rand num gen so seed gets loaded
--addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
addr_x <= TO_UNSIGNED(BEG_TEST_G, 23); -- load starting mem address
err_x <= NO; -- clear memory error flag
state_x <= INIT; -- go to the INIT state and and re-do memory test
end if;
end case;
end process;
-- update the registers of the memory tester controller
update : process(rst_i, clk_i)
begin
if rst_i = YES then
-- go to starting state and clear error flag when reset occurs
state_r <= INIT;
elsif rising_edge(clk_i) then
-- update error flag, address register, and state
err_r <= err_x;
addr_r <= addr_x;
state_r <= state_x;
end if;
end process;
end architecture;
// File MemTest.vhd translated with vhd2vl v2.4 VHDL to Verilog RTL translator
// vhd2vl settings:
// * Verilog Module Declaration Style: 2001
// vhd2vl is Free (libre) Software:
// Copyright (C) 2001 Vincenzo Liguori - Ocean Logic Pty Ltd
// http://www.ocean-logic.com
// Modifications Copyright (C) 2006 Mark Gonzales - PMC Sierra Inc
// Modifications (C) 2010 Shankar Giri
// Modifications Copyright (C) 2002, 2005, 2008-2010 Larry Doolittle - LBNL
// http://doolittle.icarus.com/~larry/vhd2vl/
//
// vhd2vl comes with ABSOLUTELY NO WARRANTY. Always check the resulting
// Verilog for correctness, ideally with a formal verification tool.
//
// You are welcome to redistribute vhd2vl under certain conditions.
// See the license (GPLv2) file included with the source for details.
// The result of translation follows. Its copyright status should be
// considered unchanged from the original VHDL.
//**********************************************************************
// Copyright (c) 1997-2014 by XESS Corp <http://www.xess.com>.
// All rights reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3.0 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library. If not, see
// <http://www.gnu.org/licenses/>.
//**********************************************************************
//------------------------------------------------------------------
// Memory-testing routine
//------------------------------------------------------------------
//package MemTestPckg is
//
// component MemTest is
// generic(
// PIPE_EN_G : boolean := false; -- enable pipelined operations
// DATA_WIDTH_G : natural := 16; -- memory data width
// ADDR_WIDTH_G : natural := 23; -- memory address width
// BEG_TEST_G : natural := 16#00_0000#; -- beginning test range address
// END_TEST_G : natural := 16#7F_FFFF# -- ending test range address
// );
// port(
// clk_i : in std_logic; -- master clock input
// rst_i : in std_logic; -- reset
// doAgain_i : in std_logic; -- re-do memory test
// begun_i : in std_logic; -- memory operation begun_i indicator
// done_i : in std_logic; -- memory operation done_i indicator
// dIn_i : in std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data from memory
// rdPending_i : in std_logic; -- read operations in progress_o indicator
// rd_o : out std_logic; -- memory read control signal
// wr_o : out std_logic; -- memory write control signal
// addr_o : out std_logic_vector(ADDR_WIDTH_G-1 downto 0); -- address to memory
// dOut_o : out std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data to memory
// progress_o : out std_logic_vector(1 downto 0); -- memory test progress_o indicator
// err_o : out std_logic -- memory error flag
// );
// end component;
//
//end package;
// no timescale needed
module MemTest
(
input wire clk_i,
input wire rst_i,
input wire doAgain_i,
input wire begun_i,
input wire done_i,
input wire [DATA_WIDTH_G - 1:0] dIn_i,
input wire rdPending_i,
output reg rd_o,
output reg wr_o,
output wire [ADDR_WIDTH_G - 1:0] addr_o,
output wire [DATA_WIDTH_G - 1:0] dOut_o,
output reg [1:0] progress_o,
output wire err_o
);
parameter PIPE_EN_G=false;
parameter [31:0] DATA_WIDTH_G=16;
parameter [31:0] ADDR_WIDTH_G=23;
parameter BEG_TEST_G = 16'h00_0000;
parameter END_TEST_G = 16'h7F_FFFF;
// memory address width
// master clock input
// reset
// re-do memory test
// memory operation begun_i indicator
// memory operation done_i indicator
// data from memory
// read operations in progress_o indicator
// memory read control signal
// memory write control signal
// address to memory
// data to memory
// memory test progress_o indicator
// memory error flag
// states of the memory tester state machine
parameter [2:0]
INIT = 0,
LOAD = 1,
COMPARE = 2,
EMPTY_PIPE = 3,
STOP = 4;
reg [2:0] state_r = INIT; reg [2:0] state_x = INIT; // state register and next state
// registers
reg [ADDR_WIDTH_G - 1:0] addr_r; reg [ADDR_WIDTH_G - 1:0] addr_x; // address register
reg err_r = NO; reg err_x = NO; // error flag
// internal signals
reg ld; // load random number gen with seed value
reg cke; // clock-enable for random number gen
wire [DATA_WIDTH_G - 1:0] rand; wire [DATA_WIDTH_G - 1:0] rand1; // random number from generator
wire [DATA_WIDTH_G - 1:0] seed; // random number starting seed
assign seed = {(((DATA_WIDTH_G - 1))-((0))+1){1'b1}};
// random number seed is 111...111
// random number generator module
randGen u0(
.clk_i(clk_i),
// input clock
.cke_i(cke),
// clock-enable to control when new random num is computed
.ld_i(ld),
// load seed control signal
.seed_i(seed),
// random number seed
.rand_o(rand1));
assign rand = rand1;
// rand <= (others=>'0');
// rand <= std_logic_vector(addr_r(15 downto 0));
// rand <= std_logic_vector(TO_UNSIGNED(17,16));
// connect internal registers to external busses
// memory address bus driven by memory address register
assign addr_o = (addr_r);
// linear memory addressing
// addr_o <= std_logic_vector(addr_r(1 downto 0) & addr_r(addr_o'high downto 2)); -- linear addressing simultaneously through each bank
assign dOut_o = rand;
// always output the current random number to the memory
assign err_o = err_r;
// output the current memory error status
// memory test controller state machine operations
always @(state_r or err_r or addr_r or dIn_i or rand or begun_i or done_i or rdPending_i or doAgain_i) begin
// default operations (do nothing unless explicitly stated in the following case statement)
rd_o <= NO;
// no memory write
wr_o <= NO;
// no memory read
ld <= NO;
// don't load the random number generator
cke <= NO;
// don't generate a new random number
addr_x <= addr_r;
// next address is the same as current address
err_x <= err_r;
// error flag is unchanged
state_x <= state_r;
// no change in memory tester state
// **** compute the next state and operations ****
case(state_r)
//----------------------------------------------------
// initialize the memory test controller
//----------------------------------------------------
INIT : begin
ld <= YES;
// load random number seed
cke <= YES;
// enable clocking of rand num gen so seed gets loaded
// @todo: attributes don't convert
//addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
addr_x <= (BEG_TEST_G);
err_x <= NO;
// clear memory error flag
state_x <= LOAD;
// next go to LOAD state and write pattern to memory
progress_o <= 2'b 00;
// indicate the current controller state
end
LOAD : begin
// load the memory with data from the random number generator
progress_o <= 2'b 01;
// indicate the current controller state
if(PIPE_EN_G == 1) begin
wr_o <= YES;
if(begun_i == YES) begin
if(addr_r != END_TEST_G) begin
addr_x <= addr_r + 1;
// so increment address
cke <= YES;
// and enable generator clock to get new random num
end
else begin
cke <= YES;
// enable generator clock and
ld <= YES;
// reload the generator with the seed value
// @todo: attributes not supported
//addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- reset to start of test range
addr_x <= (BEG_TEST_G);
// reset to start of test range
state_x <= COMPARE;
end
end
end
else begin
if(done_i == NO) begin
wr_o <= YES;
end
else if(addr_r != END_TEST_G) begin
addr_x <= addr_r + 1;
// so increment address
cke <= YES;
// and enable generator clock to get new random num
end
else begin
cke <= YES;
// enable generator clock and
ld <= YES;
// reload the generator with the seed value
//addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- reset to start of test range
addr_x <= (BEG_TEST_G);
// reset to start of test range
state_x <= COMPARE;
end
end
end
COMPARE : begin
// re-run the generator and compare it to memory contents
progress_o <= 2'b 10;
// indicate the current controller state
if(PIPE_EN_G == 1) begin
rd_o <= YES;
if(begun_i == YES) begin
addr_x <= addr_r + 1;
// increment address to check next memory location
end
if(addr_r == END_TEST_G) begin
state_x <= EMPTY_PIPE;
end
if(done_i == YES) begin
if(dIn_i != rand) begin
// compare value from memory to random number
err_x <= YES;
// error if they don't match
end
cke <= YES;
// enable generator clock to get next random num
end
end
else begin
if(done_i == NO) begin
// current read operation is not complete
rd_o <= YES;
// keep read signal active since memory read is not done_i
end
else begin
// current read operation is complete
if(dIn_i != rand) begin
// compare value from memory to random number
err_x <= YES;
// error if they don't match
end
if(addr_r == END_TEST_G) begin
state_x <= STOP;
// go to STOP state once entire range has been checked
end
else begin
addr_x <= addr_r + 1;
// increment address to check next memory location
end
cke <= YES;
// and enable generator clock to get next random num
end
end
end
EMPTY_PIPE : begin
progress_o <= 2'b 10;
// indicate the current controller state
if(done_i == YES) begin
if(dIn_i != rand) begin
// compare value from memory to random number
err_x <= YES;
// error if they don't match
end
cke <= YES;
// enable generator clock to get next random num
end
if(rdPending_i == NO) begin
state_x <= STOP;
//addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
addr_x <= (BEG_TEST_G);
// load starting mem address
end
end
default : begin
// memory test is complete
progress_o <= 2'b 11;
// indicate the current controller state
if(doAgain_i == YES) begin
ld <= YES;
// load random number seed
cke <= YES;
// enable clocking of rand num gen so seed gets loaded
//addr_x <= TO_UNSIGNED(BEG_TEST_G, addr_x'length); -- load starting mem address
addr_x <= (BEG_TEST_G);
// load starting mem address
err_x <= NO;
// clear memory error flag
state_x <= INIT;
// go to the INIT state and and re-do memory test
end
end
endcase
end
// update the registers of the memory tester controller
always @(posedge rst_i or posedge clk_i) begin
if(rst_i == YES) begin
// go to starting state and clear error flag when reset occurs
state_r <= INIT;
end else begin
// update error flag, address register, and state
err_r <= err_x;
addr_r <= addr_x;
state_r <= state_x;
end
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment