Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Бывает, схема к конвейризации не была готова, т.к. есть обратная связь, в связи с задержкой на такт(ы), начала неправильно работать.
Если честно, AXI4-Stream я никогда не использовал. Если кто-то использовал оба интерфейса, буду признателен, если поделитесь сравнением и впечатлениями.
Гораздо нагляднее, чем городить?: (?: (?: (?: (? :)))).
assign new_data_c = ()? {,} :
()? {,} :
{,};
if ( startofpacket_d1 )
new_data_c = { data_d1[1:0], data_i[7:4], data_d1[7:6] };
else if ( startofpacket_o )
new_data_c = {data_d2[5:2], data_d1[3:0]};
else
new_data_c = data_d1;
typedef struct packed {
logic [7:0] a;
logic [7:0] b;
logic [7:0] c;
} s_t;
s_t s_comb;
s_t s_input;
s_t s_delayed; // задержанная на несколько тактов s_input
// подменяем в s_delayed только поле c
always_comb
begin
s_comb = s_delayed;
if( some_flag )
s_comb.c = 8'd42;
end
По положительному фронту (так называемый posedge) clk_i на вход модуля были поданы 4 числа: 4, 8, 15 и 23. На следующий положительный фронт в регистре no_pipe_res_o появился ответ 50
Читаю про D-триггер, там речь о том, что по переднему фронту С он заносит значение в первый Т триггер и после падения С уже подается на выход.
module some_example(
input clk_i,
input [7:0] a_i,
input [7:0] b_i,
output logic [7:0] no_pipe_res_o
);
logic [7:0] a_sync;
logic [7:0] b_sync;
logic [7:0] c;
always_ff @( posedge clk_i )
begin
a_sync <= a_i;
b_sync <= b_i;
end
assign c = a_sync + b_sync;
always_ff @( posedge clk_i )
begin
no_pipe_res_o <= c;
end
endmodule


module some_example_2(
input clk_i,
input [7:0] a_i,
input [7:0] b_i,
output logic [7:0] no_pipe_res_o
);
always_ff @( posedge clk_i )
begin
no_pipe_res_o <= a_i + b_i;
end
endmodule
module no_pipe_example(
input clk_i,
input [7:0] x_1,
input [7:0] x_2,
input [7:0] x_3,
input [7:0] x_4,
output logic [7:0] no_pipe_res_o
);
// no pipeline
always @( posedge clk_i )
no_pipe_res_o <= ( x_1 + x_2 ) + ( x_3 + x_4 );
endmodule

