这是我第一次发帖,所以我会尽量做到更具体。
在我要发布的代码部分中,我试图以通用方式实现我已注释掉的“Case” - 表达式中的代码。这段代码是更大实现的一部分,我只保留了此代码中当前使用的信号。
所以问题是我希望我的输出“kin”和“din”是通用的,并且根据地址总线的输入“bus_a”,寄存器“kin_2”和“din_2”的正确字(2字节长)应填充值那时“bus_di”输入。
对于我的例子,我将使用“kin”和“din”的原始长度,每个长度为128位。因此,对于128位长度, N = 16 (16 * 8位= 128位)和 K = 8 。
library IEEE;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_1164.ALL;
entity stck_if is
generic (N: integer:=16; K: integer:=8);
port ( -------------- Clock and Reset
clk: in std_logic;
rst: in std_logic;
bus_a: in std_logic_vector (15 downto 0); -- Address
bus_di: in std_logic_vector (15 downto 0); --Data In
kin: out std_logic_vector (8*N-1 downto 0);
din: out std_logic_vector (8*N-1 downto 0));
end stck_if;
architecture stck_if_arch of stck_if is
signal kin_2: std_logic_vector (8*N-1 downto 0);
signal din_2: std_logic_vector (8*N-1 downto 0);
signal encdec_2: std_logic;
signal trig_wr: std_logic;
begin
proc1: process(clk,rst)
variable int_add: integer:=0;
variable add: std_logic_vector (15 downto 0);
variable bit_add: std_logic_vector (15 downto 0);
begin
if rst='1' then
encdec_2<='0';
kin_2<=(others =>'0');
din_2<=(others =>'0');
elsif (clk'event and clk='1') then
if (trig_wr = '1') then
if (bus_a = "0000000000001100") then
encdec_2 <= bus_di(0);
end if;
for i in 0 to K-1 loop
bit_add:="0000000100000000";
int_add:= 2*i;
add:=std_logic_vector(to_unsigned(int_add, 16));
bit_add:= std_logic_vector(unsigned(bit_add) + unsigned(add));
if (bus_a = bit_add) then
kin_2((8*(N-int_add)-1) downto 8*(N-int_add)) <= bus_di;
end if;
end loop;
for i in 0 to K-1 loop
bit_add:="0000000101000000";
int_add:= 2*i;
add:=std_logic_vector(to_unsigned(int_add, 16));
bit_add:= std_logic_vector(unsigned(bit_add) + unsigned(add));
if (bus_a = bit_add) then
din_2((8*(N-int_add)-1) downto 8*(N-int_add)) <= bus_di;
end if;
end loop;
--case bus_a is
-- when "0000000000001100"=> encdec_2 <= bus_di(0); --bus_a = 000C hex
-- when "0000000100000000"=> kin_2(127 downto 112) <= bus_di; --bus_a = 0100 hex
-- when "0000000100000010"=> kin_2(111 downto 96) <= bus_di; --bus_a = 0102 hex
-- when "0000000100000100"=> kin_2(95 downto 80) <= bus_di; --bus_a = 0104 hex
-- when "0000000100000110"=> kin_2(79 downto 64) <= bus_di; --bus_a = 0106 hex
-- when "0000000100001000"=> kin_2(63 downto 48) <= bus_di; --bus_a = 0108 hex
-- when "0000000100001010"=> kin_2(47 downto 32) <= bus_di; --bus_a = 010A hex
-- when "0000000100001100"=> kin_2(31 downto 16) <= bus_di; --bus_a = 010C hex
-- when "0000000100001110"=> kin_2(15 downto 0) <= bus_di; --bus_a = 010E hex
-- when "0000000101000000"=> din_2(127 downto 112) <= bus_di; --bus_a = 0140 hex
-- when "0000000101000010"=> din_2(111 downto 96) <= bus_di; --bus_a = 0142 hex
-- when "0000000101000100"=> din_2(95 downto 80) <= bus_di; --bus_a = 0144 hex
-- when "0000000101000110"=> din_2(79 downto 64) <= bus_di; --bus_a = 0146 hex
-- when "0000000101001000"=> din_2(63 downto 48) <= bus_di; --bus_a = 0148 hex
-- when "0000000101001010"=> din_2(47 downto 32) <= bus_di; --bus_a = 014A hex
-- when "0000000101001100"=> din_2(31 downto 16) <= bus_di; --bus_a = 014C hex
-- when "0000000101001110"=> din_2(15 downto 0) <= bus_di; --bus_a = 014E hex
-- when others => null;
--end case;
end if;
end if;
end process;
kin <= kin_2;
din <= din_2;
end stck_if_arch;
我正在使用 ModelSim PE学生版10.4a 。为了模拟实现的操作,我在ModelSim的命令行中使用以下代码:
restart -f
//clock period 20ns
force -freeze sim:/stck_if/clk 1 0, 0 {10 ns} -r 20
//Activate reset
force -freeze sim:/stck_if/rst 1 0
run
//activate wr
force -freeze sim:/stck_if/trig_wr 1 0
force -freeze sim:/stck_if/rst 0 0
run
force -freeze sim:/stck_if/bus_a 16'h0100 0
force -freeze sim:/stck_if/bus_di 16'h1111 0
run
run
force -freeze sim:/stck_if/bus_a 16'h0102 0
run
run
force -freeze sim:/stck_if/bus_a 16'h0104 0
run
run
force -freeze sim:/stck_if/bus_a 16'h0106 0
run
run
force -freeze sim:/stck_if/bus_a 16'h0108 0
run
run
etc.
尽管代码编译时没有给出任何错误,但在模拟过程中ModelSim会出现以下错误:
根据我的理解,问题在于使用“For Loop”,从我的假设来看,必须是VHDL不能翻译以下表达式:
kin_2((8*(N-int_add)-1) downto 8*(N-int_add)) <= bus_di;
进入实际电路。
我的假设是对的吗? 任何关于如何克服这个问题的想法,或者我应该在哪里寻找/阅读以找到我的答案的任何建议,都会非常有帮助!
答案 0 :(得分:0)
以下版本应该在功能上与您的版本相同,更短,并且 - 在我的拙见 - 更容易阅读。但是,我不知道合成结果会是什么。我发现很难想象推断的原语在带变量的单进程描述中会是什么。
architecture stck_if_arch of stck_if is
signal kin_2: std_logic_vector (8*N-1 downto 0);
signal din_2: std_logic_vector (8*N-1 downto 0);
signal encdec_2: std_logic;
signal trig_wr: std_logic;
begin
proc1: process(clk,rst)
variable high: unsigned(9 downto 0);
variable bid: integer range 0 to N-1;
variable left, right: integer range 0 to 8*N-1;
begin
if rst='1' then
encdec_2<='0';
kin_2<=(others =>'0');
din_2<=(others =>'0');
elsif (clk'event and clk='1') then
if (trig_wr = '1') then
high := unsigned(bus_a(15 downto 6));
bid := to_integer(unsigned(bus_a(5 downto 1)));
left := 16*(8-bid)-1;
right := 16*(7-bid);
if bus_a="0000000000001100" then
encdec_2 <= bus_di(0);
elsif bus_a(0)='0' then
if high=4 then
kin_2(left downto right) <= bus_di;
elsif high=5 then
din_2(left downto right) <= bus_di;
end if;
end if;
end if;
end if;
end process;
kin <= kin_2;
din <= din_2;
end stck_if_arch;
答案 1 :(得分:0)
我有同样的想法,U.Martinez-Corral有点扭曲:
architecture foo of stck_if is
type N_array is array (0 to K - 1) of std_logic_vector(N - 1 downto 0);
signal kin_2: N_array;
signal din_2: N_array;
signal encdec_2: std_logic;
signal trig_wr: std_logic := '1'; -- ; -- FOR TESTING without FORCE
begin
proc1:
process(clk,rst)
variable high: unsigned(9 downto 0);
variable Kidx: integer range 0 to K-1;
begin
if rst = '1' then
encdec_2 <= '0';
kin_2 <= (others => (others => '0'));
din_2 <= (others => (others => '0'));
elsif rising_edge(clk) then
if trig_wr = '1' then
high := unsigned(bus_a (15 downto 6));
Kidx := to_integer(unsigned(bus_a(3 downto 1)));
if bus_a = "0000000000001100" then
encdec_2 <= bus_di(0);
elsif bus_a(0) = '0' then
if high = 4 then
kin_2(kidx) <= bus_di;
elsif high = 5 then
din_2(kidx) <= bus_di;
end if;
end if;
end if;
end if;
end process;
UNION:
if K = 8 generate
kin <= kin_2(0) & kin_2(1) & kin_2(2) & kin_2(3) &
kin_2(4) & kin_2(5) & kin_2(6) & kin_2(7);
din <= din_2(0) & din_2(1) & din_2(2) & din_2(3) &
din_2(4) & din_2(5) & din_2(6) & din_2(7);
end generate; -- GENERATE statement for every usable K value
end architecture foo;
由于VHDL中缺少联合,因此需要为K的每个有用值生成一个generate语句。这是丑陋的一部分。
否则,这里的想法是不使用位(元素索引)范围。
对于我们这些不是Modelsim许可证持有者/用户的测试平台:
library ieee;
use ieee.std_logic_1164.all;
entity stck_if_tb is
end entity;
architecture foo of stck_if_tb is
constant K: integer := 8;
constant N: integer := 16;
signal clk: std_logic := '0';
signal rst: std_logic;
signal bus_a: std_logic_vector (15 downto 0);
signal bus_di: std_logic_vector (15 downto 0);
signal kin: std_logic_vector (8 * N - 1 downto 0);
signal din: std_logic_vector (8 * N - 1 downto 0);
begin
DUT:
entity work.stck_if
generic map (
N => N,
K => K
)
port map (
clk => clk,
rst => rst,
bus_a => bus_a,
bus_di => bus_di,
kin => kin,
din => din
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if now > 240 ns then
wait;
end if;
end process;
STIMULI:
process
begin
wait for 20 ns;
rst <= '1';
wait for 20 ns;
rst <= '0';
bus_a <= x"0100";
bus_di <= x"1111";
wait for 20 ns;
wait for 20 ns;
bus_a <= x"0102";
wait for 20 ns;
wait for 20 ns;
bus_a <= x"0104";
wait for 20 ns;
wait for 20 ns;
bus_a <= x"0106";
wait for 20 ns;
wait for 20 ns;
bus_a <= x"0108";
wait for 20 ns;
wait for 20 ns;
wait;
end process;
end architecture;
这就是:
请注意,我在不使用武力时添加了trig_wr默认值。
附录
Ú。 Martinez-Corral评论说,再次证明我们在建议使用for generate语句时一般都不好做索引算术。 (IEEE Std 1076-2008,11.8 Generate statements)
这演示了修正循环边界以匹配原始问题中注释掉的case语句的方法:
UNION:
for x in K - 1 downto 0 generate
kin(N * (x + 1) - 1 downto N * x) <= kin_2(K - 1 - x);
din(N * (x + 1) - 1 downto N * x) <= din_2(K - 1 - x);
end generate;
它与测试平台生成相同的波形。