Commit e3d4ca75 authored by twlostow's avatar twlostow

initial FIFO register support (doesn't work yet)

git-svn-id: http://svn.ohwr.org/wishbone-gen@11 4537843c-45c2-4d80-8546-c3283569414f
parent a9a2dcce
......@@ -250,6 +250,10 @@ function cgen_build_siglist()
siglist = tree_2_table("signals");
table_join(siglist, global_signals);
for i,v in pairs(siglist) do
print("SIGNAL: ", v.name);
end
return siglist;
end
......
......@@ -197,11 +197,15 @@ function cgen_doc_hdl_symbol()
end
end
foreach_subfield(reg, function(field, reg)
for i,v in pairs(field.ports) do
table.insert(ports ,v);
end
end);
foreach_subfield(reg,
function(field, reg)
if(field.ports ~= nil) then
for i,v in pairs(field.ports) do
table.insert(ports ,v);
end
end
end);
end
end);
......@@ -295,6 +299,7 @@ function cgen_doc_header_and_toc()
emit('<h1 class="heading">'..periph.hdl_entity..'</h1>');
emit('<h3>'..periph.name..'</h3>');
local t = periph.description;
if(t == nil) then t = ""; end
emit('<p>'..string.gsub(t, "\n", "<br>")..'</p>');
emit('<h3>Contents:</h3>');
......@@ -325,7 +330,7 @@ function cgen_doc_memmap()
row[4].text = "VHDL/Verilog prefix";
row[5].text = "C prefix";
foreach_reg({TYPE_REG, TYPE_FIFO}, function(reg)
foreach_reg({TYPE_REG}, function(reg)
if(reg.full_hdl_prefix ~= nil) then
htable_add_row(tbl, n);
local row = tbl.data[n]; n=n+1;
......@@ -605,7 +610,7 @@ function cgen_generate_documentation()
cgen_new_snippet();
emit(hsection(3,0, "Register description"));
foreach_reg({TYPE_REG, TYPE_FIFO}, function(reg) if(reg.no_docu == nil or reg.no_docu == false)then cgen_doc_reg(reg);end end);
foreach_reg({TYPE_REG}, function(reg) if(reg.no_docu == nil or reg.no_docu == false)then cgen_doc_reg(reg);end end);
local h_regs = cgen_get_snippet();
......
......@@ -435,7 +435,7 @@ function cgen_generate_vhdl_code(tree)
else
-- or emit the value/signal
emitx(gen_subrange(tsa));
end
end
end
......@@ -473,7 +473,7 @@ function cgen_generate_vhdl_code(tree)
--
function cgen_vhdl_comment(node)
-- print("COMMENT: "..node.str);
print("COMMENT: "..node.str);
emitx("-- "..node.str.."\n");
end
......@@ -608,7 +608,7 @@ function cgen_generate_vhdl_code(tree)
["openpin"] = cgen_vhdl_openpin;
};
-- print(node);
-- print(node);
for i,v in pairs(node) do
-- no type? probably just a block of code. recurse it deeper.
......@@ -617,7 +617,7 @@ function cgen_generate_vhdl_code(tree)
recurse(v);
else
local func = generators[v.t];
-- print(v.t);
-- print(v.t);
if(func == nil) then
die("Unimplemented generator: "..v.t);
end
......
......@@ -773,10 +773,10 @@ Project_Version = 6
Project_DefaultLib = work
Project_SortMethod = unused
Project_Files_Count = 2
Project_File_0 = /home/slayer/wbgen2_svn/wbgen2/examples/RAMs/testbench.v
Project_File_P_0 = cover_toggle 0 vlog_protect 0 file_type verilog group_id 0 cover_exttoggle 0 cover_cond 0 vlog_nodebug 0 vlog_1995compat 0 cover_branch 0 vlog_noload 0 folder {Top Level} last_compile 0 cover_fsm 0 vlog_enable0In 0 vlog_disableopt 0 vlog_vopt 1 vlog_hazard 0 vlog_showsource 0 ood 1 vlog_0InOptions {} vlog_options {} compile_to work vlog_upper 0 compile_order 0 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_1 = /home/slayer/wbgen2_svn/wbgen2/examples/RAMs/output/wb_slave_test_rams.vhdl
Project_File_P_1 = vhdl_novitalcheck 0 file_type vhdl group_id 0 vhdl_nodebug 0 vhdl_1164 1 vhdl_noload 0 vhdl_synth 0 vhdl_enable0In 0 folder {Top Level} last_compile 0 vhdl_disableopt 0 vhdl_vital 0 vhdl_vopt 1 vhdl_warn1 1 vhdl_explicit 1 vhdl_warn2 1 vhdl_showsource 0 vhdl_warn3 1 vhdl_0InOptions {} vhdl_warn4 1 vhdl_options {} vhdl_warn5 1 ood 1 compile_to work compile_order 1 cover_nosub 0 dont_compile 0 vhdl_use93 2002
Project_File_0 = /home/slayer/wbgen2_svn_new/wishbone-gen/examples/RAMs/run.do
Project_File_P_0 = compile_order -1 last_compile 0 folder {Top Level} dont_compile 1 group_id 0 file_type tcl ood 1
Project_File_1 = /home/slayer/wbgen2_svn_new/wishbone-gen/examples/RAMs/testbench.v
Project_File_P_1 = cover_toggle 0 vlog_protect 0 file_type verilog group_id 0 cover_exttoggle 0 cover_cond 0 vlog_nodebug 0 vlog_1995compat 0 vlog_noload 0 folder {Top Level} last_compile 0 cover_fsm 0 cover_branch 0 vlog_enable0In 0 vlog_disableopt 0 vlog_vopt 1 vlog_showsource 0 vlog_hazard 0 vlog_0InOptions {} ood 1 vlog_upper 0 compile_to work vlog_options {} compile_order 0 cover_expr 0 dont_compile 0 cover_stmt 0
Project_Sim_Count = 0
Project_Folder_Count = 0
Echo_Compile_Output = 0
......@@ -806,6 +806,6 @@ XML_DoubleClick = Edit
XML_CustomDoubleClick =
LOGFILE_DoubleClick = Edit
LOGFILE_CustomDoubleClick =
EditorState = {tabbed horizontal 1} {/home/slayer/wbgen2_svn/wbgen2/examples/interrupts/run.do 0 0} {/home/slayer/wbgen2_svn/wbgen2/examples/RAMs/testbench.v 0 1}
EditorState = {tabbed horizontal 1} {/home/slayer/wbgen2_svn_new/wishbone-gen/examples/RAMs/run.do 0 0}
Project_Major_Version = 6
Project_Minor_Version = 2
......@@ -5,7 +5,7 @@ set lang "vhdl"
set library_files {
"../../lib/wbgen2_pkg.vhd"
"../../lib/altera/wbgen2_dpssram.vhd"
"../../lib/wbgen2_dpssram.vhd"
};
mkdir -p output
......
......@@ -227,6 +227,12 @@ module main;
fail =1;
end
if(fail)
$display("TESTS FAILED");
else
$display("TESTS PASSED");
end
/*
......@@ -247,10 +253,6 @@ module main;
end
if(fail)
$display("TESTS FAILED");
else
$display("TESTS PASSED");
end
-----/\----- EXCLUDED -----/\----- */
......
peripheral {
name ="FIFO test";
prefix="fifotest";
hdl_entity="fifotest";
fifo_reg {
size = 256;
direction = BUS_TO_CORE;
prefix = "fifo1";
name = "fifo1";
flags_bus = {FIFO_FULL, FIFO_EMPTY, FIFO_COUNT};
flags_dev = {FIFO_FULL, FIFO_EMPTY, FIFO_COUNT};
field {
name = "ts value R";
prefix = "ts_r";
type = SLV;
size = 28;
};
field {
name = "ts value F";
prefix = "ts_f";
type = SLV;
size = 4;
};
field {
name ="port id";
prefix = "pid";
type = SLV;
size = 5;
align= 16;
};
field {
name = "frame id value";
prefix = "fid";
type = SLV;
size = 16;
align = 16;
};
};
};
\ No newline at end of file
......@@ -185,7 +185,7 @@ begin -- syn
wren_a => wr_a_i,
wren_b => wr_b_i,
clock0 => clk_a_i,
-- clock1 => clk_b_i,
clock1 => '0',
byteena_a => bwsel_int_a,
byteena_b => bwsel_int_b,
address_a => addr_a_i,
......
......@@ -29,6 +29,27 @@ package wbgen2_pkg is
wr_a_i : in std_logic;
wr_b_i : in std_logic);
end component;
component wbgen2_fifo_async
generic (
g_size : integer;
g_width : integer;
g_usedw_size : integer);
port (
rd_clk_i : in std_logic;
rd_req_i : in std_logic;
rd_data_o : out std_logic_vector(g_width-1 downto 0);
rd_empty_o : out std_logic;
rd_full_o : out std_logic;
rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0);
wr_clk_i : in std_logic;
wr_req_i : in std_logic;
wr_data_i : in std_logic_vector(g_width-1 downto 0);
wr_empty_o : out std_logic;
wr_full_o : out std_logic;
wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0));
end component;
component wbgen2_eic
generic (
g_num_interrupts : natural;
......
......@@ -16,6 +16,7 @@ Main "cgen_doc.lua"
Main "wbgen_regbank.lua"
Main "wbgen_rams.lua"
Main "wbgen_eic.lua"
Main "wbgen_fifos.lua"
Main "target_wishbone.lua"
Main "wbgen_main.lua"
-- -*- Mode: LUA; tab-width: 2 -*-
MAX_ACK_LENGTH = 10;
......
......@@ -20,11 +20,14 @@ ALL_REG_TYPES = {TYPE_REG, TYPE_RAM, TYPE_FIFO, TYPE_IRQ};
-- FIFO register flags
FIFO_FULL = 0x1;
FIFO_EMPTY = 0x2;
FIFO_ALMOST_FULL = 0x4;
FIFO_ALMOST_EMPTY = 0x8;
FIFO_CLEAR = 0x10;
FIFO_COUNT = 0x20;
-- FIFO directions
BUS_TO_CORE = 1;
CORE_TO_BUS = 2;
-- field access flags
READ_ONLY = 0x1;
READ_WRITE = 0x2;
......@@ -188,11 +191,15 @@ function calc_field_offset(field, reg)
-- align the field offset next to the current offset in the reg
local ofs = reg.current_offset;
ofs = align(field, ofs);
ofs = align(field, ofs);
-- update the current offset
reg.current_offset = ofs + field.size;
field.offset = ofs;
field.offset_unaligned = reg.current_offset_unaligned;
reg.current_offset_unaligned = reg.current_offset_unaligned + field.size;
-- calculate the number of fields in the register
if(reg.num_fields == nil) then reg.num_fields = 0; end
......@@ -218,6 +225,11 @@ function match(var, values)
if(var==v) then return true; end
end
return false;
end
function inset(var, set)
for i,v in ipairs(set) do if(var == v) then return true; end end
return false;
end
-- simulates C statement: a = cond ? x : y -> a = csel(cond, x, y);
......@@ -319,10 +331,10 @@ function calc_address_sizes(reg)
all_regs_size = align(reg, all_regs_size) + 1;
-- for FIFOS:
-- size of all FIFO fields (rounded up to multiple of 32 bits) + 1 extra FIFO control register
elseif (reg.__type == TYPE_FIFO) then
fifo_size = math.floor((reg.total_size + DATA_BUS_WIDTH - 1) / DATA_BUS_WIDTH) + 1;
all_regs_size = all_regs_size + fifo_size;
reg.num_fifo_regs = fifo_size;
-- elseif (reg.__type == TYPE_FIFO) then
-- fifo_size = math.floor((reg.total_size + DATA_BUS_WIDTH - 1) / DATA_BUS_WIDTH) + 1;
-- all_regs_size = all_regs_size + fifo_size;
-- reg.num_fifo_regs = fifo_size;
-- for RAMs:
elseif (reg.__type == TYPE_RAM) then
if(not is_power_of_2(reg.size)) then die ("RAM '"..reg.name.."': memory size must be a power of 2"); end
......@@ -368,9 +380,9 @@ function assign_addresses()
if(reg.__type==TYPE_REG) then
reg.base = align(reg, i);
i=reg.base+1;
elseif(reg.__type == TYPE_FIFO) then
reg.base = i;
i=i+reg.num_fifo_regs;
-- elseif(reg.__type == TYPE_FIFO) then
-- reg.base = i;
-- i=i+reg.num_fifo_regs;
end
end );
......@@ -391,9 +403,9 @@ function table_join(table_out, table_in)
local i,v;
if(table_in == nil) then return; end
for i,v in pairs(table_in) do
table.insert(table_out, v);
for i,v in ipairs(table_in) do
table.insert(table_out, v);
end
end
......
-- -*- Mode: LUA; tab-width: 2 -*-
function fifo_wire_core_ports(fifo)
local prefix = fifo.full_prefix;
local total_size = 0;
fifo.usedw_size = log2up(fifo.size);
local ports = {
port(BIT, 0, "in", prefix.."_"..fifo.rdwr.."_req_i",
csel(fifo.direction == BUS_TO_CORE, "FIFO read request", "FIFO write request" ))
};
-- add full/empty/usedw ports
if inset(FIFO_FULL, fifo.flags_dev) then
table_join(ports, { port (BIT, 0, "out", prefix.."_"..fifo.rdwr.."_full_o", "FIFO full flag") });
table_join(fifo.maps, { vpm (fifo.rdwr.."_full_o", prefix.."_"..fifo.rdwr.."_full_o")});
end
if inset(FIFO_EMPTY, fifo.flags_dev) then
table_join(ports, { port (BIT, 0, "out", prefix.."_"..fifo.rdwr.."_empty_o", "FIFO empty flag") });
table_join(fifo.maps, { vpm (fifo.rdwr.."_empty_o", prefix.."_"..fifo.rdwr.."_empty_o")});
end
if inset(FIFO_COUNT, fifo.flags_dev) then
table_join(ports, { port (SLV, fifo.usedw_size, "out", prefix.."_"..fifo.rdwr.."_count_o",
"FIFO number of used words") });
table_join(fifo.maps, { vpm (fifo.rdwr.."_count_o", prefix.."_"..fifo.rdwr.."_count_o")});
end
foreach_subfield(fifo,
function(field, f)
local field_pfx = string.lower(prefix.."_"..field.hdl_prefix);
total_size = total_size + field.size;
if(fifo.direction == BUS_TO_CORE) then -- bus -> core fifo
table_join(ports, {port (field.type, field.size, "out", field_pfx.."_o")});
-- assign the output to the FIFO output port
-- table_join(fifo.extra_code, {
-- va(field_pfx.."_o",
-- vi(prefix.."_out_int", field.offset_unaligned + field.size -1,
--- field.current_unaligned)) });
else -- core -> bus fifo
table_join(ports, {port (field.type, field.size, "in", field_pfx.."_i")});
table_join(fifo.extra_code, {
va(
vi(prefix.."_in_int", field.offset_unaligned + field.size -1,
field.offset_unaligned),
field_pfx.."_i") });
end
end);
table_join(fifo.ports, ports);
fifo.total_size = total_size;
end
function fifo_wire_bus_ports(fifo)
local fifo_reg_nbits = fifo.current_offset;
-- total number of FIFO input/output registers
local n_regs = math.ceil(fifo_reg_nbits / DATA_BUS_WIDTH);
local fifo_dregs = {};
local i;
for i=0, n_regs -1 do
local minofs = i * DATA_BUS_WIDTH;
local maxofs = (i + 1 ) *DATA_BUS_WIDTH - 1;
fifo_dregs[i] = {};
fifo_dregs[i].ports = {};
fifo_dregs[i].signals = {};
fifo_dregs[i].write_code = {};
fifo_dregs[i].read_code = {};
fifo_dregs[i].reset_code_main = {};
fifo_dregs[i].extra_code = {};
fifo_dregs[i].ackgen_code= {};
print("DREG ", i);
foreach_subfield(fifo,
function(field)
if(field.offset >= minofs and field.offset + field.size - 1 <= maxofs) then
table.insert(fifo_dregs[i], field);
field.offset = field.offset - minofs;
print("FIELD: ", field.name, " OFS: ", field.offset, "SIZE: ",field.size);
end
end);
r = fifo_dregs[i];
r.__type = TYPE_REG;
r.no_std_regbank = true;
r.hdl_prefix = string.format(fifo.hdl_prefix.."_R%d", i);
r.c_prefix = string.format(fifo.c_prefix.."_R%d", i);
r.ack_len = 2;
r.ports = {};
r.signals = {};
if(fifo.direction == BUS_TO_CORE) then
r.name = "FIFO '"..fifo.name.."' data input register "..i;
else -- core -> bus fifo
r.name = "FIFO '"..fifo.name.."' data output register "..i;
r.access_bus = READ_ONLY;
r.access_dev = WRITE_ONLY;
end
foreach_subfield(r,
function (field, r)
if(fifo.direction == BUS_TO_CORE) then
field.write_code = {va(
vi(fifo.full_prefix.."_in_int", -- dst
field.offset_unaligned + field.size - 1,
field.offset_unaligned),
vi("wrdata_reg", -- src
field.offset + field.size - 1,
field.offset))};
field.access_bus = WRITE_ONLY;
field.access_dev = READ_ONLY;
else
end
end);
print(r.hdl_prefix, r.c_prefix, prefix);
table.insert(periph, r);
end
print("lastreg: " ,r.name);
-- last register:
if(fifo.direction == BUS_TO_CORE) then -- Last FIFO I/O register
table_join(r.write_code, { va(fifo.full_prefix.."_wrreq_int", 1) });
table_join(r.ackgen_code, { va(fifo.full_prefix.."_wrreq_int", 0) });
table_join(r.reset_code_main, { va(fifo.full_prefix.."_wrreq_int", 0) });
end
-- add full/empty/usedw control register
local csr = {
["__type"] = TYPE_REG;
["name"] = "FIFO '"..fifo.name.."' control/status register";
["c_prefix"] = fifo.c_prefix.."_CSR";
["hdl_prefix"] = fifo.hdl_prefix.."_CSR";
["no_std_regbank"] = true;
};
function gen_fifo_csr_field(flag, field_prefix, field_name, field_desc, size, type, offset)
if inset(flag, fifo.flags_bus) then
local f = {
["__type"] = TYPE_FIELD;
["name"] = field_name;
["description"] = field_desc;
["access_bus"] = READ_ONLY;
["access_dev"] = WRITE_ONLY;
["type"] = type;
["size"] = size;
["offset"] = offset;
["c_prefix"] = field_prefix;
["hdl_prefix"] = field_prefix;
["signals"] = {};
["read_code"] = {};
["ack_len"] = 2;
};
local sig = fifo.full_prefix.."_"..field_prefix.."_int";
-- wire the FULL signal to appropriate FIFO output
table_join(fifo.maps, { vpm (fifo.rdwr.."_"..field_prefix.."_o", sig)});
table_join(f.signals, { signal (type, size, sig) });
if(type == BIT) then
table_join(f.read_code, { va(vi("rddata_reg", f.offset), sig) });
else
table_join(f.read_code, { va(vi("rddata_reg", f.offset + f.size - 1, f.offset), sig) });
end
table.insert(csr, f);
else
table_join(fifo.maps, { vpm (fifo.rdwr.."_full_o", vopenpin())});
end
end
gen_fifo_csr_field(FIFO_FULL,
"full",
"FIFO full flag",
"1: FIFO '"..fifo.name.."' is full\n0: FIFO is not full",
1,
BIT,
16);
gen_fifo_csr_field(FIFO_EMPTY,
"empty",
"FIFO empty flag",
"1: FIFO '"..fifo.name.."' is empty\n0: FIFO is not empty",
1,
BIT,
17);
gen_fifo_csr_field(FIFO_COUNT,
"count",
"FIFO counter",
"Number of data records currently being stored in FIFO '"..fifo.name.."'",
fifo.usedw_size,
SLV,
0);
if(type(fifo.flags_bus) == "table") then
table.insert(periph, csr);
end
end
function gen_code_fifo(fifo)
local prefix = string.lower(periph.hdl_prefix.."_"..fifo.hdl_prefix);
print("GenCodeFIFO");
fifo.full_prefix = prefix;
fifo.ports= {};
fifo.signals={};
fifo.maps = {};
fifo.extra_code = {};
if(fifo.direction == BUS_TO_CORE) then
fifo.rdwr = "rd";
else
fifo.rdwr = "wr";
end
fifo_wire_core_ports(fifo);
fifo_wire_bus_ports(fifo);
table_join(fifo.signals, {
signal (SLV, fifo.total_size, fifo.full_prefix.."_in_int"),
signal (SLV, fifo.total_size, fifo.full_prefix.."_out_int") });
if(fifo.direction == BUS_TO_CORE) then
table_join(fifo.signals, { signal (BIT, 0, fifo.full_prefix.."_wrreq_int") });
else
end
end
......@@ -127,7 +127,8 @@ foreach_reg(ALL_REG_TYPES, fix_prefix );
foreach_reg(ALL_REG_TYPES, function(reg)
reg.total_size=0;
reg.current_offset=0;
reg.current_offset = 0;
reg.current_offset_unaligned = 0;
end);
......@@ -135,6 +136,8 @@ foreach_field(calc_size);
foreach_reg({TYPE_REG, TYPE_RAM, TYPE_FIFO}, check_max_size);
foreach_field(calc_field_offset);
foreach_reg({TYPE_FIFO}, gen_code_fifo);
foreach_reg({TYPE_REG, TYPE_RAM, TYPE_FIFO}, calc_address_sizes);
assign_addresses();
......
......@@ -626,15 +626,25 @@ end
function fill_unused_bits(target, reg)
local t={};
local code={};
local all_wo = true;
foreach_subfield(reg, function(field, reg)
if(field.type == SLV or field.type == SIGNED or field.type == UNSIGNED) then
for i=field.offset, (field.offset+field.size-1) do t[i] = 1; end
elseif(field.type == BIT or field.type == MONOSTABLE) then
t[field.offset] = 1;
end
end
if(field.access_bus ~= WRITE_ONLY) then all_wo = false; end
end);
if(all_wo) then
for i = 0, DATA_BUS_WIDTH-1 do
table_join(code, { va(vi(target, i), vundefined()); });
end
return code;
end
for i = 0, DATA_BUS_WIDTH-1 do
if(t[i] == nil) then
table_join(code, { va(vi(target, i), vundefined()); });
......@@ -665,13 +675,14 @@ function gen_abstract_code(reg)
reg.full_hdl_prefix = string.lower(periph.hdl_prefix.."_"..reg.hdl_prefix);
if(reg.no_std_regbank == true) then
print("reg: ",reg.name," - no std regbank");
return;
end
if(reg.__type == TYPE_RAM) then
gen_code_ram(reg);
else
else
foreach_subfield(reg, function(field, reg) gen_hdl_code_reg_field(field, reg); end );
end
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment