I recently started playing with the iE40 icestick evaluation board. I encountered what I think is strange behavior:
It seems that Yosys wants to optimizes away a module which takes a port connected to a RX gpio pin. IMO this should never happen as the state of this pin should never be considered constant. I have recreated this in a minimal verilog program below:
The following code, synthesized with:
yosys -p 'synth_ice40 -noflatten -noabc -top top -json out/top.json'
generates the following
logic.
Removing the (* keep *)
above the rxi
module instead generates following logic.
Note that the rxi
module is now gone, which I don't think is right. Is this expected behavior?
module top
(
input CLK,
input RX,
output TX,
);
reg[7:0] rx_buf;
reg[7:0] tx_buf;
(* keep *) // <-- Prevents `rxi` from being optimized away.
rx rxi
(
.clk(CLK),
.rx(RX),
.rx_buf(rx_buf)
);
tx txi
(
.clk(CLK),
.tx_buf(tx_buf),
.tx(TX)
);
always @(posedge clk) begin
tx_buf <= rx_buf;
end
endmodule
module tx
(
input wire clk,
input wire[7:0] tx_buf,
output wire tx
);
always @(posedge clk) begin
tx <= tx_buf[0];
tx_buf <= {tx_buf[0], tx_buf[7:1]};
end
endmodule
module rx
(
input wire clk,
input wire rx,
output reg[7:0] rx_buf
);
always @(posedge clk) begin
rx_buf <= {rx, rx_buf[7:1]};
end
endmodule
My pin definitions are:
set_io --warn-no-port RX 9
set_io --warn-no-port TX 8
set_io CLK 21
The (* keep *)
gives me the expected logic, but I don't think that the module could ever be correctly optimized away?