-
Notifications
You must be signed in to change notification settings - Fork 0
/
bitio_op.vhd
135 lines (116 loc) · 4.07 KB
/
bitio_op.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
-------------------------------------------------------------------------------
--
-- Title Modular VHDL peripheral
-- https://github.com/the-moog/vhdl_modular_blocks
-- File bitio_op.vhd
-- Author Jason Morgan
--
-- Copyright © Jason Morgan 2018
-- License This work is licensed under a Creative Commons Attribution-NoDerivatives 4.0 International License.
-- CC-BY-ND, see LICENSE.TXT
--
-------------------------------------------------------------------------------
--
-- Date 17/7/2018
-- Version 2
--
-- ChangeLog
-- =========
-- Version By Date Change
--
-- 1 J A Morgan 2009 Initial version
-- 2 J A Morgan 17/7/18 Updated to VHDL2008
--
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_lOGIC_ARITH.all;
use work.utils.setall;
use work.utils.log2;
use work.types.all;
use work.modules.all;
/*!
@brief MODULAR PERIPHERAL: An arbitrary output register.
@details This is an example of a typical modular bus peripheral<BR>
Implements a bank of registered outputs
<BR>
All peripherals have the same bus interface, but an atbitrary bus size
*/
entity bitio_op is
generic (npins : integer := 16;
rst_value : std_logic_vector(npins - 1 downto 0) := (others => '0'));
port (
clk : in std_logic;
rst : in std_logic;
module : in module_t;
addr : in std_logic_vector;
data : inout std_logic_vector; --Sampled on the rising edge of clk
op_pins : out std_logic_vector(npins - 1 downto 0);
size : out positive;
cs : in std_logic; --Module enable active high, sampled on the rising edge of clk
rd_nwr : in std_logic); --Read/not Write
end entity;
/*!
@brief Typical implementation of a modular bus peripheral
@details Note now the data bus and address bus are of arbitrary size
*/
architecture behavior of bitio_op is
type std_lv_array is array (natural range <>) of std_logic_vector(data'range);
constant ZZZ : std_logic_vector(data'range) := (others => 'Z');
constant nbanks : integer := log2(npins / data'length);
signal op_reg : std_lv_array(0 to nbanks - 1);
signal rd_data : std_logic_vector(data'range);
constant sizei : positive := nbanks; --need to use an intermediate constant here to keep synplicity happy
constant addrbits : positive := log2(nbanks);
begin
data <= rd_data when rd_nwr = '1' and cs = '1' else ZZZ;
size <= sizei;
do_read : process (all) is
variable address : unsigned(addrbits - 1 downto 0);
variable bank : integer;
begin
address := unsigned(addr(address'range)) - module.base;
bank := conv_integer(address);
rd_data <= (others => '0');
case conv_integer(address) is
when 0 =>
rd_data <= op_reg(bank);
when others =>
null;
end case;
end process;
do_write : process(all) is
variable address : unsigned(addrbits - 1 downto 0);
variable bank : integer;
variable nbit : integer;
begin
address := unsigned(addr(address'range)) - module.base;
if rst = '1' then
for pin in op_pins'range loop
bank := pin / data'length;
nbit := pin mod data'length;
op_reg(bank)(pin) <= rst_value(pin);
end loop;
elsif rising_edge(clk) then --Process regs on rising edge
--Handle write
bank := conv_integer(address);
if cs = '1' and bank < nbanks and rd_nwr = '0' then
op_reg(bank) <= data;
end if;
end if;
end process;
do_op : process (all)
variable bank : integer;
variable nbit : integer;
begin
for pin in op_pins'range loop
--Map the register bit to a pin
--Registers are numbered 15 downto 0
--Pins are numbered 0 to N
--Bit 0 (LSB/RHS) is mapped to output 0 (LHS), Bit 1 to output 1 etc.
bank := pin / data'length;
nbit := pin mod data'length;
op_pins(pin) <= op_reg(bank)(nbit);
end loop;
end process;
end architecture;