always_ff @( posedge clk_i )?initial
begin
#100;
x_1 = 4;
x_2 = 8;
...
end
initial
begin
@( posedge tb_clk )
x_1 <= 4;
x_2 <= 8;
...
end
module gen_x(
input clk_i,
input rst_i,
output logic [7:0] x_1_o,
output logic [7:0] x_2_o,
output logic [7:0] x_3_o,
output logic [7:0] x_4_o
);
always @( posedge clk_i or posedge rst_i )
if( rst_i )
begin
x_1_o <= '0;
x_2_o <= '0;
x_3_o <= '0;
x_4_o <= '0;
end
else
begin
x_1_o <= x_1_o + 8'd1;
x_2_o <= x_2_o + 8'd3;
x_3_o <= x_3_o + 8'd5;
x_4_o <= x_4_o + 8'd7;
end
endmodule
module top(
input clk_i,
input rst_i,
output logic [7:0] no_pipe_res_o
);
logic [7:0] x_1_w;
logic [7:0] x_2_w;
logic [7:0] x_3_w;
logic [7:0] x_4_w;
gen_x gen_x(
.clk_i ( clk_i ),
.rst_i ( rst_i ),
.x_1_o ( x_1_w ),
.x_2_o ( x_2_w ),
.x_3_o ( x_3_w ),
.x_4_o ( x_4_w )
);
no_pipe_example no_pipe(
.clk_i ( clk_i )
.x_1 ( x_1_w ),
.x_2 ( x_2_w ),
.x_3 ( x_3_w ),
.x_4 ( x_4_w ),
.no_pipe_res_o ( no_pipe_res_o )
);
module top_tb;
logic clk;
logic rst;
initial
begin
clk = 1'b0;
forever
begin
#10;
clk = !clk;
end
end
initial
begin
rst = 1'b0;
#2;
rst <= 1'b1;
#2;
rst <= 1'b0;
end
// ********** TEST 0 ***********
logic [7:0] test0_res_w;
logic [7:0] test0_x_1_w;
logic [7:0] test0_x_2_w;
logic [7:0] test0_x_3_w;
logic [7:0] test0_x_4_w;
gen_x gen_x(
.clk_i ( clk ),
.rst_i ( rst ),
.x_1_o ( test0_x_1_w ),
.x_2_o ( test0_x_2_w ),
.x_3_o ( test0_x_3_w ),
.x_4_o ( test0_x_4_w )
);
no_pipe_example no_pe_0(
.clk_i ( clk ),
.x_1 ( test0_x_1_w ),
.x_2 ( test0_x_2_w ),
.x_3 ( test0_x_3_w ),
.x_4 ( test0_x_4_w ),
.no_pipe_res_o ( test0_res_w )
);
// ********** TEST 1 ***********
logic [7:0] test1_res_w;
logic [7:0] test1_x_1_w;
logic [7:0] test1_x_2_w;
logic [7:0] test1_x_3_w;
logic [7:0] test1_x_4_w;
initial
begin
test1_x_1_w = '0;
test1_x_2_w = '0;
test1_x_3_w = '0;
test1_x_4_w = '0;
for( int i = 1; i < 10; i++ )
begin
@( posedge clk );
test1_x_1_w <= i*1;
test1_x_2_w <= i*3;
test1_x_3_w <= i*5;
test1_x_4_w <= i*7;
end
end
no_pipe_example no_pe_1(
.clk_i ( clk ),
.x_1 ( test1_x_1_w ),
.x_2 ( test1_x_2_w ),
.x_3 ( test1_x_3_w ),
.x_4 ( test1_x_4_w ),
.no_pipe_res_o ( test1_res_w )
);
// ********** TEST 2 ***********
logic [7:0] test2_res_w;
logic [7:0] test2_x_1_w;
logic [7:0] test2_x_2_w;
logic [7:0] test2_x_3_w;
logic [7:0] test2_x_4_w;
initial
begin
test2_x_1_w = '0;
test2_x_2_w = '0;
test2_x_3_w = '0;
test2_x_4_w = '0;
#10;
for( int i = 1; i < 10; i++ )
begin
test2_x_1_w = i*1;
test2_x_2_w = i*3;
test2_x_3_w = i*5;
test2_x_4_w = i*7;
#20;
end
end
no_pipe_example no_pe_2(
.clk_i ( clk ),
.x_1 ( test2_x_1_w ),
.x_2 ( test2_x_2_w ),
.x_3 ( test2_x_3_w ),
.x_4 ( test2_x_4_w ),
.no_pipe_res_o ( test2_res_w )
);
endmodule

Мои все примеры на SystemVerilog)А в чем разница, если в двух словах? Я вот только с приведением типов столкнулся.
module testbench();
reg tb_clk;
reg [7:0] x_1,x_2,x_3,x_4;
wire [7:0] res, res_pipe;
no_pipe_example ex1(tb_clk,x_1,x_2,x_3,x_4,res);
pipe_example ex2(tb_clk,x_1,x_2,x_3,x_4,res_pipe);
initial
begin
$dumpfile("bench.vcd");
$dumpvars(0,testbench);
tb_clk = 0;
#50;
x_1 = 4;
x_2 = 8;
x_3 = 15;
x_4 = 23;
#100;
tb_clk = 1;
#100;
tb_clk = 0;
#100;
x_1 = 0;
x_2 = 0;
x_3 = 0;
x_4 = 0;
tb_clk = 1;
#100;
tb_clk = 0;
#100;
tb_clk = 1;
#100;
tb_clk = 0;
end
initial begin
end
endmodule
module pipe_example(
input clk_i,
input [7:0] x_1,
input [7:0] x_2,
input [7:0] x_3,
input [7:0] x_4,
output logic [7:0] pipe_res_o
);
// pipeline
logic [7:0] s1 = 0;
logic [7:0] s2 = 0;
always @( posedge clk_i )
begin
s1 <= ( x_1 + x_2 );
s2 <= ( x_3 + x_4 );
pipe_res_o <= s1 + s2;
end
endmodule

initial
begin
tb_clk = 1'b0;
forever
begin
#100;
tb_clk = !tb_clk;
end
end
initial
begin
@( posedge tb_clk );
x_1 <= 4;
x_2 <= 8;
x_3 <= 15;
x_4 <= 23;
@( posedge tb_clk );
x_1 <= 0;
x_2 <= 0;
x_3 <= 0;
x_4 <= 0;
end
Пару слов о конвейерах в FPGA