【问题标题】:ADT7420 Temperature reading -VerilogADT7420 温度读数-Verilog
【发布时间】:2016-04-29 19:48:37
【问题描述】:

我有以下代码来尝试读取我的 nexys4DDR FPGA 板上的 ADT7420。我似乎无法让它工作。所有的 LED 都打开了,我找不到问题所在。我哪里错了?

reg [5:0] SD_COUNTER = 6'd0;//counter used for the sending all the signals     to the temperature sensor
   reg [31:0] count= 32'h00000000;//counter used for slow clock
//since we are using SDA as inout we cannot use it inside the always block. I created a temp. reg SDI
    reg SDI;//register used for sending signals to temperature sensor inside the always block
    reg SCLK; // clock used inside the always block which is equated to the SCL at the end.
    reg dp = 1'b1;//decimal point for 7 segment display
    reg [18:0] Counter; // temp. counter for multiplexing seven segment display
// these are the registers used for 7 segment display
    reg [3:0] first;
reg [3:0] second;
reg [3:0] third;
reg [3:0] fourth;
reg [3:0] fifth;
reg [3:0] sixth;
reg [3:0] seg;
reg [15:0] led_temp = 16'b0000000000000000;//temp reg used in always block to asssign sda values
reg CLK = 0;//slow clock
// code for slow clock(200k)
always @ (posedge clk)
begin
    count <= count + 1;
    Counter <= Counter + 1;

if (count == 32'h00030D40)//200k in hex
    begin
        count  <= 0;
        CLK <= ~CLK;
    end
 else 
    count <= count + 1;
 end
always @ (posedge CLK) //always on 200k clock
begin
    if (SD_COUNTER == 49)
        SD_COUNTER <= 1;
    else
        SD_COUNTER <= SD_COUNTER + 1;
end

always @ (posedge CLK)
begin

    case (SD_COUNTER)
        6'd0   :   begin SDI <= 1; SCLK <= 1; end //initial condition
        //START signal for I2C protocol
        6'd1    :   SDI <= 0;
        6'd2    :   SCLK <= 1;
//      SLAVE ADDRESS 0x4B
        6'd3    :   SDI <= 1;
        6'd4    :   SDI <= 0;
        6'd5    :   SDI <= 0;
        6'd6    :   SDI <= 1;
        6'd7    :   SDI <= 0;
        6'd8    :   SDI <= 1;
        6'd9    :   SDI <= 1;
        6'd10   :   SDI <= 0; //write (R/W =1'b0 bit)
        6'd11   :   SDI <= 1'bz; //ACK (acknowledge from slave) 
        // Address of register inside the temperature sensor (0x00, temperature register)
        6'd12   :   SDI <= 0;
        6'd13   :   SDI <= 0;
        6'd14   :   SDI <= 0;
        6'd15   :   SDI <= 0;
        6'd16   :   SDI <= 0;
        6'd17   :   SDI <= 0;
        6'd18   :   SDI <= 0;
        6'd19   :   SDI <= 0;
        6'd20   :   SDI <= 1'bz; //acknowledge from the slave
        //Re-Start signal for I2C protocol
        6'd21   : begin SDI <= 1; SCLK <= 1;end
        6'd22   :   SDI <= 0;
        6'd23   :   SCLK <= 1;
        //Slave Address 0x4B

        6'd24   :   SDI <= 1;
        6'd25   :   SDI <= 0;
        6'd26   :   SDI <= 0;
        6'd27   :   SDI <= 1;
        6'd28   :   SDI <= 0;
        6'd29   :   SDI <= 1;
        6'd30   :   SDI <= 1;
        6'd31   :   SDI <= 1;//read (R/W=1'b1 bit)(read from the temp. sensor)
        6'd32   :   SDI <= 1'bz;//acknowledge from the slave
//we are storing in the values in a temporary led register, so that we can see the values on the leds.
        //Reading and storing the temperature on led_temp(MSB)
        6'd33   :   led_temp[15] <= SDI;
        6'd34   :   led_temp[14] <= SDI;
        6'd35   :   led_temp[13] <= SDI;
        6'd36   :   led_temp[12] <= SDI;
        6'd37   :   led_temp[11] <= SDI;
        6'd38   :   led_temp[10] <= SDI;
        6'd39   :   led_temp[9]  <= SDI;
        6'd40   :   led_temp[8]  <= SDI;
        6'd41   :   SDI <= 1'bz; // acknowledge from the slave

        //Reading and storing the temperature on led_temp(LSB)
        6'd42   :   led_temp[7]  <= SDI;
        6'd43   :   led_temp[6]  <= SDI;
        6'd44   :   led_temp[5]  <= SDI;
        6'd45   :   led_temp[4]  <= SDI;
        6'd46   :   led_temp[3]  <= SDI;
        6'd47   :   led_temp[2]  <= SDI;
        6'd48   :   led_temp[1]  <= SDI;
        6'd49   :   led_temp[0]  <= SDI;
        6'd50   :   SDI     <= 1'b1; //acknowledge from the master 

        //STOP signal for I2C protocol
        6'd51  :   begin SDI <= 1'b0; SCLK <= 1'b1; end
        6'd52   :   SDI <= 1'b1;
       endcase

end
//assigning led_temp to led 
assign led = led_temp;  
//assigning the SCL(I2C clock) to either slow clock(200k) or SCLK. 
assign SCL = ((SD_COUNTER >= 4) & (SD_COUNTER <= 20) | ((SD_COUNTER >= 25) & (SD_COUNTER <= 49)))  ? ~CLK : SCLK;
//assignin SDA(I2C Serial data) to SDI
assign SDA = SDI;

【问题讨论】:

标签: verilog temperature


【解决方案1】:

看起来您正在使用SDI 作为三态,但是三态必须是wire 类型;不是reg。故意将xz 分配给reg 类型表明这种情况下的值是无关紧要的,允许合成器驱动生成的网络为任何值(通常基于逻辑优化)。它仍然是驱动的,而不是三态的。

三态应该是wire 类型,并且赋值应该很简单:

wire SDI;
reg SDI_drv_en, SDI_drv_val;
always @(posedge clk) begin
  // ... assign SDI_drv_en & SDI_drv_val to known values (1 or 0), plus other logic ...
end
assign SDI = SDI_drv_en ? SDI_drv_val : 1'bz; // Simple tri-state driver

仅供参考:
大多数 RTL 编码指南建议不要将 reg 类型分配给 xz
听起来您是在直接合成 RTL 代码而不进行模拟。建议在合成前进行模拟。在仿真中调试逻辑问题更容易。
您的代码可能还有其他问题,但这应该足以让您朝着正确的方向前进。

【讨论】:

  • 模拟输入输出的最佳方法是什么?我是否只想将其作为模拟输出?
  • 端口应该是inout。 RTL 采样时应该有什么东西在驱动它;例如另一个模块或测试台。
猜你喜欢
  • 2018-04-08
  • 1970-01-01
  • 2018-02-07
  • 2019-11-30
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 2018-04-18
  • 1970-01-01
相关资源
最近更新 更多