如何等待始终阻塞的边缘?

How to wait for edges in always block?

我想写这样的东西:

always@(posedge bus_start)
begin
    @(posedge scl) buffer[7] = sda;
    @(posedge scl) buffer[6] = sda;
    @(posedge scl) buffer[5] = sda;
    @(posedge scl) buffer[4] = sda;
    @(posedge scl) buffer[3] = sda;
    @(posedge scl) buffer[2] = sda;
    @(posedge scl) buffer[1] = sda;
    @(posedge scl) buffer[0] = sda;
end

但是根据我得到的错误是无法合成的

我可能会用FSM来解决这个问题,但这会使它变得复杂,有什么办法让它可以综合吗?

您似乎正在尝试从 I2C 接口捕获数据。 这是一个简单的解决方案,用于从 sda 捕获 8 位数据并将其存储到名为 buffer 的寄存器中。

// starts on rising edge of scl or bus_start
always@(posedge bus_start or posedge scl) 
begin
    buffer[0] <= sda; // loads sda into the lowest bit of buffer
    buffer[7:1] <= buffer[6:0]; // shifts the lower 6 bits one to
                                // the left, acting as a shift register
end

可以在 verilog 中找到有关 I2C 的更多信息here 此外,可以找到一个基本的 I2C 从机 here(您必须注册并登录才能查看源代码)。

您没有提供足够的信息。

@Krabby127 的回答也不可综合。

我认为你还有很多工作要做。您应该首先了解 Verilog 和 C 之间的区别。 RTL代码是描述硬件的FPGA.So可综合的概念对你来说很重要。

并且您必须处理 I2C 的去抖动 signal.Take 处理三态信号。 毕竟我建议你从 opencores.org 得到一些 I2C 项目来研究。 原谅我糟糕的英语。

I2C slave 主要使用 SCL 以外的采样时钟。我并不是说不可能,但通常的做法是使用更快的时钟来采样 SCL 和 SDA 信号。

我绝对建议至少从以下端口开始设计。由于SDA是三态信号,我也建议现阶段不要处理它。您可以假设它已在您的模块之外完成,并且可以继续使用单独的输入和输出端口。

input  clk;     // system clock
input  rst;     // system reset

input  scl;     // i2c clock
input  sda_in;  // i2c input data
output sda_out; // i2c output data

老实说,I2C 不是学习 HDL(Verilog/SV/VHDL)和数字设计的好选择。会带来一些复杂的问题。