FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6352 Discussions

Connecting an 8-bit peripheral to a 32-bit avalon bus

Altera_Forum
Honored Contributor II
1,783 Views

Hello, 

 

I am connecting an I2C core to a ColdFire V1 IP Core using the Avalon Bus in SOPC. I get a warning about the slave (I2C core), which has 8-bit registers, not having byteenables. Then it says Narrow (less than 32-bit) writes from the cpu core will result in spurious writes to the I2C slave. I also notice that when I write to addresses in memory (RAM), they get written to correctly whether writing using a 32-bit int or a 4 successive writes with char type (8-bit), but when writing to the I2C core, I have to write all 4 registers (are at 4 successive address in the I2C Core) at once, but if I try to write them as bytes, things get hosed. :confused: 

 

Salman
0 Kudos
11 Replies
Altera_Forum
Honored Contributor II
569 Views

I would ignore the 2 LSBs of the address bus and add a byteenable[1:0] in the I2C module and use those two bits internally as your 2 LSBs of the address.  

 

Boris
0 Kudos
Altera_Forum
Honored Contributor II
569 Views

Boris thanks for responding. Okay, now why do I need 2 bits for byte enable? I have the following code for the writing of internal 8-bit registers using just 3 bits of the address for the write and just one byte for the write data register : 

 

// avalon signals 

input clk; // master clock input 

input reset_n; // asynchronous reset 

input [2:0] address; // lower address bits 

output [7:0] writedata; // databus output 

input wr; // write input 

input rd; // read input 

 

reg [7:0] writedata; 

 

always @(posedge clk) 

begin 

//if (~wr & rd) 

if (wr & ~rd) 

case (address) // synopsys parallel_case 

3'b000: writedata <=# 1 prer[ 7:0]; 

3'b001: writedata <=# 1 prer[15:8]; 

3'b010: writedata <=# 1 ctr; 

3'b011: writedata <=# 1 rxr; // write is transmit register (txr) 

3'b100: writedata <=# 1 sr; // write is command register (cr) 

3'b101: writedata <=# 1 txr; 

3'b110: writedata <=# 1 cr; 

3'b111: writedata <=# 1 0; // reserved 

endcase 

end
0 Kudos
Altera_Forum
Honored Contributor II
569 Views

This is just a snippet of my code. I will attach the whole top level for you to see (if needed).

0 Kudos
Altera_Forum
Honored Contributor II
569 Views

First the avalon bus structure by default is 32-bit data, word addressing, using byteenables. When a slave is only 8-bits wide the SOPC builder will generate a 32-bit to 8-bit converter. This converter needs the byteeneables from the slave to be able to tell which specific byte address to write/read. Otherwise each read/write on the avalon will be a word access and the converter will perform 4 byte accesses from the slave. This will result in the effect that you are seeing. Just do this in your code.  

 

input [1:0] byteenable; 

 

 

wire [2:0] address_int; 

assign address_int = {address[2], byteenable}; 

 

Use the address_int in your case. Of course you will have to map in the byteenable in the component as well.  

 

/Boris
0 Kudos
Altera_Forum
Honored Contributor II
569 Views

BTW does your Coldfire core have byteenables? If not that would explain why this is happening. I have used your method with the NIOS processor and having 8-bit slaves works just fine without byteenables on the slave.

0 Kudos
Altera_Forum
Honored Contributor II
569 Views

It is actually has an AMBA bus but has a wrapper on it so that it works with the SOPC/Avalon bus. I wasn't using the byteenables. I will try using them as per the suggestion. THanks. 

 

.abyteenable (abyteenable) // output: 4-bit Byte Enable [3]=31:24 [2]=23:16 [1]=15:8 [0]=7:0
0 Kudos
Altera_Forum
Honored Contributor II
569 Views

Yeah try that. I think you can leave your slave alone.

0 Kudos
Altera_Forum
Honored Contributor II
569 Views

It is really best to make your slave 32bits and to ignore the high bits (set to zero on reads). 

You probably still want to verify that the byte enable for D0..7 is asserted. 

 

Note that the nios cpu always does 32bit reads (all byte enables asserted), discarding the unwanted bits internally. 

 

The additional logic for the mux is almost certainly less than that for the bus width adapter!
0 Kudos
Altera_Forum
Honored Contributor II
569 Views

I agree I try to make all my slaves 32-bit to avoid problems with the different bus widths.

0 Kudos
Altera_Forum
Honored Contributor II
569 Views

I tried your suggestion of using the byteenable, but now I have many configuration registers within the i2c module being optimized away (some which I need to stay). Perhaps that byteenable fix isn't going to work for my file or do I need some modification of my top-level IP to make it work? See the attached of what I did.

0 Kudos
Altera_Forum
Honored Contributor II
569 Views

I think I made a mistake when I suggested a solution to you. There are actually 4 byteenable bits in the byteenable bus. One for each byte within the word. You probably need to do the following.  

 

input [3:0] byteenable; 

 

wire [2:0] address_int; 

 

 

always (*) 

begin 

case(byteenable) 

4'b0001: address_int = {address[2], 2'b00}; 

4'b0010: address_int = {address[2], 2'b01}; 

4'b0100: address_int = {address[2], 2'b10}; 

4'b1000: address_int = {address[2], 2'b11}; 

default: address_int = {address[2], 2'b00}; 

endcase 

end 

 

Please check out the avalon specification for more information on how byteenables work.  

 

/Boris
0 Kudos
Reply