Skip to content
Snippets Groups Projects
Commit b0b19257 authored by Federico Vaga's avatar Federico Vaga
Browse files

Merge remote-tracking branch 'ohwr/proposed_master' into develop

parents 58695b59 6258b8df
Branches
Tags
No related merge requests found
files = ["wb16_to_wb32.vhd"]
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- WR2RF_VME core
-- https://ohwr.org/project/vme-rf-wr-bobr
--------------------------------------------------------------------------------
--
-- unit name: wb16_to_wb32
--
-- description: Bridge wishbone data width by using a register for the upper 16
-- bits.
-- In order to atomically read a 32 bit word at address ADDR:
-- * read the 16 LSB word at address ADDR
-- * read the 16 MSB word at address ADDR+2
-- In order to atomically write a 32 bit word at address ADDR:
-- * write the 16 MSB word at address ADDR+2
-- * write the 16 LSB word at address ADDR
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN (home.cern)
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.wishbone_pkg.all;
entity wb16_to_wb32 is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
wb16_i : in t_wishbone_slave_in;
wb16_o : out t_wishbone_slave_out;
wb32_i : in t_wishbone_master_in;
wb32_o : out t_wishbone_master_out
);
end;
architecture arch of wb16_to_wb32 is
signal datah : std_logic_vector(15 downto 0);
signal stall : std_logic;
signal we : std_logic;
signal ack : std_logic;
begin
wb16_o.stall <= stall or ack;
wb32_o.dat (31 downto 16) <= datah;
wb16_o.rty <= '0';
wb16_o.err <= '0';
wb16_o.ack <= ack;
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
datah <= (others => '0');
stall <= '0';
ack <= '0';
wb32_o.cyc <= '0';
wb32_o.stb <= '0';
else
if stall = '0' then
-- Ready.
ack <= '0';
if wb16_i.stb = '1' and wb16_i.cyc = '1' and ack = '0' then
if wb16_i.adr(1) = '1' then
-- Access to DATAH.
if wb16_i.we = '1' then
-- Write.
if wb16_i.sel(0) = '1' then
datah (7 downto 0) <= wb16_i.dat(7 downto 0);
end if;
if wb16_i.sel(1) = '1' then
datah (15 downto 8) <= wb16_i.dat(15 downto 8);
end if;
else
-- Read
wb16_o.dat(15 downto 0) <= datah;
end if;
ack <= '1';
else
-- Access to the device.
stall <= '1';
we <= wb16_i.we;
wb32_o.cyc <= '1';
wb32_o.stb <= '1';
wb32_o.adr <= wb16_i.adr(31 downto 2) & "00";
wb32_o.dat (15 downto 0) <= wb16_i.dat(15 downto 0);
wb32_o.we <= wb16_i.we;
wb32_o.sel <= "11" & wb16_i.sel (1 downto 0); -- Humm...
end if;
end if;
else
-- Stall = 1, waiting for the answer.
if wb32_i.ack = '1' then
wb16_o.dat (15 downto 0) <= wb32_i.dat (15 downto 0);
if we = '0' then
datah <= wb32_i.dat (31 downto 16);
end if;
wb32_o.cyc <= '0';
wb32_o.stb <= '0';
ack <= '1';
stall <= '0';
end if;
end if;
end if;
end if;
end process;
end arch;
......@@ -157,7 +157,7 @@ architecture structural of i2c_master_top is
signal sr : std_logic_vector(7 downto 0); -- status register
-- internal reset signal
signal rst_i : std_logic;
signal arst_n : std_logic;
-- wishbone write access
signal wb_wacc : std_logic;
......@@ -190,7 +190,7 @@ architecture structural of i2c_master_top is
begin
-- generate internal reset signal
rst_i <= not wb_rst_i; --arst_i xor ARST_LVL;
arst_n <= arst_i xor ARST_LVL;
-- generate acknowledge output signal
gen_ack_o : process(wb_clk_i)
......@@ -228,9 +228,9 @@ begin
-- generate registers (CR, SR see below)
gen_regs: process(rst_i, wb_clk_i)
gen_regs: process(arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
prer <= (others => '1');
ctr <= (others => '0');
txr <= (others => '0');
......@@ -268,9 +268,9 @@ begin
-- generate command register
gen_cr: process(rst_i, wb_clk_i)
gen_cr: process(arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
cr <= (others => '0');
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
......@@ -309,7 +309,7 @@ begin
port map (
clk => wb_clk_i,
rst => wb_rst_i,
nReset => rst_i,
nReset => arst_n,
ena => core_en,
clk_cnt => prer,
start => sta,
......@@ -346,9 +346,9 @@ begin
st_irq_block : block
begin
-- generate status register bits
gen_sr_bits: process (wb_clk_i, rst_i)
gen_sr_bits: process (arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
al <= '0';
rxack <= '0';
tip <= '0';
......@@ -371,9 +371,9 @@ begin
end process gen_sr_bits;
-- generate interrupt request signals
gen_irq: process (wb_clk_i, rst_i)
gen_irq: process (arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
inta_o <= '0';
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
......
......@@ -28,9 +28,6 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.genram_pkg.all;
package wishbone_pkg is
constant c_wishbone_address_width : integer := 32;
......
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// General Cores Library
// https://www.ohwr.org/projects/general-cores
//------------------------------------------------------------------------------
//
// Title : Software Wishbone master unit for testbenches
// unit name: IWishboneMaster
//
// File : if_wishbone.sv
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : SystemVerilog
// description: Software Wishbone master unit for testbenches.
//
/* Todo:
pipelined reads
settings wrapped in the accessor object
*/
//------------------------------------------------------------------------------
// Copyright CERN 2010-2019
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions
// and limitations under the License.
//------------------------------------------------------------------------------
`include "simdrv_defs.svh"
`include "if_wishbone_types.svh"
......@@ -23,35 +32,24 @@ interface IWishboneMaster
input rst_n_i
);
parameter g_addr_width = 32;
parameter g_data_width = 32;
logic [g_addr_width - 1 : 0] adr;
logic [g_data_width - 1 : 0] dat_o;
logic [(g_data_width/8)-1 : 0] sel;
wire [g_data_width - 1 : 0] dat_i;
wire ack;
wire stall;
wire err;
wire rty;
logic cyc;
logic stb;
logic we;
wire clk;
wire rst_n;
time last_access_t = 0;
parameter g_addr_width = 32;
parameter g_data_width = 32;
struct {
int gen_random_throttling;
real throttle_prob;
int little_endian;
int cyc_on_stall;
wb_address_granularity_t addr_gran;
} settings;
logic [g_addr_width - 1 : 0] adr;
logic [g_data_width - 1 : 0] dat_o;
logic [(g_data_width/8)-1 : 0] sel;
wire [g_data_width - 1 : 0] dat_i;
wire ack;
wire stall;
wire err;
wire rty;
logic cyc;
logic stb;
logic we;
modport master
wire stall_valid = stall & cyc;
modport master
(
output adr,
output dat_o,
......@@ -59,316 +57,246 @@ interface IWishboneMaster
output cyc,
output stb,
output we,
input ack,
input dat_i,
input stall,
input err,
input rty
input ack,
input dat_i,
input stall,
input err,
input rty
);
function automatic logic[g_addr_width-1:0] gen_addr(uint64_t addr, int xfer_size);
if(settings.addr_gran == WORD)
case(g_data_width)
8: return addr;
16: return addr >> 1;
32: return addr >> 2;
64: return addr >> 3;
default: $error("IWishbone: invalid WB data bus width [%d bits\n]", g_data_width);
endcase // case (xfer_size)
else
return addr;
endfunction
time last_access_t = 0;
enum {
IDLE,
BUSY,
WAIT_ACK
} xf_state;
wb_cycle_t request_queue[$];
wb_cycle_t result_queue[$];
struct {
int gen_random_throttling;
real throttle_prob;
int little_endian; // not supported
int cyc_on_stall; // not used, kept for compatibility
wb_address_granularity_t addr_gran;
} settings;
function automatic logic[63:0] rev_bits(logic [63:0] x, int nbits);
logic[63:0] tmp;
int i;
for (i=0;i<nbits;i++)
tmp[nbits-1-i] = x[i];
for (i = 0; i < nbits; i++)
tmp[nbits-1-i] = x[i];
return tmp;
endfunction // rev_bits
function automatic logic[g_addr_width-1:0] gen_addr(wb_xfer_t xfer);
if (settings.addr_gran == WORD)
case (g_data_width)
8: return xfer.a;
16: return xfer.a >> 1;
32: return xfer.a >> 2;
64: return xfer.a >> 3;
default: $error("IWishbone: invalid WB data bus width [%d bits\n]", g_data_width);
endcase
else
return xfer.a;
endfunction // gen_addr
//FIXME: little endian
function automatic logic[(g_data_width/8)-1:0] gen_sel(uint64_t addr, int xfer_size, int little_endian);
function automatic logic[(g_data_width/8)-1:0] gen_sel(wb_xfer_t xfer);
logic [(g_data_width/8)-1:0] sel;
const int dbytes = (g_data_width/8-1);
sel = ((1<<xfer_size) - 1);
return rev_bits(sel << (addr % xfer_size), g_data_width/8);
endfunction
sel = ((1 << xfer.size) - 1);
return rev_bits(sel << (xfer.a % xfer.size), g_data_width/8);
endfunction // gen_sel
function automatic logic[g_data_width-1:0] gen_data(uint64_t addr, uint64_t data, int xfer_size, int little_endian);
//FIXME: little endian
function automatic logic[g_data_width-1:0] gen_data(wb_xfer_t xfer);
const int dbytes = (g_data_width/8-1);
logic[g_data_width-1:0] tmp;
tmp = data << (8 * (dbytes - (xfer_size - 1 - (addr % xfer_size))));
// $display("GenData: xs %d dbytes %d %x", tmp, xfer_size, dbytes);
return tmp;
return xfer.d << (8 * (dbytes - (xfer.size - 1 - (xfer.a % xfer.size))));
endfunction // gen_data
function automatic uint64_t decode_data(uint64_t addr, logic[g_data_width-1:0] data, int xfer_size);
function automatic uint64_t decode_data(wb_xfer_t xfer, logic[g_data_width-1:0] data);
int rem;
// $display("decode: a %x d %x xs %x", addr, data ,xfer_size);
rem = xfer.a % xfer.size;
rem = addr % xfer_size;
return (data >> (8*rem)) & ((1<<(xfer_size*8)) - 1);
return (data >> (8 * rem)) & ((1 << (xfer.size * 8)) - 1);
endfunction // decode_data
task automatic classic_cycle
(
inout wb_xfer_t xfer[],
input bit rw,
input int n_xfers,
output wb_cycle_result_t result
);
int i;
if($time != last_access_t)
@(posedge clk_i); /* resynchronize, just in case */
for(i=0;i<n_xfers;i++)
begin
stb <= 1'b1;
cyc <= 1'b1;
adr <= gen_addr(xfer[i].a, xfer[i].size);
we <= rw;
sel <= gen_sel(xfer[i].a, xfer[i].size, settings.little_endian);
//gen_sel(xfer[i].a, xfer[i].size);
dat_o <= gen_data(xfer[i].a, xfer[i].d, xfer[i].size, settings.little_endian);
@(posedge clk_i);
if(ack == 0) begin
while(ack == 0) begin @(posedge clk_i); end
end else if(err == 1'b1 || rty == 1'b1)
begin
cyc <= 0;
we <= 0;
stb <= 0;
result = (err ==1'b1 ? R_ERROR: R_RETRY);
break;
end
xfer[i].d = decode_data(xfer[i].a, dat_i, xfer[i].size);
cyc <= 0;
we <= 0;
stb <= 0;
end // if (ack == 0)
@(posedge clk_i);
result = R_OK;
last_access_t = $time;
endtask // automatic
task automatic classic_cycle(ref wb_cycle_t c);
reg xf_idle = 1;
int i;
int ack_cnt_int;
int failure = 0;
/* resynchronize, just in case */
if ($time != last_access_t) @(posedge clk_i);
xf_state = BUSY;
for (i = 0; i < c.data.size(); i++) begin
stb <= 1'b1;
cyc <= 1'b1;
adr <= gen_addr(c.data[i]);
we <= (c.rw != 0);
sel <= gen_sel(c.data[i]);
dat_o <= gen_data(c.data[i]);
@(posedge clk_i);
while (ack != 1'b1 && err != 1'b1 && rty == 1'b1) @(posedge clk_i);
if (err || rty) begin
c.result = (err ? R_ERROR: R_RETRY);
failure = 1;
break;
end
c.data[i].d = decode_data(c.data[i], dat_i);
cyc <= 0;
we <= 0;
stb <= 0;
@(posedge clk_i);
end
if (!failure)
c.result = R_OK;
xf_state = IDLE;
last_access_t = $time;
endtask // classic_cycle
task automatic pipelined_cycle(ref wb_cycle_t c);
int stb_count = 0;
int ack_count = 0;
int failure = 0;
int cur_rdbk = 0;
/* resynchronize, just in case */
if ($time != last_access_t) @(posedge clk_i);
xf_state = BUSY;
cyc <= 1'b1;
stb <= 1'b1;
adr <= gen_addr(c.data[stb_count]);
if (c.rw == 1) begin
we <= 1'b1;
sel <= gen_sel(c.data[stb_count]);
dat_o <= gen_data(c.data[stb_count]);
end
else begin
we <= 1'b0;
sel <= 'hffffffff;
end
while (stall_valid || ((stb_count < c.data.size()) && !failure)) begin
if (ack) begin
ack_count++;
if (c.rw == 0) begin
c.data[cur_rdbk].d = dat_i;
cur_rdbk++;
end
end
else if (err || rty) begin
c.result = (err ? R_ERROR: R_RETRY);
failure = 1;
break;
end
if (settings.gen_random_throttling &&
probability_hit(settings.throttle_prob)) begin
stb <= 1'b0;
we <= 1'b0;
end
else if (stall_valid == 1'b0) begin
stb <= 1'b1;
adr <= gen_addr(c.data[stb_count]);
if (c.rw == 1) begin
we <= 1'b1;
sel <= gen_sel(c.data[stb_count]);
dat_o <= gen_data(c.data[stb_count]);
end
else begin
we <= 1'b0;
sel <= 'hffffffff;
end
stb_count++;
end
@(posedge clk_i);
end
stb <= 1'b0;
we <= 1'b0;
xf_state = WAIT_ACK;
while ((ack_count < c.data.size()) && !failure) begin
if (ack) begin
ack_count++;
if (c.rw == 0) begin
c.data[cur_rdbk].d = dat_i;
cur_rdbk++;
end
end
else if (err || rty) begin
c.result = (err ? R_ERROR: R_RETRY);
failure = 1;
xf_state = IDLE;
break;
end
if (ack_count == c.data.size()) begin
cyc <= 1'b0;
we <= 1'b0;
xf_state = IDLE;
end
@(posedge clk_i);
end
always@(posedge clk_i)
begin
if(!cyc)
ack_cnt_int <= 0;
else if(stb && !stall && !ack)
ack_cnt_int++;
else if((!stb || stall) && ack)
ack_cnt_int--;
end
task automatic count_ack(ref int ack_cnt);
// if(stb && !stall && !ack)
// ack_cnt++;
if (ack)
ack_cnt--;
endtask
task automatic handle_readback(ref wb_xfer_t xf [$], input int read, ref int cur_rdbk);
if(ack && read)
begin
xf[cur_rdbk].d = dat_i;
cur_rdbk++;
end
endtask // handle_readback
task automatic pipelined_cycle
(
ref wb_xfer_t xfer[$],
input int write,
input int n_xfers,
output wb_cycle_result_t result
);
int i;
int ack_count ;
int failure ;
int cur_rdbk;
ack_count = 0;
failure = 0;
xf_idle = 0;
cur_rdbk = 0;
if($time != last_access_t)
@(posedge clk_i); /* resynchronize, just in case */
while(stall && !settings.cyc_on_stall)
@(posedge clk_i);
cyc <= 1'b1;
i =0;
ack_count = n_xfers;
while(i<n_xfers)
begin
count_ack(ack_count);
handle_readback(xfer, !write, cur_rdbk);
if(err) begin
result = R_ERROR;
failure = 1;
break;
end
if(rty) begin
result = R_RETRY;
failure = 1;
break;
end
if (!stall && settings.gen_random_throttling && probability_hit(settings.throttle_prob)) begin
stb <= 1'b0;
we <= 1'b0;
@(posedge clk_i);
end else begin
adr <= gen_addr(xfer[i].a, xfer[i].size);
stb <= 1'b1;
if(write)
begin
we <= 1'b1;
sel <= gen_sel(xfer[i].a, xfer[i].size, settings.little_endian);
dat_o <= gen_data(xfer[i].a, xfer[i].d, xfer[i].size, settings.little_endian);
end else begin
we<=1'b0;
sel <= 'hffffffff;
end
@(posedge clk_i);
stb <= 1'b0;
we <= 1'b0;
if(stall)
begin
stb <= 1'b1;
if(write)
we <= 1'b1;
while(stall)
begin
count_ack(ack_count);
@(posedge clk_i);
end
stb <= 1'b0;
we <= 1'b0;
end
i++;
end
end // for (i =0;i<n_xfers;i++)
while((ack_count > 0) && !failure)
begin
// $display("AckCount %d", ack_count);
if(err) begin
result = R_ERROR;
failure = 1;
break;
end
if(rty) begin
result = R_RETRY;
failure = 1;
break;
end
count_ack(ack_count);
handle_readback(xfer, !write, cur_rdbk);
if(stb && !ack)
ack_count++;
else if(!stb && ack)
ack_count--;
@(posedge clk_i);
end
cyc <= 1'b0;
@(posedge clk_i);
if(!failure)
result = R_OK;
xf_idle = 1;
last_access_t = $time;
endtask // automatic
we <= 1'b0;
wb_cycle_t request_queue[$];
wb_cycle_t result_queue[$];
if (!failure)
c.result = R_OK;
last_access_t = $time;
endtask // pipelined_cycle
class CIWBMasterAccessor extends CWishboneAccessor;
function automatic int poll();
return 0;
endfunction
endfunction // poll
task get(ref wb_cycle_t xfer);
while(!result_queue.size())
@(posedge clk_i);
xfer = result_queue.pop_front();
endtask
task clear();
endtask // clear
@(posedge clk_i);
xfer = result_queue.pop_front();
endtask // get
task put(ref wb_cycle_t xfer);
request_queue.push_back(xfer);
endtask // put
function int idle();
return (request_queue.size() == 0) && xf_idle;
return (request_queue.size() == 0) && (xf_state == IDLE);
endfunction // idle
endclass // CIWBMasterAccessor
endclass // CIWBMasterAccessor
function automatic CIWBMasterAccessor get_accessor();
automatic CIWBMasterAccessor tmp;
......@@ -376,63 +304,44 @@ endclass // CIWBMasterAccessor
return tmp;
endfunction // get_accessor
always@(posedge clk_i)
if(!rst_n_i)
begin
request_queue = {};
result_queue = {};
xf_idle = 1;
cyc <= 0;
dat_o <= 0;
stb <= 0;
sel <= 0;
adr <= 0;
we <= 0;
end
if (!rst_n_i) begin
request_queue = {};
result_queue = {};
xf_state = IDLE;
cyc <= 0;
dat_o <= 0;
stb <= 0;
sel <= 0;
adr <= 0;
we <= 0;
end
initial begin
settings.gen_random_throttling = 0;
settings.throttle_prob = 0.1;
settings.cyc_on_stall = 0;
settings.addr_gran = WORD;
settings.throttle_prob = 0.1;
settings.addr_gran = WORD;
end
initial forever begin
@(posedge clk_i);
if (request_queue.size() > 0) begin
wb_cycle_t c;
c = request_queue.pop_front();
case(c.ctype)
PIPELINED:
pipelined_cycle(c);
CLASSIC:
classic_cycle(c);
endcase
result_queue.push_back(c);
end
end
initial forever
begin
@(posedge clk_i);
if(request_queue.size() > 0)
begin
wb_cycle_t c;
wb_cycle_result_t res;
c = request_queue.pop_front();
case(c.ctype)
PIPELINED:
begin
pipelined_cycle(c.data, c.rw, c.data.size(), res);
c.result =res;
end
CLASSIC:
begin
// $display("WBMaster: got classic cycle [%d, rw %d]", c.data.size(), c.rw);
classic_cycle(c.data, c.rw, c.data.size, res);
c.result =res;
end
endcase // case (c.ctype)
result_queue.push_back(c);
end
end
endinterface // IWishbone
endinterface // IWishboneMaster
[*]
[*] GTKWave Analyzer v3.3.98 (w)1999-2018 BSI
[*] Tue Mar 3 12:42:41 2020
[*]
[dumpfile] "/home/tgingold/Repositories/ohwr/general-cores/modules/wishbone/wb16_to_wb32/tb/tb.ghw"
[dumpfile_mtime] "Tue Mar 3 12:40:34 2020"
[dumpfile_size] 2363
[savefile] "/home/tgingold/Repositories/ohwr/general-cores/modules/wishbone/wb16_to_wb32/tb/tb.gtkw"
[timestart] 0
[size] 1620 1056
[pos] -1 -1
*-23.629396 61240000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top.
[treeopen] top.tb_wb16_to_wb32.
[sst_width] 283
[signals_width] 102
[sst_expanded] 1
[sst_vpaned_height] 315
@28
top.tb_wb16_to_wb32.rst_n
top.tb_wb16_to_wb32.clk
@200
-wb32
@28
top.tb_wb16_to_wb32.wb32_in.cyc
top.tb_wb16_to_wb32.wb32_in.stb
top.tb_wb16_to_wb32.wb32_in.we
top.tb_wb16_to_wb32.wb32_out.ack
@22
#{top.tb_wb16_to_wb32.wb32_out.dat[31:0]} top.tb_wb16_to_wb32.wb32_out.dat[31] top.tb_wb16_to_wb32.wb32_out.dat[30] top.tb_wb16_to_wb32.wb32_out.dat[29] top.tb_wb16_to_wb32.wb32_out.dat[28] top.tb_wb16_to_wb32.wb32_out.dat[27] top.tb_wb16_to_wb32.wb32_out.dat[26] top.tb_wb16_to_wb32.wb32_out.dat[25] top.tb_wb16_to_wb32.wb32_out.dat[24] top.tb_wb16_to_wb32.wb32_out.dat[23] top.tb_wb16_to_wb32.wb32_out.dat[22] top.tb_wb16_to_wb32.wb32_out.dat[21] top.tb_wb16_to_wb32.wb32_out.dat[20] top.tb_wb16_to_wb32.wb32_out.dat[19] top.tb_wb16_to_wb32.wb32_out.dat[18] top.tb_wb16_to_wb32.wb32_out.dat[17] top.tb_wb16_to_wb32.wb32_out.dat[16] top.tb_wb16_to_wb32.wb32_out.dat[15] top.tb_wb16_to_wb32.wb32_out.dat[14] top.tb_wb16_to_wb32.wb32_out.dat[13] top.tb_wb16_to_wb32.wb32_out.dat[12] top.tb_wb16_to_wb32.wb32_out.dat[11] top.tb_wb16_to_wb32.wb32_out.dat[10] top.tb_wb16_to_wb32.wb32_out.dat[9] top.tb_wb16_to_wb32.wb32_out.dat[8] top.tb_wb16_to_wb32.wb32_out.dat[7] top.tb_wb16_to_wb32.wb32_out.dat[6] top.tb_wb16_to_wb32.wb32_out.dat[5] top.tb_wb16_to_wb32.wb32_out.dat[4] top.tb_wb16_to_wb32.wb32_out.dat[3] top.tb_wb16_to_wb32.wb32_out.dat[2] top.tb_wb16_to_wb32.wb32_out.dat[1] top.tb_wb16_to_wb32.wb32_out.dat[0]
#{top.tb_wb16_to_wb32.wb32_in.adr[31:0]} top.tb_wb16_to_wb32.wb32_in.adr[31] top.tb_wb16_to_wb32.wb32_in.adr[30] top.tb_wb16_to_wb32.wb32_in.adr[29] top.tb_wb16_to_wb32.wb32_in.adr[28] top.tb_wb16_to_wb32.wb32_in.adr[27] top.tb_wb16_to_wb32.wb32_in.adr[26] top.tb_wb16_to_wb32.wb32_in.adr[25] top.tb_wb16_to_wb32.wb32_in.adr[24] top.tb_wb16_to_wb32.wb32_in.adr[23] top.tb_wb16_to_wb32.wb32_in.adr[22] top.tb_wb16_to_wb32.wb32_in.adr[21] top.tb_wb16_to_wb32.wb32_in.adr[20] top.tb_wb16_to_wb32.wb32_in.adr[19] top.tb_wb16_to_wb32.wb32_in.adr[18] top.tb_wb16_to_wb32.wb32_in.adr[17] top.tb_wb16_to_wb32.wb32_in.adr[16] top.tb_wb16_to_wb32.wb32_in.adr[15] top.tb_wb16_to_wb32.wb32_in.adr[14] top.tb_wb16_to_wb32.wb32_in.adr[13] top.tb_wb16_to_wb32.wb32_in.adr[12] top.tb_wb16_to_wb32.wb32_in.adr[11] top.tb_wb16_to_wb32.wb32_in.adr[10] top.tb_wb16_to_wb32.wb32_in.adr[9] top.tb_wb16_to_wb32.wb32_in.adr[8] top.tb_wb16_to_wb32.wb32_in.adr[7] top.tb_wb16_to_wb32.wb32_in.adr[6] top.tb_wb16_to_wb32.wb32_in.adr[5] top.tb_wb16_to_wb32.wb32_in.adr[4] top.tb_wb16_to_wb32.wb32_in.adr[3] top.tb_wb16_to_wb32.wb32_in.adr[2] top.tb_wb16_to_wb32.wb32_in.adr[1] top.tb_wb16_to_wb32.wb32_in.adr[0]
#{top.tb_wb16_to_wb32.wb32_in.dat[31:0]} top.tb_wb16_to_wb32.wb32_in.dat[31] top.tb_wb16_to_wb32.wb32_in.dat[30] top.tb_wb16_to_wb32.wb32_in.dat[29] top.tb_wb16_to_wb32.wb32_in.dat[28] top.tb_wb16_to_wb32.wb32_in.dat[27] top.tb_wb16_to_wb32.wb32_in.dat[26] top.tb_wb16_to_wb32.wb32_in.dat[25] top.tb_wb16_to_wb32.wb32_in.dat[24] top.tb_wb16_to_wb32.wb32_in.dat[23] top.tb_wb16_to_wb32.wb32_in.dat[22] top.tb_wb16_to_wb32.wb32_in.dat[21] top.tb_wb16_to_wb32.wb32_in.dat[20] top.tb_wb16_to_wb32.wb32_in.dat[19] top.tb_wb16_to_wb32.wb32_in.dat[18] top.tb_wb16_to_wb32.wb32_in.dat[17] top.tb_wb16_to_wb32.wb32_in.dat[16] top.tb_wb16_to_wb32.wb32_in.dat[15] top.tb_wb16_to_wb32.wb32_in.dat[14] top.tb_wb16_to_wb32.wb32_in.dat[13] top.tb_wb16_to_wb32.wb32_in.dat[12] top.tb_wb16_to_wb32.wb32_in.dat[11] top.tb_wb16_to_wb32.wb32_in.dat[10] top.tb_wb16_to_wb32.wb32_in.dat[9] top.tb_wb16_to_wb32.wb32_in.dat[8] top.tb_wb16_to_wb32.wb32_in.dat[7] top.tb_wb16_to_wb32.wb32_in.dat[6] top.tb_wb16_to_wb32.wb32_in.dat[5] top.tb_wb16_to_wb32.wb32_in.dat[4] top.tb_wb16_to_wb32.wb32_in.dat[3] top.tb_wb16_to_wb32.wb32_in.dat[2] top.tb_wb16_to_wb32.wb32_in.dat[1] top.tb_wb16_to_wb32.wb32_in.dat[0]
#{top.tb_wb16_to_wb32.wb32_in.sel[3:0]} top.tb_wb16_to_wb32.wb32_in.sel[3] top.tb_wb16_to_wb32.wb32_in.sel[2] top.tb_wb16_to_wb32.wb32_in.sel[1] top.tb_wb16_to_wb32.wb32_in.sel[0]
@200
-wb16
@28
top.tb_wb16_to_wb32.wb16_out.cyc
top.tb_wb16_to_wb32.wb16_out.stb
top.tb_wb16_to_wb32.wb16_out.we
@29
top.tb_wb16_to_wb32.wb16_in.stall
@22
#{top.tb_wb16_to_wb32.wb16_out.adr[31:0]} top.tb_wb16_to_wb32.wb16_out.adr[31] top.tb_wb16_to_wb32.wb16_out.adr[30] top.tb_wb16_to_wb32.wb16_out.adr[29] top.tb_wb16_to_wb32.wb16_out.adr[28] top.tb_wb16_to_wb32.wb16_out.adr[27] top.tb_wb16_to_wb32.wb16_out.adr[26] top.tb_wb16_to_wb32.wb16_out.adr[25] top.tb_wb16_to_wb32.wb16_out.adr[24] top.tb_wb16_to_wb32.wb16_out.adr[23] top.tb_wb16_to_wb32.wb16_out.adr[22] top.tb_wb16_to_wb32.wb16_out.adr[21] top.tb_wb16_to_wb32.wb16_out.adr[20] top.tb_wb16_to_wb32.wb16_out.adr[19] top.tb_wb16_to_wb32.wb16_out.adr[18] top.tb_wb16_to_wb32.wb16_out.adr[17] top.tb_wb16_to_wb32.wb16_out.adr[16] top.tb_wb16_to_wb32.wb16_out.adr[15] top.tb_wb16_to_wb32.wb16_out.adr[14] top.tb_wb16_to_wb32.wb16_out.adr[13] top.tb_wb16_to_wb32.wb16_out.adr[12] top.tb_wb16_to_wb32.wb16_out.adr[11] top.tb_wb16_to_wb32.wb16_out.adr[10] top.tb_wb16_to_wb32.wb16_out.adr[9] top.tb_wb16_to_wb32.wb16_out.adr[8] top.tb_wb16_to_wb32.wb16_out.adr[7] top.tb_wb16_to_wb32.wb16_out.adr[6] top.tb_wb16_to_wb32.wb16_out.adr[5] top.tb_wb16_to_wb32.wb16_out.adr[4] top.tb_wb16_to_wb32.wb16_out.adr[3] top.tb_wb16_to_wb32.wb16_out.adr[2] top.tb_wb16_to_wb32.wb16_out.adr[1] top.tb_wb16_to_wb32.wb16_out.adr[0]
#{top.tb_wb16_to_wb32.wb16_out.dat[31:0]} top.tb_wb16_to_wb32.wb16_out.dat[31] top.tb_wb16_to_wb32.wb16_out.dat[30] top.tb_wb16_to_wb32.wb16_out.dat[29] top.tb_wb16_to_wb32.wb16_out.dat[28] top.tb_wb16_to_wb32.wb16_out.dat[27] top.tb_wb16_to_wb32.wb16_out.dat[26] top.tb_wb16_to_wb32.wb16_out.dat[25] top.tb_wb16_to_wb32.wb16_out.dat[24] top.tb_wb16_to_wb32.wb16_out.dat[23] top.tb_wb16_to_wb32.wb16_out.dat[22] top.tb_wb16_to_wb32.wb16_out.dat[21] top.tb_wb16_to_wb32.wb16_out.dat[20] top.tb_wb16_to_wb32.wb16_out.dat[19] top.tb_wb16_to_wb32.wb16_out.dat[18] top.tb_wb16_to_wb32.wb16_out.dat[17] top.tb_wb16_to_wb32.wb16_out.dat[16] top.tb_wb16_to_wb32.wb16_out.dat[15] top.tb_wb16_to_wb32.wb16_out.dat[14] top.tb_wb16_to_wb32.wb16_out.dat[13] top.tb_wb16_to_wb32.wb16_out.dat[12] top.tb_wb16_to_wb32.wb16_out.dat[11] top.tb_wb16_to_wb32.wb16_out.dat[10] top.tb_wb16_to_wb32.wb16_out.dat[9] top.tb_wb16_to_wb32.wb16_out.dat[8] top.tb_wb16_to_wb32.wb16_out.dat[7] top.tb_wb16_to_wb32.wb16_out.dat[6] top.tb_wb16_to_wb32.wb16_out.dat[5] top.tb_wb16_to_wb32.wb16_out.dat[4] top.tb_wb16_to_wb32.wb16_out.dat[3] top.tb_wb16_to_wb32.wb16_out.dat[2] top.tb_wb16_to_wb32.wb16_out.dat[1] top.tb_wb16_to_wb32.wb16_out.dat[0]
#{top.tb_wb16_to_wb32.wb16_out.sel[3:0]} top.tb_wb16_to_wb32.wb16_out.sel[3] top.tb_wb16_to_wb32.wb16_out.sel[2] top.tb_wb16_to_wb32.wb16_out.sel[1] top.tb_wb16_to_wb32.wb16_out.sel[0]
@28
top.tb_wb16_to_wb32.wb16_in.ack
@22
#{top.tb_wb16_to_wb32.wb16_in.dat[31:0]} top.tb_wb16_to_wb32.wb16_in.dat[31] top.tb_wb16_to_wb32.wb16_in.dat[30] top.tb_wb16_to_wb32.wb16_in.dat[29] top.tb_wb16_to_wb32.wb16_in.dat[28] top.tb_wb16_to_wb32.wb16_in.dat[27] top.tb_wb16_to_wb32.wb16_in.dat[26] top.tb_wb16_to_wb32.wb16_in.dat[25] top.tb_wb16_to_wb32.wb16_in.dat[24] top.tb_wb16_to_wb32.wb16_in.dat[23] top.tb_wb16_to_wb32.wb16_in.dat[22] top.tb_wb16_to_wb32.wb16_in.dat[21] top.tb_wb16_to_wb32.wb16_in.dat[20] top.tb_wb16_to_wb32.wb16_in.dat[19] top.tb_wb16_to_wb32.wb16_in.dat[18] top.tb_wb16_to_wb32.wb16_in.dat[17] top.tb_wb16_to_wb32.wb16_in.dat[16] top.tb_wb16_to_wb32.wb16_in.dat[15] top.tb_wb16_to_wb32.wb16_in.dat[14] top.tb_wb16_to_wb32.wb16_in.dat[13] top.tb_wb16_to_wb32.wb16_in.dat[12] top.tb_wb16_to_wb32.wb16_in.dat[11] top.tb_wb16_to_wb32.wb16_in.dat[10] top.tb_wb16_to_wb32.wb16_in.dat[9] top.tb_wb16_to_wb32.wb16_in.dat[8] top.tb_wb16_to_wb32.wb16_in.dat[7] top.tb_wb16_to_wb32.wb16_in.dat[6] top.tb_wb16_to_wb32.wb16_in.dat[5] top.tb_wb16_to_wb32.wb16_in.dat[4] top.tb_wb16_to_wb32.wb16_in.dat[3] top.tb_wb16_to_wb32.wb16_in.dat[2] top.tb_wb16_to_wb32.wb16_in.dat[1] top.tb_wb16_to_wb32.wb16_in.dat[0]
[pattern_trace] 1
[pattern_trace] 0
library ieee;
use ieee.std_logic_1164.all;
use work.wishbone_pkg.all;
entity tb_wb16_to_wb32 is
end;
architecture behav of tb_wb16_to_wb32 is
signal clk : std_logic;
signal rst_n : std_logic;
signal wb16_in : t_wishbone_master_in;
signal wb16_out : t_wishbone_master_out;
signal wb32_in : t_wishbone_slave_in;
signal wb32_out : t_wishbone_slave_out;
signal reg1 : std_logic_vector(31 downto 0);
signal reg0 : std_logic_vector(31 downto 0);
signal done : boolean := false;
begin
dut: entity work.wb16_to_wb32
port map (
clk_i => clk,
rst_n_i => rst_n,
wb16_i => wb16_out,
wb16_o => wb16_in,
wb32_i => wb32_out,
wb32_o => wb32_in
);
process
begin
clk <= '0';
wait for 5 ns;
clk <= '1';
wait for 5 ns;
if done then
wait;
end if;
end process;
-- Simple slave with 2 registers.
process (clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
reg1 <= x"4400_3300";
reg0 <= x"2200_1100";
wb32_out.ack <= '0';
else
if wb32_in.cyc = '1' and wb32_in.stb = '1' then
if wb32_in.we = '1' then
if wb32_in.adr (2) = '1' then
reg1 <= wb32_in.dat;
else
reg0 <= wb32_in.dat;
end if;
else
if wb32_in.adr (2) = '1' then
wb32_out.dat <= reg1;
else
wb32_out.dat <= reg0;
end if;
end if;
wb32_out.ack <= '1';
else
wb32_out.ack <= '0';
end if;
end if;
end if;
end process;
process
procedure wait_ack is
begin
loop
wait until rising_edge (clk);
exit when wb16_in.ack = '1';
end loop;
end wait_ack;
procedure read16 (addr : std_logic_vector (31 downto 0)) is
begin
wb16_out.adr <= addr;
wb16_out.we <= '0';
wb16_out.cyc <= '1';
wb16_out.stb <= '1';
wait_ack;
end read16;
procedure write16 (addr : std_logic_vector (31 downto 0); dat : std_logic_vector(15 downto 0)) is
begin
wb16_out.adr <= addr;
wb16_out.dat (15 downto 0) <= dat;
wb16_out.we <= '1';
wb16_out.sel <= "0011";
wb16_out.cyc <= '1';
wb16_out.stb <= '1';
wait_ack;
end write16;
begin
rst_n <= '0';
wait until rising_edge (clk);
wait until rising_edge (clk);
rst_n <= '1';
read16 (x"0000_0000");
assert wb16_in.dat (15 downto 0) = x"1100" severity failure;
read16 (x"0000_0002");
assert wb16_in.dat (15 downto 0) = x"2200" severity failure;
read16 (x"0000_0004");
assert wb16_in.dat (15 downto 0) = x"3300" severity failure;
read16 (x"0000_0006");
assert wb16_in.dat (15 downto 0) = x"4400" severity failure;
write16(x"0000_0002", x"0220");
write16(x"0000_0000", x"0110");
read16 (x"0000_0000");
assert wb16_in.dat (15 downto 0) = x"0110" severity failure;
read16 (x"0000_0002");
assert wb16_in.dat (15 downto 0) = x"0220" severity failure;
done <= true;
report "done";
wait;
end process;
end behav;
\ No newline at end of file
......@@ -3,10 +3,16 @@
with open("buildinfo_pkg.vhd", "w") as f:
import subprocess
import time
commitid = subprocess.check_output(
try:
commitid = subprocess.check_output(
["git", "log", "-1", "--format=%H"]).decode().strip()
userid = subprocess.check_output(
except:
commitid = "unknown"
try:
userid = subprocess.check_output(
["git", "config", "--get", "user.name"]).decode().strip()
except:
userid = "unknown"
if action == "simulation":
top = sim_top
tool = sim_tool
......
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