Изучаю шину авалон, написал тестовый проект из трех мастеров, одновременно доступающихся к одному подчиненному устройству. При помощи вкладки "Generate" в qsys сгенерил тестбенч для модельсима. Прогнал 2 случая:
1. Все мастера имеют одинаковый приоритет доступа к подчиненному устройству (==1). Получил картинку eq.jpeg.
По ней видно, что по событию sec_pulse три мастера начинают одновременно доступаться к шине, арбитр разруливает это путем удерживания сигнала waitrequest.
вопрос: Почему для нулевого мастера тоже получается задержка за счет waitrequest? Если на шине оставить только одного мастера, то waitrequest падает в момент выставления сигнала write_data, если несколько мастеров - то через цикл. В этот цикл разрешается арбитраж на шине?
2. ПРи помощи qsys поставл мастеру_1 приоритет 9 (остальные два имеют приоритет 1). Ожидал, что арбитраж выиграет мастер_1. Однако симуляция показала, что по прежнему первая транзакция идет от мастера_0 (файл neq.jpeg)
вопрос: почему мастер_1 не начинает первым транзакцию?
вопрос: на диаграмме видно, что сигнал waitrequest для мастер_2 продлился еще на один такт (те между окончанием передачи мастер_1 и началом передачи мастер_2 вставился холостой цикл, чего не было на eq.jpeg. С чем это связано?
Если это важно: квартус версии 13.0 (Linux), модельсим 10.1d
Спасибо!
Приложения:
1. Код мастера шины
Код
module mmbus_master
#(
parameter REVERSE = 0,
parameter DIGIT_NUM = 0
)
(
input bit clk, reset_n, waitrequest,
output bit write,
output bit[31:0] write_data,
output bit[3:0] byte_select,
output bit[31:0] address
);
// pulse every 1 sec
bit[31:0] divider;
bit sec_pulse;
always_ff @(posedge clk) begin
if (!reset_n)
divider <= '0;
else if (divider < 50)
divider <= divider + 1'b1;
else
divider <= '0;
end
assign sec_pulse = divider == 50;
// Increment digit
bit[3:0] digit;
always_ff @(posedge clk) begin
if (!reset_n)
digit <= '0;
else if (sec_pulse) begin
if (REVERSE) begin
if (digit == 0) digit <= 9;
else digit <= digit - 1'b1;
end
else begin
if (digit == 9) digit <= '0;
else digit <= digit + 1'b1;
end
end
end
// Write digit to bus
typedef enum
{
IDLE,
WAIT
} EState;
EState eWriteState;
always_ff @(posedge clk) begin
if (!reset_n)
eWriteState <= IDLE;
else begin
unique case (eWriteState)
IDLE: if (sec_pulse) begin
address <= 32'h5044;
write_data <= digit << 8*DIGIT_NUM;
write <= '1;
byte_select <= 1'b1 << DIGIT_NUM;
eWriteState <= WAIT;
end
WAIT: if (!waitrequest) begin
address <= '0;
write_data <= '0;
write <= '0;
byte_select <= '0;
eWriteState <= IDLE;
end
endcase
end
end
endmodule
#(
parameter REVERSE = 0,
parameter DIGIT_NUM = 0
)
(
input bit clk, reset_n, waitrequest,
output bit write,
output bit[31:0] write_data,
output bit[3:0] byte_select,
output bit[31:0] address
);
// pulse every 1 sec
bit[31:0] divider;
bit sec_pulse;
always_ff @(posedge clk) begin
if (!reset_n)
divider <= '0;
else if (divider < 50)
divider <= divider + 1'b1;
else
divider <= '0;
end
assign sec_pulse = divider == 50;
// Increment digit
bit[3:0] digit;
always_ff @(posedge clk) begin
if (!reset_n)
digit <= '0;
else if (sec_pulse) begin
if (REVERSE) begin
if (digit == 0) digit <= 9;
else digit <= digit - 1'b1;
end
else begin
if (digit == 9) digit <= '0;
else digit <= digit + 1'b1;
end
end
end
// Write digit to bus
typedef enum
{
IDLE,
WAIT
} EState;
EState eWriteState;
always_ff @(posedge clk) begin
if (!reset_n)
eWriteState <= IDLE;
else begin
unique case (eWriteState)
IDLE: if (sec_pulse) begin
address <= 32'h5044;
write_data <= digit << 8*DIGIT_NUM;
write <= '1;
byte_select <= 1'b1 << DIGIT_NUM;
eWriteState <= WAIT;
end
WAIT: if (!waitrequest) begin
address <= '0;
write_data <= '0;
write <= '0;
byte_select <= '0;
eWriteState <= IDLE;
end
endcase
end
end
endmodule
2. Код подчиненного устройства
Код
function [6:0]bin2seg(input bit [3:0] digit);
unique case (digit)
0: bin2seg = 7'b1000000;
1: bin2seg = 7'b1111001;
2: bin2seg = 7'b0100100;
3: bin2seg = 7'b0110000;
4: bin2seg = 7'b0011001;
5: bin2seg = 7'b0010010;
6: bin2seg = 7'b0000010;
7: bin2seg = 7'b1111000;
8: bin2seg = 7'b0000000;
9: bin2seg = 7'b0010000;
default: bin2seg = 7'b1111111;
endcase
endfunction
module seg_driver
(
input bit clk, reset_n, write, chipselect,
input bit [3:0] byteselect,
input bit[31:0] write_data,
output bit[6:0] seg0, seg1, seg2, seg3
);
bit[31:0] value;
always_ff@(posedge clk) begin
if (!reset_n)
value <= '0;
else if (chipselect && write)
//value <= write_data;
if (byteselect[0]) value[7:0] <= write_data[7:0];
if (byteselect[1]) value[15:8] <= write_data[15:8];
if (byteselect[2]) value[23:16] <= write_data[23:16];
if (byteselect[3]) value[31:24] <= write_data[31:24];
end
assign seg0 = bin2seg(value[3:0]);
assign seg1 = bin2seg(value[11:8]);
assign seg2 = bin2seg(value[19:16]);
assign seg3 = bin2seg(value[27:24]);
endmodule
unique case (digit)
0: bin2seg = 7'b1000000;
1: bin2seg = 7'b1111001;
2: bin2seg = 7'b0100100;
3: bin2seg = 7'b0110000;
4: bin2seg = 7'b0011001;
5: bin2seg = 7'b0010010;
6: bin2seg = 7'b0000010;
7: bin2seg = 7'b1111000;
8: bin2seg = 7'b0000000;
9: bin2seg = 7'b0010000;
default: bin2seg = 7'b1111111;
endcase
endfunction
module seg_driver
(
input bit clk, reset_n, write, chipselect,
input bit [3:0] byteselect,
input bit[31:0] write_data,
output bit[6:0] seg0, seg1, seg2, seg3
);
bit[31:0] value;
always_ff@(posedge clk) begin
if (!reset_n)
value <= '0;
else if (chipselect && write)
//value <= write_data;
if (byteselect[0]) value[7:0] <= write_data[7:0];
if (byteselect[1]) value[15:8] <= write_data[15:8];
if (byteselect[2]) value[23:16] <= write_data[23:16];
if (byteselect[3]) value[31:24] <= write_data[31:24];
end
assign seg0 = bin2seg(value[3:0]);
assign seg1 = bin2seg(value[11:8]);
assign seg2 = bin2seg(value[19:16]);
assign seg3 = bin2seg(value[27:24]);
endmodule