Error 10028 can t resolve multiple constant drivers for net

All, Here is one of my Verilog trial-learning code:    ==============================================================  // Verilog learning example module SRAM_Read_Write_Sync ( nrst, Writeclk, Readclk, EQ, write_addr, read_addr); input nrst, Writeclk, Readclk; output EQ, write_addr, read_addr; // De...

All, Here is one of my Verilog trial-learning code: 

 

============================================================== 

// Verilog learning example
module SRAM_Read_Write_Sync ( nrst, Writeclk, Readclk, EQ, write_addr, read_addr);
input nrst, Writeclk, Readclk;
output EQ, write_addr, read_addr;
// Declare the address counters as 9-bit counters
reg write_addr;
reg read_addr;
reg EQ;

// reset address to 0 if NRST goes LO
always @ (negedge nrst)
begin
write_addr = 0;
read_addr = 0;
end

// increment Write address
always @ (posedge Writeclk)
begin
write_addr = write_addr + 1;
end
// increment Read address
always @ (posedge Readclk)
begin
read_addr = read_addr + 1;
if (read_addr == write_addr)
EQ = 1'b1;
else
EQ = 1'b0;
end
endmodule

================================================================== 

All, (the text in RED) when I try to use the negative edge of my nrst as a reset for my address counters I get the  

Error (10028): Can’t resolve multiple constant drivers for net «read_addr[3]» at SRAM_Read_Write_Sync.v(26) 

If I remove the RED code it compiles fine. 

 

How should I implement a nrst signal that take precedence over any other signals that reset the address counters? 

 

Thanks, 

Keith

I’m trying to write a code that will detect a rising edge on din signal and will raise dout for 5 clock cycles after that happens. I keep on getting different errors while compiling and I’m not sure what they mean. I think I lack a basic understanding of some concepts in VHDL but sadly looking online and did not help me much. I still don’t have a feeling of what actions are acceptable by the software.

In my code I currently have a rising edge detector at the 1st process which raises dout to logic high. The second process checks if dout is high and while so counts down from 5 to 0 and on 0 sets dout to logic low.

This does not compile and returns the following errors:

Error (10028): Can’t resolve multiple constant drivers for net «count[2]» at rise_ext.vhd(31)

Error (10029): Constant driver at rise_ext.vhd(17)

Error (10028): Can’t resolve multiple constant drivers for net «count[1]» at rise_ext.vhd(31)

Error (10028): Can’t resolve multiple constant drivers for net «count[0]» at rise_ext.vhd(31)

Error (10028): Can’t resolve multiple constant drivers for net «dout» at rise_ext.vhd(31)

Error (10029): Constant driver at rise_ext.vhd(19)

Error (12153): Can’t elaborate top-level user hierarchy

Error: Quartus II 32-bit Analysis & Synthesis was unsuccessful. 7 errors, 2 warnings
Error: Peak virtual memory: 326 megabytes
Error: Processing ended: Sat Jan 11 13:13:38 2014
Error: Elapsed time: 00:00:04
Error: Total CPU time (on all processors): 00:00:02

Error (293001): Quartus II Full Compilation was unsuccessful. 9 errors, 2 warnings

    entity rise_ext is
    port ( clk:    in  bit ;
           resetN: in  bit ;
           din:    in  bit ;
           count:  buffer integer range 0 to 6 ;
           dout:   buffer bit ) ;
end rise_ext ;

architecture arc_rise_ext of rise_ext is
    signal s1 , s2 : bit ;
begin
    process ( resetN, clk )
    begin
        if resetN = '0' then
           dout <= '0' ;
           count <= 5 ;
        elsif clk'event and clk = '1' then
              s1 <= din ;
              s2 <= s1  ;
              dout <= not s1 and s2 ;
        end if ;
    end process ;

    process ( clk, dout )
    begin
        if clk'event and clk = '1' then
           if dout = '1' then
              if count > 0 then
                 count <= count - 1 ;
              else
                 dout <= '0' ;
                 count <= 5 ;
              end if;
          end if ;
        end if ;
    end process ;
