【发布时间】:2017-11-14 11:07:05
【问题描述】:
背景:
我是计算机科学专业的,填补了我们计算机工程人员留下的空白。我在学校,这是我高级项目的一部分。我正在尝试对 FPGA 进行编程,以用于我的团队正在创建的电子棋盘游戏。 FPGA 只是 Raspberry Pi 的一个 IO 扩展器,它控制所有逻辑。下面的 verilog 代码在 Altera Max V 570 开发套件上运行,目的是为生产单元迁移到 Max V 40。每个 FPGA 将控制一组 4 个游戏块,最终产品将有 4 组块。
问题:
我正在创建一个 FPGA,它将与树莓派接口以控制我们系统中的 MOSFET(现在是 LED)。我遇到的问题是,无论我向磁贴发送什么命令,LED 总是像这样切换:
对于 tile0,只有第 0 个 LED 会切换
对于 tile1,只有第一个 LED 会切换
对于 tile2,只有第二个 LED 会切换
对于 tile3,只有第 3 个 LED 会切换
这是一张实际照片的链接:
https://drive.google.com/open?id=0B7P773tnBnRybHhGRmZMX3hScGFrNXpKUDN2c0tBbkFZaTVJ
(忽略每组中的最后一个 LED,它将从电容传感器输入)
这适用于 LED 切换命令(以下代码中的 2'b11)和螺线管切换命令(以下代码中的 2'b01)。
在使用 Altera ModelSim 进行仿真时,一切正常!但是随着所有东西都连接到面包板上,我看到了上面的情况。
我对这个问题的看法
我最初认为问题在于分配给我正在读取的同一个寄存器,但我添加了另一个步骤(偶然......)来读取寄存器,然后分配,但我看到了更糟糕的行为(LED 不会切换)。帮助! :)
这是我的verilog代码:
module comm_protocol(clock, bus, t0, t1, t2, t3, t0cap, t1cap, t2cap, t3cap, capOut);
parameter [1:0] my_address = 2'b11;
input clock;
input [3:0] bus;
output reg [4:0] t0;
output reg [4:0] t1;
output reg [4:0] t2;
output reg [4:0] t3;
input wire t0cap, t1cap, t2cap, t3cap;
output reg capOut;
reg start;
reg [1:0] tickCounter;
reg gotFpgaAddress;
reg [1:0] fpgaAddress;
reg[1:0] tileAddress;
reg gotCommand;
reg [3:0] command;
initial begin
start <= 0;
t0 <= 5'b11111;
t1 <= 5'b11111;
t2 <= 5'b11111;
t3 <= 5'b11111;
end
always @ (posedge clock) begin
// check if we have recieved the start condition, which is just a positive edge on the clock
if (~start) begin
start <= 1;
tickCounter <= 0;
gotFpgaAddress <= 0;
gotCommand <= 0;
end
else begin // we have received the start condition, so continue into the logic
// increment the counter
// this counter controls when a reset of the logic is performed
// the entire protocol should take place in 4 cycles, so when our counter hits 3 we are done
tickCounter <= tickCounter + 1;
if (tickCounter == 3) begin
start <= 0;
end
else begin // no reset, continue into logic
// here, we will read the address of the fpga the pi is talking to
// first check if we have recieved the address or not
if (~gotFpgaAddress) begin
fpgaAddress <= bus[3:2]; //[3:0];
tileAddress <= bus[1:0];
gotFpgaAddress <= 1;
//gotTileAddress <= 1;
end
else begin // we got the address, now compare it to see if it matches our address
if (fpgaAddress == my_address) begin
// the message is intended for us, so next we check if the command has been received
if (~gotCommand) begin
//tileAddress <= bus[3:0];
command <= bus;
gotCommand <= 1;
end
else begin // we have received the command, now decode it and perform the action
// decode the command that has been sent
// leading 11xx : toggle an led specified by the 2 least significant bits
// leading 00xx : read from the capactive sensor and write it onto the bus
// leading 01xx : toggle the solenoid for the popup
// implement logic to toggle leds
if (command[3:2] == 2'b11) begin
// route to appropriate tile
case (tileAddress)
// tile 0
2'b00: begin
case (command[1:0])
2'b00: t0[0] <= ~t0[0];
2'b01: t0[1] <= ~t0[1];
2'b10: t0[2] <= ~t0[2];
2'b11: t0[3] <= ~t0[3];
endcase
end
// tile 1
2'b01: begin
case (command[1:0])
2'b00: t1[0] <= ~t1[0];
2'b01: t1[1] <= ~t1[1];
2'b10: t1[2] <= ~t1[2];
2'b11: t1[3] <= ~t1[3];
endcase
end
// tile 2
2'b10: begin
case (command[1:0])
2'b00: t2[0] <= ~t2[0];
2'b01: t2[1] <= ~t2[1];
2'b10: t2[2] <= ~t2[2];
2'b11: t2[3] <= ~t2[3];
endcase
end
// tile 3
2'b11: begin
case (command[1:0])
2'b00: t3[0] <= ~t3[0];
2'b01: t3[1] <= ~t3[1];
2'b10: t3[2] <= ~t3[2];
2'b11: t3[3] <= ~t3[3];
endcase
end
endcase
end
// implement logic to read from the capacitive sensor and write it onto the bus
else if (command[3:2] == 2'b00) begin
case (tileAddress)
2'b00: capOut <= t0cap;
2'b01: capOut <= t1cap;
2'b10: capOut <= t2cap;
2'b11: capOut <= t3cap;
endcase
end
// implement logic to toggle the solenoid
else if (command[3:2] == 2'b01) begin
case (tileAddress)
2'b00: t0[4] <= ~t0[4];
2'b01: t1[4] <= ~t1[4];
2'b10: t2[4] <= ~t2[4];
2'b11: t3[4] <= ~t3[4];
endcase
end
end
end
end
end
end
end
endmodule
奖金
目前我已经消耗了 42 个逻辑元素,如果有人能指点我如何将其减少到正好 40 个 LE 或更少,我将永远感激不尽!没什么大不了的,80 元 Max V 只比 MaxV40 多 70 美分
【问题讨论】:
-
在 fpga 编译过程中是否收到任何警告?很少有地方对我来说看起来很可疑。 1)没有正确的复位。初始块可能无法在 fpga 中工作。 2)您将端口声明为“reg”,这不一定是一个表现良好的概念。可能在更高级别的层次结构中存在连接问题,并且在模拟/fpga 行为方面存在差异。
-
在 2 分钟的茶歇时间里需要阅读大量代码。一件显而易见的事情是
command- 你什么时候分配它,你什么时候阅读它?它在 2 个不同的时钟周期内吗?你会期望这会起作用吗?如果是这样,为什么?绘制时序图,然后从图中编码;您的控制流看起来不对。还要确保您了解非阻塞赋值 (<=) 的作用。 -
@Serge 我收到了警告,但没有任何线索可以解释为什么它不能正常工作。只是缺少计时文件等等。
-
@EML 命令在收到 fpga 地址和 tile 地址后分配。在下一个时钟周期,命令的内容被使用,所以我没有分配和尝试在同一个周期中使用它。此外,时钟周期之间有很多时间,现在我正在手动切换 pi 上的 shell 中的所有内容(使用 python 和 pigpio)。