I'm trying to write a Verilog module and a section of code is something like this:
input wire [7:0] data_in
reg [199:0] buffer;
.
.
.
always @(posedge clk) begin
buffer[119:112] <= data_in; //place data_in to a specific part of buffer
buffer <= buffer << 8; //logical left shift the buffer
end
but the problem is the first line of always block is ignored (after each clk posedge)! in another word, data_in
doesn't place in buffer[119:112]
and buffer always remain 200'b0
!
the first question is what is the the cause? and the second question is how can i do that what i want?
You have to look at this from the point of view of the hardware design. always @(posedge clk)
represents a flop. The only thing it does, is saving values at the clock edge. The data itself is prepared with some combinatorial logic before. In your case, assigning data_in to some bits as well, as the shift are the parts of the combinatorial world.
Saying that, you can write your model as the following:
reg [199:0] buffer_in, buffer_shifted;
reg [7:0] data_in;
reg clk;
always @* begin
buffer_in = buffer;
buffer_in[119:112] = data_in;
buffer_shifted = buffer_in << 8;
end
always @(posedge clk)
buffer <= buffer_shifted;
First two statements in the above always block are really the same as the following
buffer_in = {buffer[199:120], data_in[7:0], buffer[111:0]};
And now you can collapse all of this and even move it to the statement which models the flop itself. The nature of these statements will still be the same, combinatorial logic, but you can get rid of intermediate variables:
always @(posedge clk)
buffer <= {buffer[199:120], data_in[7:0], buffer[111:0]} << 8;
Adding a testcase
module top;
reg [7:0] data_in;
reg clk;
reg [199:0] buffer;
always @(posedge clk)
buffer <= {buffer[199:120], data_in[7:0], buffer[111:0]} << 8;
initial begin
clk = 0;
buffer = 0;
data_in = 4'h1;
#13
data_in = 4'h2;
end
always
#5 clk = ~clk;
initial
#20 $finish;
always @*
$display("%3t> %h_%h", $time, buffer[199:112], buffer[111:0]);
endmodule