Iam trying to write a SPI master module by myself to learn FPGA-Verilog efficiently. Here is the spi_master module:
module spi_master(
output [15:0] tx_data,
input [15:0] rx_data,
output mosi,
input miso,
output cs,
output sck,
input start
);
reg [15:0] tx_data;
reg [3:0] tx_counter;
reg [3:0] rx_counter;
wire start;
reg cs;
reg mosi;
wire miso;
wire sck;
initial begin
tx_counter [3:0] = 4'b0;
rx_counter [3:0] = 4'b0;
end
always @(negedge sck) begin
if (cs == 0 && tx_counter != 4'b1111) begin
#(5) mosi <= tx_data[tx_counter];
#(6) tx_counter <= tx_counter + 4'b1;
end
else if(cs == 0 && tx_counter == 4'b1111) begin
#(5) cs <= 1'b1;
end
else if (cs == 1 && tx_counter == 0) begin
#(5) cs <= 1'b0;
end
end
always @(posedge sck) begin
if (cs == 0 && tx_counter <= 4'b1111 && tx_counter >= 4'b0001) begin
#1 rx_data[rx_counter] <= miso;
#2 rx_counter <= rx_counter + 4'b1;
end
end
endmodule
And here is the test module;
`include "spi_master.v"
module spi_master_tb(
);
reg clk;
reg start;
reg mosi;
wire miso;
reg cs;
reg sck;
reg [15:0] tx_data;
initial begin
clk = 0;
tx_data = 16'hF0AA;
#20 start = 1'b1;
#1000 $finish;
sck = 0;
end
always begin
#1 clk = ~clk;
end
always @(start) begin
#10 sck = ~sck; // divided clk by CLK_DIVIDER
end
spi_master SPI_block(
tx_data,
rx_data,
mosi,
miso,
cs,
sck,
start
);
endmodule
the spi_master module can be compiled without error but when I try testbench I get this error:
ERROR:HDLCompiler:1660 - "C:/Users/aozel/Desktop/FPGA Projects/myModule/../Test2/spi_master.v" Line 74: Procedural assignment to a non-register rx_data is not permitted, left-hand side should be reg/integer/time/genvar
Why is this? Also when I add: reg [15:0] rx_data;
to the spi_master module this time I get this:
ERROR:HDLCompiler:661 - "C:/Users/aozel/Desktop/FPGA Projects/myModule/../Test2/spi_master.v" Line 24: Non-net port rx_data cannot be of mode input
Why is this happening? I ve read somewhere that says never set inputs as regs. But editor throws exact opposite suggestions. So, to sum up, Are there basic rules for port settings in Verilog? How should I start?
And secondly, I really did not understand why we should not use registers as inputs. Why is that? Where will I store inputs? How will I read them? I think I have to use registers for inputs which is not considered as interrupts. Can someone explain it? I d really appreciate.
Best Answer
Just to start out, at the top of your
spi_master
module, you haverx_data
declared as an input. Then at line 74 (I assume, I didn't count) you haveIf
rx_data
is an input tospi_master
, thenspi_master
should not be assigning any values to it. The values should be assigned by the instantiating module (or test bench) and given to thespi_master
instance as inputs.If the intent is that your receive data on the
miso
line (because you're the master) and then make it available in a parallel word to the code where your module is instantiated, thenrx_data
should be an output from this module.I also see an issue where you have
tx_data
andmosi
both declared as outputs. If the intent is to taketx_data
in parallel, and convert it to serial data on themosi
line, thentx_data
should be an input to your module.You can't make an input a reg because you aren't going to assign to it in the module where it is an input.
You will assign to it in the higher-level module. Whether you declare it as a reg or not in that module depends on how it's assigned to. If it's assigned in an
always
block, it must be a reg. If it's assigned in anassign
statement, or it's the output from another module, then it must not be a reg.Generally, I'd say you need to think more carefully about what's an output and what's an input to your module. Think about if you were drawing a block diagram of your design, and each instance of your module were represented by a block. If the the signal would be flowing out of the block, that's an output. If the signal would be flowing in to the block, that's an input.