我有以下代码尝试在我的nexys4DDR FPGA板上读取ADT7420。我似乎无法让它发挥作用。所有领导的风都开始了,我找不到问题。我哪里错了?
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;
答案 0 :(得分:0)
看起来您正在使用SDI
作为三态,但三态必须是wire
类型;不是reg
。故意将x
或z
分配到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
类型分配给x
或z
。
听起来你没有模拟直接合成你的RTL代码。建议在合成前进行模拟。在模拟中调试逻辑问题更容易
您的代码可能还有其他问题,但这应该足以让您朝着正确的方向前进。