end arc_rise_ext ;

Any help will be appreciated!

I changed all the data types to std_logic and finished the code, still I get these errors…

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity rise_ext is
    port ( clk:    in  std_logic ;
           resetN: in  std_logic ;
           din:    in  std_logic ;
           count:  buffer integer range 0 to 6 ;
           dout:   buffer std_logic ) ;
end rise_ext ;

architecture arc_rise_ext of rise_ext is
    signal s1 , s2 : std_logic ;
begin
    process ( resetN, clk )
    begin
        if resetN = '0' then
           dout <= '0' ;
            count <= 6 ;
        elsif rising_edge(clk) then
              s1 <= din ;
              s2 <= s1  ;
              dout <= not s1 and s2 ;
        end if ;
    end process ;

    process ( clk )
    begin
        if rising_edge(clk) then
           if dout = '1' then
               count <= 5 ;
            end if ;
        end if ;
    end process ;

    process ( clk )
    begin
        if rising_edge(clk) then
           if count = 0 then
                count <= 6 ;
                dout <= '0' ;
            else
               count <= count - 1 ;
            end if ;
        end if ;
    end process ;
end arc_rise_ext ;

I’ve searched for this on google but the answers are not clear to me. Act like I am very stupid please, as I am a freshmen ECE major. My lab wants to me to use Verilog to program a DE0 to display the numbers 0-9 on its displays depending on what switches we flip. We were tasked to to program it in Behavioral, Dataflow, and Structural styles. I have compiled and succesfully programmed the board in Behavioral and Dataflow style. My struggle is with the Structural. I am getting the following errors upon compilation.

Error (10028): Can't resolve multiple constant drivers for net "W_OR_NOT_X_OR_NOT_Y_OR_NOT_Z" at Lab_3_b_structural.v(181)

Error (10028): Can't resolve multiple constant drivers for net 
"W_OR_X_OR_Y_OR_NOT_Z" at Lab_3_b_structural.v(176)

Error (10029): Constant driver at Lab_3_b_structural.v(142)

Error (10029): Constant driver at Lab_3_b_structural.v(157)

Error (12152): Can't elaborate user hierarchy "structural:h0"

Error (293001): Quartus II Full Compilation was unsuccessful. 7 errors, 10 warnings

Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 5 errors, 10 warnings

Error: Peak virtual memory: 453 megabytes
Error: Processing ended: Sat Oct 08 17:13:54 2016
Error: Elapsed time: 00:00:01
Error: Total CPU time (on all processors): 00:00:00
Error: Peak virtual memory: 453 megabytes
Error: Processing ended: Sat Oct 08 17:13:54 2016
Error: Elapsed time: 00:00:01
Error: Total CPU time (on all processors): 00:00:00

/* In this lab we are using Verilog to create the seven segment display on the DE0. 
We had to perform the lab using behavioral, dataflow, and structural. So, three tests */

