Mark Baseggio
Junior Member level 2
Hello,
I am currently working on a project with an old C64 SID (Sound Interface Device) chip. I'm using a Xilinx SC9572XL CPLD along with an ESP8266 acting as SPI master. The CPLD performs clocking of the SID, as well as conversion of the SPI data to the SID's address and data lines. While the code seems to compile/generate I get tons of warnings I can't figure out.
**disclaimer** In terms of experience with logic, I'm a "total noob." I've done my best with Google and researching examples available, but please don't beat me over the head and tell me I'm dumb. Because I already know that
I have developed the following code to receive data from the SPI master (note it sends 200bits at a time, which is all of the SID's 25 one-byte registers). As you can see the code stores the data like a ROM, and throws up a flag when there is data ready to read and put on the bus. Race conditions are not an issue as writes go to the SPI bus very slowly at 50Hz, so the CPLD has lots of time to write the register values.
Here is the corresponding module that then takes the data and writes it to the SID data/addr bus. Note: the CPLD clk line is 20MHz, while the sid_clk is 1MHz. The SID accepts write while it's clock is high.
From what I can tell by my hack-ish test-benches things are working as designed. But I get all these warnings that I'm not sure if I should be concerned about or not:
If anyone feels like helping me out I'd be very appreciative! THANKS.
Mark
I am currently working on a project with an old C64 SID (Sound Interface Device) chip. I'm using a Xilinx SC9572XL CPLD along with an ESP8266 acting as SPI master. The CPLD performs clocking of the SID, as well as conversion of the SPI data to the SID's address and data lines. While the code seems to compile/generate I get tons of warnings I can't figure out.
**disclaimer** In terms of experience with logic, I'm a "total noob." I've done my best with Google and researching examples available, but please don't beat me over the head and tell me I'm dumb. Because I already know that
I have developed the following code to receive data from the SPI master (note it sends 200bits at a time, which is all of the SID's 25 one-byte registers). As you can see the code stores the data like a ROM, and throws up a flag when there is data ready to read and put on the bus. Race conditions are not an issue as writes go to the SPI bus very slowly at 50Hz, so the CPLD has lots of time to write the register values.
Code:
module spi_slave(
input ss,
input sclk,
input mosi,
input read_en,
input [4:0] addr,
output [7:0] data,
output reg data_rdy = 1'b0
);
reg [7:0] data_in;
reg [7:0] bit_cnt = 8'd0;
reg [7:0] sid_reg [24:0]; // store all SID registers
assign data = (read_en) ? sid_reg[addr] : 8'b0;
always @(posedge sclk) begin
if (!ss) begin
data_in = {data_in[6:0], mosi}; // shift left
bit_cnt = bit_cnt + 1;
if (!(bit_cnt % 8)) begin // if # bits in is divisable by 8 we just got a full byte
sid_reg[(bit_cnt/8)-1] <= data_in; // store the current value
if (bit_cnt == 8'd200) bit_cnt <= 8'd0; // once we reach 25 bytes reset the counter
end
end
end
always @(posedge ss or posedge read_en) begin
if(!bit_cnt) data_rdy = 1; // let the bus module know it's time to assert data
if(read_en) data_rdy = 0; // when read starts turn off ready
end
endmodule
Here is the corresponding module that then takes the data and writes it to the SID data/addr bus. Note: the CPLD clk line is 20MHz, while the sid_clk is 1MHz. The SID accepts write while it's clock is high.
Code:
module sid_glue(
input clk,
input sid_clk,
output sid_cs, // active low write
output reg sid_rw = 1'b1, // hold low to write
input data_rdy,
output reg [4:0] addr = 4'b0,
input [7:0] data, // incoming frame data from SPI
output reg read_en = 1'b0,
output reg [4:0] sid_addr = 5'b0,
output reg [7:0] sid_data = 8'b0
);
reg [7:0] last_data [24:0];
reg write_en = 1'b0;
// sync sid_clk to the FPGA clock using a 2-bit shift register
reg [1:0] sid_clk_r; always @(posedge clk) sid_clk_r <= {sid_clk_r[0], sid_clk};
wire sid_clk_risingedge = (sid_clk_r==2'b01);
wire sid_clk_fallingedge = (sid_clk_r==2'b10);
// same for data ready, just need to detect pos edge
reg [1:0] data_rdy_r; always @(posedge clk) data_rdy_r <= {data_rdy_r[0], data_rdy};
wire data_rdy_posedge = (data_rdy_r==2'b01);
assign sid_cs = sid_rw; // tied together for now (we don't need read atm)
always @(posedge clk) begin
if ((write_en || data_rdy_posedge) && sid_clk_risingedge) begin
if (!write_en) write_en <= 1'b1;
read_en = 1;
if ((data != last_data[addr]) || last_data[addr] === 8'bX) begin // don't write the data if it hasn't changed
sid_addr = addr; // put the address on the SID addr lines
sid_data = data; // data on the data line
sid_rw = 0;
last_data[addr] <= data; // copy data to the buffer for compare next time
end
end
else if (write_en && sid_clk_fallingedge) begin
sid_rw = 1;
read_en = 0;
addr = addr + 1; // move to the next address
if (addr == 25) begin write_en <= 0; addr = 5'b0; end // disable writes and reset counter
end
end
endmodule
From what I can tell by my hack-ish test-benches things are working as designed. But I get all these warnings that I'm not sure if I should be concerned about or not:
Code:
..snip..
WARNING:Xst:1710 - FF/Latch <last_data_8_0> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <last_data_9_7> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <last_data_9_6> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <last_data_9_5> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <last_data_9_4> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <last_data_9_3> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <last_data_9_2> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <last_data_9_1> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <last_data_9_0> (without init value) has a constant value of 0 in block <glue>. This FF/Latch will be trimmed during the optimization process.
..snip..
WARNING:Xst:2677 - Node <data_in_7> of sequential type is unconnected in block <spi_slave>.
WARNING:Xst:2677 - Node <data_in_6> of sequential type is unconnected in block <spi_slave>.
WARNING:Xst:2677 - Node <data_in_5> of sequential type is unconnected in block <spi_slave>.
WARNING:Xst:2677 - Node <data_in_4> of sequential type is unconnected in block <spi_slave>.
...snip...
WARNING:Xst:864 - "sid_glue.v" line 33: Comparisons to 'X' or 'Z' are treated as always false.
If anyone feels like helping me out I'd be very appreciative! THANKS.
Mark