diff --git a/Labs/12. Peripheral units/PS2Receiver.sv b/Labs/12. Peripheral units/PS2Receiver.sv new file mode 100644 index 0000000..6703b4e --- /dev/null +++ b/Labs/12. Peripheral units/PS2Receiver.sv @@ -0,0 +1,93 @@ +module PS2Receiver( + input logic clk, + input logic kclk, + input logic kdata, + output logic [15:0] keycodeout, + output keycode_valid + ); + + logic flag; + logic [3:0] flag_shift; + logic kclkf, kdataf; + logic [3:0] cnt; + + assign keycode_valid = flag_shift[0] && !flag_shift[2]; + + initial begin //for tb + cnt = 0; + keycodeout = 0; + flag_shift = 0; + flag = 0; + end + +debouncer debounce( + .clk(clk), + .I0(kclk), + .I1(kdata), + .O0(kclkf), + .O1(kdataf) +); +always@(posedge clk) begin + flag_shift <= (flag_shift << 1) + flag; +end + +always_ff @(negedge(kclkf))begin + case(cnt) + 0:if(keycodeout != 16'hE000)keycodeout <= 0;//Start bit + 1:keycodeout[0]<=kdataf; + 2:keycodeout[1]<=kdataf; + 3:keycodeout[2]<=kdataf; + 4:keycodeout[3]<=kdataf; + 5:keycodeout[4]<=kdataf; + 6:keycodeout[5]<=kdataf; + 7:keycodeout[6]<=kdataf; + 8:keycodeout[7]<=kdataf; + //TODO ADD PARITY CHECK + 9:begin + flag<=1'b1; + if(keycodeout[7:0] == 8'hE0) begin + keycodeout <= {keycodeout[7:0], 8'd0}; + end + end + 10:flag<=1'b0; + default: cnt <= 0; + endcase + if(cnt<=9) cnt<=cnt+1; + else if(cnt==10) cnt<=0; +end + +endmodule + + +module debouncer( + input logic clk, + input logic I0, + input logic I1, + output logic O0, + output logic O1 + ); + + logic [4:0]cnt0, cnt1; + logi Iv0=0,Iv1=0; + logi out0, out1; + + always_ff @(posedge(clk))begin + if (I0==Iv0) begin + if (cnt0==19)O0<=I0; + else cnt0<=cnt0+1; + end + else begin + cnt0<="00000"; + Iv0<=I0; + end + if (I1==Iv1)begin + if (cnt1==19)O1<=I1; + else cnt1<=cnt1+1; + end + else begin + cnt1<="00000"; + Iv1<=I1; + end + end + +endmodule diff --git a/Labs/12. Peripheral units/PS2Receiver.v b/Labs/12. Peripheral units/PS2Receiver.v deleted file mode 100644 index 1c85af2..0000000 --- a/Labs/12. Peripheral units/PS2Receiver.v +++ /dev/null @@ -1,93 +0,0 @@ -module PS2Receiver( - input clk, - input kclk, - input kdata, - output reg [15:0] keycodeout, - output keycode_valid - ); - - reg flag; - reg [3:0] flag_shift; - wire kclkf, kdataf; - reg [3:0]cnt; - - assign keycode_valid = flag_shift[0] && !flag_shift[2]; - - initial begin //for tb - cnt = 0; - keycodeout = 0; - flag_shift = 0; - flag = 0; - end - -debouncer debounce( - .clk(clk), - .I0(kclk), - .I1(kdata), - .O0(kclkf), - .O1(kdataf) -); -always@(posedge clk) begin - flag_shift <= (flag_shift << 1) + flag; -end - -always@(negedge(kclkf))begin - case(cnt) - 0:if(keycodeout != 16'hE000)keycodeout <= 0;//Start bit - 1:keycodeout[0]<=kdataf; - 2:keycodeout[1]<=kdataf; - 3:keycodeout[2]<=kdataf; - 4:keycodeout[3]<=kdataf; - 5:keycodeout[4]<=kdataf; - 6:keycodeout[5]<=kdataf; - 7:keycodeout[6]<=kdataf; - 8:keycodeout[7]<=kdataf; - //TODO ADD PARITY CHECK - 9:begin - flag<=1'b1; - if(keycodeout[7:0] == 8'hE0) begin - keycodeout <= {keycodeout[7:0], 8'd0}; - end - end - 10:flag<=1'b0; - default: cnt <= 0; - endcase - if(cnt<=9) cnt<=cnt+1; - else if(cnt==10) cnt<=0; -end - -endmodule - - -module debouncer( - input clk, - input I0, - input I1, - output reg O0, - output reg O1 - ); - - reg [4:0]cnt0, cnt1; - reg Iv0=0,Iv1=0; - reg out0, out1; - -always@(posedge(clk))begin - if (I0==Iv0)begin - if (cnt0==19)O0<=I0; - else cnt0<=cnt0+1; - end - else begin - cnt0<="00000"; - Iv0<=I0; - end - if (I1==Iv1)begin - if (cnt1==19)O1<=I1; - else cnt1<=cnt1+1; - end - else begin - cnt1<="00000"; - Iv1<=I1; - end - end - -endmodule diff --git a/Labs/12. Peripheral units/hex_digits.sv b/Labs/12. Peripheral units/hex_digits.sv new file mode 100644 index 0000000..7a3c96e --- /dev/null +++ b/Labs/12. Peripheral units/hex_digits.sv @@ -0,0 +1,76 @@ +module hex_digits( + input logic clk_i, rst_i, + input logic [4:0] hex0, // Входной сигнал со значением цифры, выводимой на нулевой (самый правый) индикатор + input logic [4:0] hex1, // Входной сигнал со значением цифры, выводимой на первый индикатор + input logic [4:0] hex2, // Входной сигнал со значением цифры, выводимой на второй индикатор + input logic [4:0] hex3, // Входной сигнал со значением цифры, выводимой на третий индикатор + input logic [4:0] hex4, // Входной сигнал со значением цифры, выводимой на четвертый индикатор + input logic [4:0] hex5, // Входной сигнал со значением цифры, выводимой на пятый индикатор + input logic [4:0] hex6, // Входной сигнал со значением цифры, выводимой на шестой индикатор + input logic [4:0] hex7, // Входной сигнал со значением цифры, выводимой на седьмой индикатор + + output logic [6:0] hex_led, // Выходной сигнал, контролирующий каждый отдельный светодиод индикатора + output logic [7:0] hex_sel // Выходной сигнал, указывающий на какой индикатор выставляется hex_led + ); + localparam pwm 1000 //шим сегментов + + logic [9:0] counter; + logic [4:0] semseg; + logic [7:0] ANreg; + logic [6:0] hex_ledr; + + assign hex_sel = ANreg; + assign hex_led = hex_ledr; + + always_ff @(posedge clk_i) begin + if (rst_i) begin + counter <= 'b0; + ANreg[7:0] <= 8'b11111111; + hex_ledr <= 7'b1111111; + end + else begin + if (counter < pwm) counter <= counter + 'b1; + else begin + counter <= 'b0; + ANreg[1] <= ANreg[0]; + ANreg[2] <= ANreg[1]; + ANreg[3] <= ANreg[2]; + ANreg[4] <= ANreg[3]; + ANreg[5] <= ANreg[4]; + ANreg[6] <= ANreg[5]; + ANreg[7] <= ANreg[6]; + ANreg[0] <= !(ANreg[6:0] == 7'b1111111); + end + case (1'b0) + ANreg[0]: semseg <= hex0; + ANreg[1]: semseg <= hex1; + ANreg[2]: semseg <= hex2; + ANreg[3]: semseg <= hex3; + ANreg[4]: semseg <= hex4; + ANreg[5]: semseg <= hex5; + ANreg[6]: semseg <= hex6; + ANreg[7]: semseg <= hex7; + endcase + case (semseg) + 5'h10: hex_ledr <= 7'b0000001; + 5'h11: hex_ledr <= 7'b1001111; + 5'h12: hex_ledr <= 7'b0010010; + 5'h13: hex_ledr <= 7'b0000110; + 5'h14: hex_ledr <= 7'b1001100; + 5'h15: hex_ledr <= 7'b0100100; + 5'h16: hex_ledr <= 7'b0100000; + 5'h17: hex_ledr <= 7'b0001111; + 5'h18: hex_ledr <= 7'b0000000; + 5'h19: hex_ledr <= 7'b0000100; + 5'h1A: hex_ledr <= 7'b0001000; + 5'h1B: hex_ledr <= 7'b1100000; + 5'h1C: hex_ledr <= 7'b0110001; + 5'h1D: hex_ledr <= 7'b1000010; + 5'h1E: hex_ledr <= 7'b0110000; + 5'h1F: hex_ledr <= 7'b0111000; + default: hex_ledr <= 7'b1111111; + endcase + end + end + +endmodule diff --git a/Labs/12. Peripheral units/hex_digits.v b/Labs/12. Peripheral units/hex_digits.v deleted file mode 100644 index bf37bfb..0000000 --- a/Labs/12. Peripheral units/hex_digits.v +++ /dev/null @@ -1,76 +0,0 @@ -module hex_digits( - input clk_i, rst_i, - input [4:0] hex0, // Входной сигнал со значением цифры, выводимой на нулевой (самый правый) индикатор - input [4:0] hex1, // Входной сигнал со значением цифры, выводимой на первый индикатор - input [4:0] hex2, // Входной сигнал со значением цифры, выводимой на второй индикатор - input [4:0] hex3, // Входной сигнал со значением цифры, выводимой на третий индикатор - input [4:0] hex4, // Входной сигнал со значением цифры, выводимой на четвертый индикатор - input [4:0] hex5, // Входной сигнал со значением цифры, выводимой на пятый индикатор - input [4:0] hex6, // Входной сигнал со значением цифры, выводимой на шестой индикатор - input [4:0] hex7, // Входной сигнал со значением цифры, выводимой на седьмой индикатор - - output [6:0] hex_led, // Выходной сигнал, контролирующий каждый отдельный светодиод индикатора - output [7:0] hex_sel // Выходной сигнал, указывающий на какой индикатор выставляется hex_led - ); - `define pwm 1000 //шим сегментов - - reg [9:0] counter; - reg [4:0] semseg; - reg [7:0] ANreg; - reg [6:0] hex_ledr; - - assign hex_sel = ANreg; - assign hex_led = hex_ledr; - - always @(posedge clk_i) begin - if (rst_i) begin - counter <= 'b0; - ANreg[7:0] <= 8'b11111111; - hex_ledr <= 7'b1111111; - end - else begin - if (counter < `pwm) counter <= counter + 'b1; - else begin - counter <= 'b0; - ANreg[1] <= ANreg[0]; - ANreg[2] <= ANreg[1]; - ANreg[3] <= ANreg[2]; - ANreg[4] <= ANreg[3]; - ANreg[5] <= ANreg[4]; - ANreg[6] <= ANreg[5]; - ANreg[7] <= ANreg[6]; - ANreg[0] <= !(ANreg[6:0] == 7'b1111111); - end - case (1'b0) - ANreg[0]: semseg <= hex0; - ANreg[1]: semseg <= hex1; - ANreg[2]: semseg <= hex2; - ANreg[3]: semseg <= hex3; - ANreg[4]: semseg <= hex4; - ANreg[5]: semseg <= hex5; - ANreg[6]: semseg <= hex6; - ANreg[7]: semseg <= hex7; - endcase - case (semseg) - 5'h10: hex_ledr <= 7'b0000001; - 5'h11: hex_ledr <= 7'b1001111; - 5'h12: hex_ledr <= 7'b0010010; - 5'h13: hex_ledr <= 7'b0000110; - 5'h14: hex_ledr <= 7'b1001100; - 5'h15: hex_ledr <= 7'b0100100; - 5'h16: hex_ledr <= 7'b0100000; - 5'h17: hex_ledr <= 7'b0001111; - 5'h18: hex_ledr <= 7'b0000000; - 5'h19: hex_ledr <= 7'b0000100; - 5'h1A: hex_ledr <= 7'b0001000; - 5'h1B: hex_ledr <= 7'b1100000; - 5'h1C: hex_ledr <= 7'b0110001; - 5'h1D: hex_ledr <= 7'b1000010; - 5'h1E: hex_ledr <= 7'b0110000; - 5'h1F: hex_ledr <= 7'b0111000; - default: hex_ledr <= 7'b1111111; - endcase - end - end - -endmodule diff --git a/Other/FAQ.md b/Other/FAQ.md index ffe1356..b4b9c4b 100644 --- a/Other/FAQ.md +++ b/Other/FAQ.md @@ -101,7 +101,7 @@ endmodule Запрещено использовать процедурное присваивание (присваивание в блоке `always` или `initial`) объектам, не являющимися регистрами. Скорее всего, вы пытались выполнить `b = a;` или `b <= a;` блоке `always`/`initial`, где `b` является проводом. -```Verilog +```SystemVerilog module adder(input a, input b, output c); always @(*) begin c = a ^ b; // ошибка, процедурное присваивание diff --git a/Other/vector_abs/half_divider.v b/Other/vector_abs/half_divider.sv similarity index 53% rename from Other/vector_abs/half_divider.v rename to Other/vector_abs/half_divider.sv index 75be1d4..1e4731b 100644 --- a/Other/vector_abs/half_divider.v +++ b/Other/vector_abs/half_divider.sv @@ -1,6 +1,6 @@ module half_divider( - input [31:0] numerator, - output[31:0] quotient + input logic [31:0] numerator, + output logic [31:0] quotient ); assign quotient = numerator << 1'b1; diff --git a/Other/vector_abs/max_min.v b/Other/vector_abs/max_min.sv similarity index 53% rename from Other/vector_abs/max_min.v rename to Other/vector_abs/max_min.sv index 5b227b4..a04fb07 100644 --- a/Other/vector_abs/max_min.v +++ b/Other/vector_abs/max_min.sv @@ -1,11 +1,11 @@ module max_min( - input [31:0] a, - input [31:0] b, - output reg[31:0] max, - output reg[ 3:0] min + input logic [31:0] a, + input logic [31:0] b, + output logic [31:0] max, + output logic [ 3:0] min ); - always @(*) begin + always_comb @(*) begin if(a > b) begin max = a; min = b; diff --git a/Other/vector_abs/tb.v b/Other/vector_abs/tb.sv similarity index 94% rename from Other/vector_abs/tb.v rename to Other/vector_abs/tb.sv index 3b8c48c..19f4c94 100644 --- a/Other/vector_abs/tb.v +++ b/Other/vector_abs/tb.sv @@ -1,8 +1,8 @@ module tb(); -reg [31:0] a; -reg [31:0] b; -wire [31:0] res; +logic [31:0] a; +logic [31:0] b; +logic [31:0] res; vector_abs dut( .x(a), @@ -31,8 +31,8 @@ initial begin : test a = 0; b = 0; #5; checker(a,b,res); - - + + a = 1; b = 1; #5; checker(a,b,res); @@ -40,14 +40,14 @@ initial begin : test a = 3; b = 4; #5; checker(a,b,res); - - + + for(i = 0; i < 100; i=i+1) begin a = $random()&32'hff; b = $random()&32'hff; #5; checker(a,b,res); end - + $display("Test has been finished with %d errors", err_count); if(err_count == 0) begin $display("SUCCESS!"); diff --git a/Other/vector_abs/vector_abs.v b/Other/vector_abs/vector_abs.sv similarity index 64% rename from Other/vector_abs/vector_abs.v rename to Other/vector_abs/vector_abs.sv index a829a64..a89e9e7 100644 --- a/Other/vector_abs/vector_abs.v +++ b/Other/vector_abs/vector_abs.sv @@ -1,12 +1,12 @@ module vector_abs( - input [31:0] x, - input [31:0] y, - output[31:0] abs + input logic [31:0] x, + input logic [31:0] y, + output logic [31:0] abs ); - wire [31:0] min; - wire [31:0] min_half; + logic [31:0] min; + logic [31:0] min_half; max_min max_min_unit( .a(x), diff --git a/Vivado Basics/Debug manual.md b/Vivado Basics/Debug manual.md index dcd4648..b6b2a54 100644 --- a/Vivado Basics/Debug manual.md +++ b/Vivado Basics/Debug manual.md @@ -7,7 +7,7 @@ При должном отношении, поиск ошибок может превратиться в увлекательное детективное расследование, где у вас есть "место преступления" (обнаруженное несоответствие в поведении, обычно это не сама ошибка, а ее следствие, круги на воде) и какой-то "набор улик" (фрагменты лога, исходный код). И вы по чуть-чуть будете разматывать "нераспутываемую паутину лжи", получая все новые улики, ведущие к истинной ошибке. -Этот документ посвящен практикуму по поискам подобных ошибок в **Verilog**-коде. +Этот документ посвящен практикуму по поискам подобных ошибок в **SystemVerilog**-коде. - [Руководство по поиску и исправлению ошибок в проекте](#руководство-по-поиску-и-исправлению-ошибок-в-проекте) - [Цель](#цель) @@ -75,7 +75,7 @@ Открывается следующий код (с курсором на строчке `wire [31:0] res;`): -```Verilog +```SystemVerilog module tb(); reg [31:0] a; @@ -142,7 +142,7 @@ vector_abs dut( Видим два сигнала в Z-состоянии и один сигнал в X-состоянии. Обычно, сигналы с Z-состоянием проще всего исправить, т.к. зачастую это забытое или некорректное подключение провода. Кроме того, сигнал, зависящий от сигнала с Z-состоянием может оказаться в X-состоянии, так что это может быть решением нашей проблемы, поэтому займемся проводами `min` и `min_half`. Сперва займемся сигналом `min` и перейдем к шагу 2 нашего алгоритма (нажимаем правой кнопкой мыши и выбираем `Go To Source Code`): -```Verilog +```SystemVerilog module vector_abs( input [31:0] x, input [31:0] y, @@ -217,7 +217,7 @@ vector_abs dut( Значит надо смотреть как формируется результат в нашем устройстве, посмотрим на выход `abs` в модуле `vector_abs`: -```Verilog +```SystemVerilog assign abs = max + min_half; ``` @@ -238,7 +238,7 @@ assign abs = max + min_half; Как и с сигналом `abs`, необходимо определить сигналы, влияющие на значение сигнала `min_half`. Данный сигнал подключен к выходу `quotient` модуля `half_divider`, поэтому мы будем смотреть исходный код данного модуля: -```Verilog +```SystemVerilog module half_divider( input [31:0] numerator, output[31:0] quotient @@ -264,7 +264,7 @@ endmodule Именно поэтому, когда мы в первый раз пытались посчитать результат "на бумаге", у нас было расхождение с моделью: когда мы делим 1 на 2, мы получаем 0.5, однако деление путем отбрасывания цифры округляет результат вниз (1/2=0, 15/10=1). Как "отбросить" цифру средствами цифровой логики? Для этого используется операция сдвига вправо. -Операция сдвига вправо в **Verilog** записывается оператором `>>`. Справа от оператора указывается число "отбрасываемых цифр", в нашем случае одна. Но постойте, в логике присваивания стоит оператор `<<`. Это ошибка, исправим ее! +Операция сдвига вправо в **SystemVerilog** записывается оператором `>>`. Справа от оператора указывается число "отбрасываемых цифр", в нашем случае одна. Но постойте, в логике присваивания стоит оператор `<<`. Это ошибка, исправим ее! Повторяем моделирование. @@ -294,7 +294,7 @@ max + min/2 = 4 + 3/2 = 4 + 1 = 5 В глаза сразу же бросается, что сигнал `max` внешне отличается от всех остальных — он ведет себя как однобитный сигнал. Если все остальные сигналы 32-разрядные, то и сигнал `max` должен быть таким же. Перейдем к объявлению этого сигнала, чтобы это исправить (нажав правой кнопкой мыши, и выбрав `Go To Source Code`): -```Verilog +```SystemVerilog module vector_abs( input [31:0] x, input [31:0] y, @@ -314,7 +314,7 @@ max + min/2 = 4 + 3/2 = 4 + 1 = 5 //... ``` -Это странно, курсор был установлен на строку `.max(max)`, хотя раньше в этом случае курсор устанавливался на строку, где объявлялся выбранный сигнал. Но вот в чем дело, если мы просмотрим файл внимательно, то не обнаружим объявления сигнала вовсе. Как так вышло, что мы использовали необъявленный сигнал, а САПР не выдал нам ошибку? Дело в том, что стандарт [IEEE 1364-2005](https://ieeexplore.ieee.org/document/1620780) для языка **Verilog** допускает подобное использование необъявленного сигнала. В этом случае, синтезатор неявно создаст одноименный одноразрядный сигнал, что и произошло. +Это странно, курсор был установлен на строку `.max(max)`, хотя раньше в этом случае курсор устанавливался на строку, где объявлялся выбранный сигнал. Но вот в чем дело, если мы просмотрим файл внимательно, то не обнаружим объявления сигнала вовсе. Как так вышло, что мы использовали необъявленный сигнал, а САПР не выдал нам ошибку? Дело в том, что стандарт [IEEE 1364-2005](https://ieeexplore.ieee.org/document/1620780) для языка **SystemVerilog** допускает подобное использование необъявленного сигнала. В этом случае, синтезатор неявно создаст одноименный одноразрядный сигнал, что и произошло. Для исправления этой ошибки, объявим сигнал `max` с корректной разрядностью и повторим моделирование. diff --git a/Vivado Basics/Vivado trainer.md b/Vivado Basics/Vivado trainer.md index b404bac..343a67b 100644 --- a/Vivado Basics/Vivado trainer.md +++ b/Vivado Basics/Vivado trainer.md @@ -25,9 +25,9 @@ 10. Удалить папку 11. Повторить все действия самостоятельно -## Создание модуля на Verilog +## Создание модуля на SystemVerilog -1. Создать новый Verilog файл, для этого в окне `Sources` нажать на кнопку `+` +1. Создать новый SystemVerilog файл, для этого в окне `Sources` нажать на кнопку `+` 2. В открывшемся окне выбрать `Add or create design source` → Нажать `Next` 3. Нажать `Create File` → В открывшемся окне ввести имя модуля `top` и выбрать тип файла SystemVerilog → Нажать `OK` → В оставшемся окне нажать `Finish` 4. В открывшемся окне НЕ вводить названия портов и сразу нажать OK → После чего подтвердить выбор `Yes`