Пытаюсь сделать простейший 16-битный процессор на ПЛИС. Для начала пытаюсь реализовать шину данных, по которой ядро будет взаимодействовать с переферией (USART, GPIO и т. д.). И не получается.
Вот так сейчас выглядит ядро:
module mcu_core(rst, clk, addr, data, write);
input rst;
input clk;
output reg[15:0] addr;
inout[15:0] data;
output reg write;
reg[15:0] data_out;
assign data = write ? data_out : 16'bZ;
reg[31:0] counter;
reg[3:0] tmp;
always @(posedge clk or negedge rst)
if (~rst) begin
addr <= 0;
data_out <= 0;
write <= 0;
counter <= 0;
end else begin
if (counter == 0) begin
counter <= 60 * 1000 * 1000;
end else begin
counter <= counter - 1;
if (counter == 1) begin
addr <= 16'hF010;
data_out <= tmp;
write <= 1;
end else if (counter == 30 * 1000 * 1000) begin
addr <= 16'hF010;
write <= 0;
tmp <= ~data;
end else begin
write <= 0;
addr <= 0;
data_out <= 0;
end
end
end
endmodule
Пока вместо исполнения программы из памяти используются хардкоженные действия. Ядро пытается прочитать 16 бит по адресу 0xF010, инвертировать их и записать. И делать так каждую секунду. К шине подключен модуль управления 4 светодиодами:
module led_module(rst, clk, addr, data, write, led);
input rst;
input clk;
input[15:0] addr;
inout[15:0] data;
input write;
output wire[3:0] led;
wire cs;
reg[3:0] state;
assign cs = (addr == 16'hF010);
assign led = ~state;
assign data = (~write && cs) ? state : 16'bZ;
always @(posedge clk or negedge rst)
if (~rst) begin
state <= 0;
end else begin
if (cs && write) begin
state <= data;
end
end
endmodule
Он хранит текущее состояние светодиодов в буфере и позволяет читать и писать его. А реальные выводы ПЛИС синхронизированы с буфером (светодиоды подключены к ПЛИС катодом, поэтому для правильной работы выполняется инверсия).
В итоге я ожидаю, что все светодиоды будут мигать каждую секунду. Однако этого не происходит и они вообще не загораются, потому что ядро читает единицы с шины (и после инверсии они становятся нулями).
Запись без чтения работает - если писать константное значение вместо tmp, то я могу управлять светодиодами.
Подсоединение ядра и модуля светодиодов к шине в модуле верхнего уровня выполнено так:
wire[15:0] addr;
wire[15:0] data;
wire write;
mcu_core core0(usb_rst, usb_clk, addr, data, write);
led_module leds(usb_rst, usb_clk, addr, data, write, led);