如何编写大型VHDL模块并使其可读?

时间:2016-08-29 12:05:40

标签: vhdl xilinx-ise

我正在尝试为玩具处理器编写控制逻辑模块。它循环通过读取/解码/执行状态,从各种存储器位读取和写入,并设置一组控制信号。它有点大,据我所知,它不能真正细分为更小的模块。

我不想把所有状态的逻辑都放在一个过程中 - 它很难读,而且中间别名的数量很大。使用模拟器时信号很痛苦。

我尝试将每个州的逻辑拆分为自己的流程,但后来我遇到了多个驱动程序的问题。

我还尝试在一个主进程的头部为每个状态的逻辑声明单独的过程,并让进程根据当前状态调用正确的过程。这很好用,模块化的“功能”和更可读的结构... 每个程序的中间信号在模拟器中是不可见的(并且可能无法访问测试平台?我之前放弃了试着这样做。)我正在使用ISim以防万一。

我做错了吗?我可以使用一些技巧来避免一个庞大的整体过程吗?

编辑:模块的代码是here

3 个答案:

答案 0 :(得分:1)

可能只需要使用更适合阅读大型VHDL文件的编辑器。我经常处理3000多行VHDL文件,其中大部分空间是单个进程的逻辑,并且由于支持代码折叠的编辑器而没有阅读它们的困难。

我使用Notepad ++,但我确信还有其他编辑器可以支持VHDL语法折叠。当我打开一个文件时,按下alt + 0折叠每个可能的语法折叠点,然后根据需要扩展到我正在处理的部分。您也可以使用行隐藏来折叠文件的任意部分,尽管使用起来有点尴尬。

如果您有大量相关的并发语句,您可以轻松地将它们分组到一个带有name : if true generate的折叠点,这也允许您在主体系结构范围之外声明中间信号(block语句有效,但并非所有工具都支持)。要在流程中强制折叠点,我使用if true then

答案 1 :(得分:1)

如果您正在设计一个在巨大的case语句中实现不同操作的处理器,那么您真正描述的是一系列并行功能单元,为输出多路复用器供电。您可能有一个输出被驱动,具体取决于操作模式,乘法,加法,减法,某些逻辑运算,移位等的输出。

您可以通过在自己的实体中实现每个功能单元,以模块化方式轻松设计它,其中一些可能非常简单。在第一种情况下,这些块将无条件地操作,并且它们的输出将馈送输出多路复用器。您可能稍后添加由指令解码逻辑驱动的启用信号,该启用信号仅启用将在特定操作中使用的块,以节省功耗。听起来你可能会使用这种方法得到很多控制信号,但是如果你将它们全部放在一个记录中,它会使代码非常紧凑,同时在控制点允许冗长和可读性使用信号,例如:

AddSub : entity work.AdderSubtractor
port map (
  clk => clk,
  enable => decoded_instruction.addsub_enable,
  a => a,
  b => b,
  mode => decoded_instruction.addsub_mode, -- This might be an enumerated type
  output => addsub_output
);

会有其他_output信号,最后你会有类似

的信号
OutputMux : process (all)
begin
  case decoded_instruction.output_mux_select is
    when ADD_SUB => output <= addsub_output;
    when MULT => output <= mult_output;
    when LOGIC => output <= logic_output;
  end case;
end process;

这样做的一个好处是,您可能会发现在FPGA中的DSP模块中实现的几个功能是有效的;您可以轻松设计一个功能块,用于添加,减去,乘法,写入目标设备中的DSP模块。这个输出只是你输出的另一个输入。复用器。根据我的经验,您应该能够使用单个DSP模块(或描述一些级联DSP模块的单个实体,根据您的数据路径宽度)有效地实现许多处理功能。

我个人更喜欢这种使设计非常模块化的方法。在最近的一个多核DSP项目中,我只有几个文件有~500行,大多数有200或更少。这意味着当我回到设计的一部分时,它通常适合一页,并且可以在很短的时间内轻松地被拾取和理解。我还发现,当实施重型流水线以提高设计性能时,在一个流程或实体中进行过多操作可能会使这项工作变得更加困难。

最后,如果功能元素包含在小实体中,您可以更容易地单独模拟,测试和验证那段代码,根据我的经验,这可以让块被注销更快,同时对代码更有信心。如果所有事情都在一个过程中,那么很难有信心做出修改或改进一件事的改变,并不会打破别的东西。再次采用严格的流水线设计,我发现改变一些无意中导致设计失败的积极时序约束变得非常容易,因此实体越简单,发生这种情况的可能性就越小。

答案 2 :(得分:0)

如上所述,你的问题很难回答。我们在说几行?

您可以查找良好的VHDL代码实践: - 应避免使用别名(并非所有工具都支持AFAIK) - 给信号/变量一个明确的名称 - 尝试分组功能 - 尽量不要改变由500行分隔的2个地方的信号/变量,通常有办法 - 如果真的需要,你可以考虑使用VHDL93中引入的共享变量。 (但这不会解决您的多个驱动程序问题) - 不要忘记记录分组信号的可用性

关于使“中间信号可见”,您可以写

junk_proc: process(clk, rst) is
variable a,b,c: of_some_types;
begin
if rst then
//do reset stuff
elsif rising_edge(clk)
b:=func1(a);
c:=func2(b);
end if;
end process;

变量a,b和c(在这种情况下为普通线)显然可以在任何模拟工具中显示。

但是,如果您编写b = func1(func2(func3(func4(a)))),请不要忘记您在一个时钟周期内描述了所有这些。考虑到你的描述,我打赌你会遇到问题,但也许这是一种很好的学习方式。