module Lab_3_b_structural(SW, HEX0, HEX1, HEX2);

    input [9:0] SW;

    output [6:0] HEX0, HEX1, HEX2;

    wire [6:0] hex0, hex1, hex2;
    //DE0 is common anode
    assign HEX0 = ~hex0;
    assign HEX1 = ~hex1;
    assign HEX2 = ~hex2;

    structural h0 (SW[3:0], hex0);
    structural h1 (SW[7:4], hex1);
    structural h2 ({2'b00,SW[9:8]}, hex2);
endmodule 

module structural (bcd, hex);

    input [3:0] bcd; //WXYZ

    output [6:0] hex; //ABCDEFG

    wire W,X,Y,Z;
    assign W = bcd[3];
    assign X = bcd[2];
    assign Y = bcd[1];
    assign Z = bcd[0];

    //NOTS (Used By all Segments)
    wire W_NOT;
    wire X_NOT;
    wire Y_NOT;
    wire Z_NOT;
    not not1 (W_NOT, W);
    not not2 (X_NOT, X);
    not not3 (Y_NOT, Y);
    not not4 (Z_NOT, Z);


    //A =(W|X|Y|~Z)&(W|~X|Y|Z)
    wire W_OR_X_OR_Y_NOT_Z; 
    wire W_OR_NOT_X_OR_Y_OR_Z;

    or or1A (W_OR_X_OR_Y_NOT_Z, 
    W,
    X,
    Y,
    Z_NOT);
    or or2A (W_OR_NOT_X_OR_Y_OR_Z, 
    W, 
    NOT_X,
    Y, 
    Z);
    and FinalA (hex[0], 
    W_OR_NOT_X_OR_Y_OR_Z, 
    W_OR_X_OR_Y_NOT_Z);

    //B = (W|~X|Y|~Z)&(W|~X|~Y|Z)
    wire W_OR_NOT_X_OR_Y_OR_NOT_Z;
    wire W_OR_NOT_X_OR_NOT_Y_OR_Z;

    or or1B (W_OR_NOT_X_OR_Y_OR_NOT_Z, 
    W, 
    NOT_X,
    Y, 
    NOT_Z);
    or or2B (W_OR_NOT_X_OR_NOT_Y_OR_Z, 
    W,
    NOT_X,
    NOT_Y,
    Z);
    and FinalB (hex[1],
    W_OR_NOT_X_OR_Y_OR_NOT_Z,
    W_OR_NOT_X_OR_NOT_Y_OR_Z);

    //C = (W|X|~Y|Z)
    wire W_OR_X_OR_NOT_Y_OR_Z;

    or FinalC (hex[2], W_OR_X_OR_NOT_Y_OR_Z);

    //D = (~X&Y)|(~X&~Z)|(X&~Y&Z)|(Y&~Z)|W
    wire NOT_X_AND_Y;
    wire NOT_X_AND_NOT_Z;
    wire X_AND_NOT_Y_AND_Z;

    and and1D (NOT_X_AND_Y, 
    NOT_X, 
    Y);
    and and2D (NOT_X_AND_NOT_Z,
    NOT_X, 
    NOT_Z);
    and and3D (X_AND_NOT_Y_AND_Z,
    X,
    NOT_Y,
    Z);
    or finalD (hex[3], 
    NOT_X_AND_Y, 
    NOT_X_AND_NOT_Z, 
    X_AND_NOT_Y_AND_Z,
    W);

    //E = (~W&~X&~Y&~Z)|~W&~X&Y&~Z)|(~W&X&Y&~Z)|(W&~X&~Y&~Z)
    wire NOT_W_AND_NOT_X_AND_NOT_Y_AND_NOT_Z;
    wire NOT_W_AND_NOT_X_AND_Y_AND_NOT_Z;
    wire NOT_W_AND_X_AND_Y_AND_NOT_Z;
    wire W_AND_NOT_X_AND_NOT_Y_AND_NOT_Z;

    and and1E (NOT_W_AND_NOT_X_AND_NOT_Y_AND_NOT_Z, 
    NOT_W,
    NOT_X, 
    NOT_Y,
    NOT_Z);
    and and2E (NOT_W_AND_NOT_X_AND_Y_AND_NOT_Z,
    NOT_W,
    NOT_X,
    Y, 
    NOT_Z);
    and and3E (NOT_W_AND_X_AND_Y_AND_NOT_Z, 
    NOT_W,
    X, 
    Y, 
    NOT_Z);
    and and4E (W_AND_NOT_X_AND_NOT_Y_AND_NOT_Z, 
    W, 
    NOT_X,
    NOT_Y,
    NOT_Z);
    or finalE (hex[4], 
    NOT_W_AND_NOT_X_AND_NOT_Y_AND_NOT_Z,
    NOT_W_AND_NOT_X_AND_Y_AND_NOT_Z,
    NOT_W_AND_X_AND_Y_AND_NOT_Z,
    W_AND_NOT_X_AND_NOT_Y_AND_NOT_Z);

    //F = (W|X|Y|~Z)&(W|X|~Y|Z)&(W|X|~Y|~Z)&(W|~X|~Y|~Z)
    wire W_OR_X_OR_Y_OR_NOT_Z;
    wire W_OR_X_OR_NOT_Y_OR_NOT_Z;
    wire W_OR_NOT_X_OR_NOT_Y_OR_NOT_Z;

    or or1F (W_OR_X_OR_Y_OR_NOT_Z, 
    W, 
    X, 
    Y,
    NOT_Z);
    or or2F (W_OR_X_OR_NOT_Y_OR_Z, 
    W, 
    X, 
    NOT_Y,
    Z);
    or or3F (W_OR_X_OR_NOT_Y_OR_NOT_Z, 
    W, 
    X, 
    NOT_Y,
    NOT_Z);
    or or4F (W_OR_NOT_X_OR_NOT_Y_OR_NOT_Z, 
    W, 
    NOT_X,
    NOT_Y,
    NOT_Z);
    and finalF (hex[5],
    W_OR_X_OR_Y_OR_NOT_Z,
    W_OR_X_OR_NOT_Y_OR_Z,
    W_OR_X_OR_NOT_Y_OR_NOT_Z,
    W_OR_NOT_X_OR_NOT_Y_OR_NOT_Z);

    //G = (W|X|Y|Z)&(W|X|Y|~Z)&(W|~X|~Y|~Z)
    wire W_OR_X_OR_Y_OR_Z;

    or or1G (W_OR_X_OR_Y_OR_Z,
    W, 
    X,
    Y, 
    Z);
    or or2G (W_OR_X_OR_Y_OR_NOT_Z,
    W,
    X,
    Y,
    NOT_Z);
    or or3G (W_OR_NOT_X_OR_NOT_Y_OR_NOT_Z,
    W, 
    NOT_X, 
    NOT_Y,
    NOT_Z);
    and finalG (hex[6],
    W_OR_X_OR_Y_OR_Z,
    W_OR_X_OR_Y_OR_NOT_Z,
    W_OR_NOT_X_OR_NOT_Y_OR_NOT_Z);
endmodule

Skip to main content

Forum for Electronics

Forum for Electronics

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals… and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

  • Digital Design and Embedded Programming

  • PLD, SPLD, GAL, CPLD, FPGA Design

You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an alternative browser.

Error (10028): Can’t resolve multiple constant drivers


  • Thread starter

    Pastel


  • Start date

    Oct 28, 2019

Status
Not open for further replies.

  • #1

Hi guys!

It’s been a while since my last post, I had to work on other things.
To summarize: I made a signal generator, 8 channels, using a MAX10 and parallel
DACs, and the first part of the design works fine.
I had timing problems at some point, but after re-reading replies (Thanks FVM!!),
I found out that using a PLL to generate my clocks is a lot better. Basically it
fixed everything.

Now I have another problem that looks like a classical one. I needed to communicate
with the FPGA to ask it to send data by SPI to other devices. I first made a very
simple SPI slave engine. NB: There are verilog SPI engines on the net, but a way
too complicated to grasp at once, so I wanted to build my own brew.

The code is shown below. It operates at a single mode (clock pulse positive, I think
it’s the (0,0) mode). The version below works perfectly well, but it has to receive
32 bit frames only. If for some reason the MCU transfer is interrupted, then the
data frame (shift_reg) will not be empty but invalid. Not a problem if the next frame is exactly
32 bits, because everything would be cleared by shift, but anyway I would like it to be a bit
cleaner, so as soon as I drop the chip select, I would like to set the shift register to 0.

Code Verilog — [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
module inspi (
leds,
chip_id,
miso, mosi, clk, cs
);
output reg[3:0] chip_id; // This will get the address of the slave devices
output reg[5:0] leds; // LEDs to check the functionality
output reg miso; // As this is a slave, only MISO is output
input mosi;
input clk;
input cs;
// Internal variables
reg[31:0] shift_reg; // Register to receive the MOSI bits
// Initialization
initial begin
chip_id <= ‘hF; // Set the address of the external chips to F (none selected)
shift_reg <= 0;
end
// At every clock, shift and add the current MOSI bit
always@(posedge clk) begin
shift_reg = shift_reg << 1;
if(mosi == 1) begin
shift_reg <= shift_reg+1;
end
end
// At end of transfer, CS goes high. Return the LEDs status and chip IDs
// received by SPI. All other bits are ignored for the time being.
always@(posedge cs) begin
leds <= shift_reg[5:0];
chip_id = shift_reg[27:24];
end
// At negative edge of CS, we know that the transfer is about to happen.
// Set the shift register to 0.
always@(negedge cs) begin
// shift_reg <= 0;
end
endmodule

So basically:
1. On rising edge of the clock, I shift the register left, and add one data bit on
the right.
2. When cs goes high, it means that the transfer is finished, so I output some
parts of the frame. Leds is an array of 6 leds. This works fine. When I receive
a 32 bit frame, I take the last 6 bits and send them to the LEDs. I also have
15 SPI devices driven by the FPGA. I receive the chip id externally and can verify
with the scope that the right bit has been dropped.
3. When the cs goes low, it means that I’m going to receive data. I would like to
clear the shift_reg for a new transfer, but I get this error:

Error (10028): Can’t resolve multiple constant drivers for net «shift_reg[26]» at inspi.sv(35)

Not only shift_reg[26], I get one error like this per bit.

I have tried to google for this error, and found many replies, but I still don’t
understand the problem. The shift_reg is accessed at different events, so I don’t
understand where there could be a clash.
Could anybody (try to) explain me what’s wrong and how to fix it?
NB: when compiled as shown below, it works. The problem arises when I uncomment
the // shift_reg <=0; line.

NB: I have also checked the similar issues on this forum, but apparently everybody is
using VHDL.

Thanks for any hint!

Pastel

  • #2

Advanced Member level 4

Joined
Jul 9, 2010
Messages
1,272
Helped
458
Reputation

916

Reaction score
434
Trophy points
1,363
Location

Sweden

Activity points

9,876


Only drive signals from one process block.
Use as few clocks as possible. In this case only use clk as a clock, and detect the cs edges inside the «always@(posedge clk)» process block.

Don’t set the lowest bit by doing «shift_reg <= shift_reg+1;» even if you «know» that the lowest bit is zero.
That is fine for software where such an addition costs nothing, but you don’t want an adder for this in hardware.
You should not assume that the tool is smart enough to know that the lowest bit is zero before the addition, so only the lowest bit is affected by the operation.
In hardware, if you want to set the lowest bit, just do it. Why add one to the whole 32-bit register?

  • #3

Hello!

Thanks for your reply.
Yes, indeed, using a 32 bit adder was a bit too much.
For those who may have the same problem, I changed the always@(posedge clk) like this:


Code Verilog - [expand]
1
2
3
4
always@(posedge clk) begin
    shift_reg <= shift_reg << 1;
    shift_reg[0] <= mosi;
end

One question about your comment:

Use as few clocks as possible. In this case only use clk as a clock, and detect the cs edges inside
the «always@(posedge clk)» process block.

I wasn’t aware I was using more than one clock (called clk) in my code. Do you mean that as soon
as you have an always@(posedge sig) block, the signal sig is considered as a clock?

Now one problem:
The clock will happen only if CS is already low and stop before goes back to high. So if I test CS inside
of the always block, there is no way I will get an edge on CS, it will always be low.

Now I know that I can say always@(posedge clk or negedge cs), but isn’t this equivalent to what I have
already written? I tried and it works, but it also worked before.


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
always@(posedge clk or posedge cs) begin
        if(cs == 1) begin
            leds <= shift_reg[5:0];
            chip_id = shift_reg[27:24];
        end
        else begin
            shift_reg <= shift_reg << 1;
            shift_reg[0] <= mosi;
        end
    end

Beside this, I need to do something on falling edge of CS (reset the shift register) and also on rising
edge of cs (output what I need from the SPI frame). And always@(posedge clk or negedge cs or posedge cs)
doesn’t compile.
To fix this, I tried to define a pcs (for positive cs, active high) as ~cs.
Now always@(posedge clk or posedge pcs or posedge cs) compiles fine, but it doesn’t work anymore
(the LEDs are not lit anymore as they used to be).

Here is the whole (non working) code: (I found the «wire pcs = ~cs;» trick on the net)


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module inspi (
    leds,
    chip_id,
    miso, mosi, clk, cs
);
    output reg[3:0] chip_id;
    output reg[5:0] leds;
    output reg miso;
    input mosi;
    input clk;
    input cs;
 
    reg[31:0]   shift_reg;
    wire pcs = ~cs;
    
    initial begin
        chip_id <= 'hF;
        shift_reg <= 0;
    end
 
    always@(posedge clk or posedge pcs or posedge cs) begin
        if(pcs == 1) begin
            shift_reg <= 0;
        end
        else if(cs == 1) begin
            leds <= shift_reg[5:0];
            chip_id = shift_reg[27:24];
        end
        else begin
            shift_reg <= shift_reg << 1;
            shift_reg[0] <= mosi;
        end
    end
endmodule

Thanks for any hint!

Pastel

  • #4

Advanced Member level 4

Joined
Jul 9, 2010
Messages
1,272
Helped
458
Reputation

916

Reaction score
434
Trophy points
1,363
Location

Sweden

Activity points

9,876


Ok, now I see that clk is your SPI clock from the master.
I suggest that you use some other high speed clock as your only clock in the whole design and treat all SPI signals as normal I/O.
Everything is much easier with everything in one clock domain. It also solves your problem with no clock when CS is inactive.

The «master clock» must have a higher frequency the frequency than the SPI clock.
I suggest at least 8 times higher for an SPI slave to give margin for synchronization registers on all inputs. Use 50 MHz, 100 MHz or whatever you have available (or create with a PLL).
Clock all SPI inputs via 2 registers before using them to avoid metastability problems.
Try to minimize the number of clocks. Only one clock in the whole design is nice.

  • #5

Hello!

Thanks for your reply.
Yes, indeed, using a 32 bit adder was a bit too much.
For those who may have the same problem, I changed the always@(posedge clk) like this:


Code Verilog - [expand]
1
2
3
4
always@(posedge clk) begin
    shift_reg <= shift_reg << 1;
    shift_reg[0] <= mosi;
end

Ugh, why use two lines do the same thing that can be done in one line. I also think the one line is easier to see is a shift register (at least to my hardware centric brain).


Code Verilog - [expand]
1
2
3
4
always @ (posedge clk) begin
  shift_reg <= {shift_reg, mosi};  // a shift reg, Verilog doesn't give a hoot about the 33-bits getting loaded into the 32-bit value, though you will get warnings about this
  shift_reg <= {shift_reg[30:0], mosi};  // if you need to want to get rid of the warning above.
end

— — — Updated — — —

Ok, now I see that clk is your SPI clock from the master.
I suggest that you use some other high speed clock as your only clock in the whole design and treat all SPI signals as normal I/O.
Everything is much easier with everything in one clock domain. It also solves your problem with no clock when CS is inactive.

The «master clock» must have a higher frequency the frequency than the SPI clock.
I suggest at least 8 times higher for an SPI slave to give margin for synchronization registers on all inputs. Use 50 MHz, 100 MHz or whatever you have available (or create with a PLL).
Clock all SPI inputs via 2 registers before using them to avoid metastability problems.
Try to minimize the number of clocks. Only one clock in the whole design is nice.

Using the SPI clock as a true clock, is sometimes required….
I worked on a design that had no clocks running until the external PLL was programmed. The processor used SPI to command the FPGA to program the PLL. The SPI clock was the only clock running in the system besides the processors internal osc after boot up (FPGA did not get that clock).

— — — Updated — — —

The use of posedge cs is probably going to result in non-optimal code being generated to be able to asynhronously load the values leds and chip_id.

You should not use such coding as the second posedge or negedge should only be used as an asynchronous reset/set with a static constant value being assigned to the FFs produced by synthesis. This is not software and this language may look like C syntax, but is not C.

Uh, wire pcs = ~cs; isn’t some trick. It’s perfectly valid Verilog code with a continuous assignment done as part of the declaration of the wire. If someone else referred to it as a trick then they need to read the LRM.

Also as you are mixing multiple different signals into a single always block you are running into a bunch of problems as you need all those extra posedge terms to get the simulation to do what you want. Ever consider that the always blocks should only have the FFs necessary to implement one specific function. e.g. the shfit_reg should only be in a single always block all by itself. The leds should be in it’s own separate always block or may with only one other signal chip_id as they share the same common cs==1 statement.

initial blocks should not be used in synthesizable code, they may or may not be synthesized depending on the FPGA and the tools used. They absolutely won’t synthesize in ASICs and are ignored, if you design requires a initial value to work then you absolutely need to have a reset of some sort (i.e like the CS == 1’b1) to initialize those signals.

…and that if (cs == 1) statement…synthesis (depending on the tool) will report comparing between a 32-bit and a 1-bit it is better to use either if (cs == 1’b1) or preferably if (cs).

  • #6

Hello!

Thanks for your replies.
I changed the code as you suggested (shift_reg <= {shift_reg[30:0], mosi};)

Indeed, by processing many different edges, the code became a real mess,
and everytime I tried to implement initialization, I got compilation errors.
So I rewrote another version as suggested by std_match. It’s a kind of state
machine that only depends on the system clock and the SPI inputs (which are
at a very low frequency compared to the system, 10MHz, vs 100).
In the always@(posedge sysclock), I keep track of the values of spi_clock
and spi_cs by using 2 internal variables, m_spi_cs and m_spi_clk.

It looks more or less like this. There is no error like I used to have
(can’t resolve multiple constant drivers), and it seems to work fine.
I’m not sure that’s the most efficient way to do it, but at least it works,
and now the shift register is initialized before filling it. I’m going to
add a bit counter and a status report, possibly a 1 bit error report
if the number of bits is wrong.

And I will now implement the master SPI which communicates with board
devices, sending the contents of what has been received from SPI slave.

Anyway thanks again for your replies which were really helpful, and feel free
to comment if you have time.


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
always@(posedge sysclock) begin
    if(spi_cs != m_spi_cs) begin        //  There was a change on cs
        m_spi_cs <= spi_cs;             //  Store the new cs state
        if(spi_cs) begin                //  Chip select had a rising edge
            leds <= shift_reg[5:0];     //  Output the leds status
            chip_id = shift_reg[27:24]; //  Output the chip ID
        end
        else begin                      //  Chip select had a falling edge
            shift_reg <= 0;             //  Reset the shift register
        end
    end
    if(spi_clk != m_spi_clk) begin      //  The polarity of spi clock has just changed
        m_spi_clk <= spi_clk;           //  Store the new polarity
        if(spi_clk) begin               //  The observed change was a rising edge
            shift_reg <= {shift_reg[30:0], mosi};
        end
    end
end

Pastel

Status
Not open for further replies.
  • Digital Design and Embedded Programming

  • PLD, SPLD, GAL, CPLD, FPGA Design

  • This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.

Понравилась статья? Поделить с друзьями:
  • Error 1002 could not make a websocket connection
  • Error 1002 bbb
  • Error 10013 0x0000271d
  • Error 10012 mi home
  • Error 10010 heroes and generals решение