Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add synchronous RAM macros to support runtime-updatable functions #10

Merged
merged 4 commits into from
Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from setuptools import setup, find_packages

name = 'svreal'
version = '0.2.2'
version = '0.2.4'

DESCRIPTION = '''\
Library for working with fixed-point numbers in SystemVerilog\
Expand Down
66 changes: 66 additions & 0 deletions svreal/svreal.sv
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,29 @@ endfunction
`REAL_FROM_WIDTH_EXP(out_name, data_bits_expr, data_expt_expr); \
`SYNC_ROM_INTO_REAL(addr_name, out_name, clk_name, ce_name, addr_bits_expr, data_bits_expr, file_path_expr, data_expt_expr)

// synchronous RAM

`define SYNC_RAM_INTO_REAL(addr_name, din_name, out_name, clk_name, ce_name, we_name, addr_bits_expr, data_bits_expr, data_expt_expr) \
sync_ram_real #( \
`PASS_REAL(out, out_name), \
.addr_bits(addr_bits_expr), \
.data_bits(data_bits_expr), \
.data_expt(data_expt_expr) \
) sync_ram_real_``out_name``_i ( \
.addr(addr_name), \
.din(din_name), \
.out(out_name), \
.clk(clk_name), \
.ce(ce_name), \
.we(we_name) \
)

`define SYNC_RAM_REAL(addr_name, din_name, out_name, clk_name, ce_name, we_name, addr_bits_expr, data_bits_expr, data_expt_expr) \
`REAL_FROM_WIDTH_EXP(out_name, data_bits_expr, data_expt_expr); \
`SYNC_RAM_INTO_REAL(addr_name, din_name, out_name, clk_name, ce_name, we_name, addr_bits_expr, data_bits_expr, data_expt_expr)

// synchronous RAM

// interface functions

// range is not included as a parameter since there is no
Expand Down Expand Up @@ -876,4 +899,47 @@ module sync_rom_real #(
`endif
endmodule

// adapted from the example on page 119-120 here:
// https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_2/ug901-vivado-synthesis.pdf

module sync_ram_real #(
`DECL_REAL(out),
parameter integer addr_bits=1,
parameter integer data_bits=1,
parameter integer data_expt=1
) (
input wire logic [(addr_bits-1):0] addr,
input wire logic signed [(data_bits-1):0] din,
`OUTPUT_REAL(out),
input wire logic clk,
input wire logic ce,
input wire logic we
);
// memory contents
logic signed [(data_bits-1):0] ram [0:((2**addr_bits)-1)];

// RAM I/O
logic signed [(data_bits-1):0] data;
always @(posedge clk) begin
if (ce) begin
if (we) begin
ram[addr] <= din;
end
data <= ram[addr];
end
end

// Assign to output. We have to explicitly handle FLOAT_REAL case
// because ROM data is always stored with fixed-point formatting,
// even when FLOAT_REAL is defined.
`ifdef FLOAT_REAL
assign out = `FIXED_TO_FLOAT(data, data_expt);
`else
localparam `RANGE_PARAM_REAL(data) = 2.0**(data_bits+data_expt-1);
localparam `WIDTH_PARAM_REAL(data) = data_bits;
localparam `EXPONENT_PARAM_REAL(data) = data_expt;
`ASSIGN_REAL(data, out);
`endif
endmodule

`endif // `ifndef __SVREAL_SV__
66 changes: 66 additions & 0 deletions tests/test_sync_ram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# AHA imports
import magma as m
import fault

# svreal imports
from .common import pytest_sim_params, get_file
from svreal import get_svreal_header

def pytest_generate_tests(metafunc):
pytest_sim_params(metafunc)
metafunc.parametrize('defines', [{}, {'FLOAT_REAL': None}])

def test_sync_ram(simulator, defines, width=18, exponent=-12):
# declare circuit
class dut(m.Circuit):
name = 'test_sync_ram'
io = m.IO(
addr=m.In(m.Bits[2]),
din=m.In(m.Bits[width]),
out=fault.RealOut,
clk=m.ClockIn,
ce=m.BitIn,
we=m.BitIn,
)

# define the test
t = fault.Tester(dut, dut.clk)

# initialize
t.zero_inputs()
t.poke(dut.ce, 1)
t.step(2)

# write data

write_order = [1, 0, 3, 2]
write_data = [1.23, -2.34, 3.45, -4.56]

t.poke(dut.we, 1)
for addr in write_order:
t.poke(dut.addr, addr)
t.poke(dut.din, int(round(write_data[addr]*(2**(-exponent)))))
t.step(2)

# read data

read_order = [0, 3, 2, 1]

t.poke(dut.we, 0)
for addr in read_order:
t.poke(dut.addr, addr)
t.step(2)
t.expect(dut.out, write_data[addr], abs_tol=0.001)

# update defines
defines.update(dict(WIDTH=width, EXPONENT=exponent))

# run the test
t.compile_and_run(
target='system-verilog',
simulator=simulator,
ext_srcs=[get_file('test_sync_ram.sv')],
inc_dirs=[get_svreal_header().parent],
defines=defines,
ext_model_file=True
)
18 changes: 18 additions & 0 deletions tests/test_sync_ram.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
`timescale 1ns / 1ps

`include "svreal.sv"

module test_sync_ram (
input [1:0] addr,
input signed [((`WIDTH)-1):0] din,
output real out,
input clk,
input ce,
input we
);
// instantiate the RAM
`SYNC_RAM_REAL(addr, din, out_int, clk, ce, we, 2, `WIDTH, `EXPONENT);

// wire up the RAM output
assign out = `TO_REAL(out_int);
endmodule