mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
brosandr.lab_02_alu (#62)
* Feat(02_Alu):Перепиcывание board модуля * Fix(02_Alu):Замена .v->.sv в board файле * Feat(pic/labs/board):Доб-ие пикчи alu_structure * Ref(pic/labs_board):Обн-ие nexys_alu_structure * Ref(pic/labs/board):Улуч-ие nexys_alu_struct * Ref(02_Alu/board):Замена назв-ий переменных в nexys_alu * Fix(02_Alu/board):Доб-ие @negedge arstn_i в регистр an * Ref(02_Alu/board):Переписывание форм-ия operand_* на assign * Ref(pic/labs/board):Rename ...svg->...drawio.svg * Ref(labs/02_Alu/nexys_alu):Перевод на bcd * Fix(labs/02_alu/nexys):Испр-ие вывода operand_a * Fix(labs/02_alu/nexys):Изм-ие разряд-ти bcd на 42 * Fix(.pic/labs/board/nexys_alu):Обн-ие разрядности * Ref(labs/02_alu/board):Обн-ие README * Ref(02_Alu/board):Дополнение описания оболочки * Ref(labs/02_alu_board):Различные улучшения md * Ref(labs_02_alu/board):Доб-ие точки в md * Repo(pic/labs/board):Уд-ие лишних картинок * Fix(labs/02_alu/board/md):Испр-ие alt названия * Ref(labs/02_alu/board):Перевод тире на юникод симв * Style(02_alu/board):Доб-ие абзаца после картинки * Fix(02_alu/board):Apply suggestions from code review Co-authored-by: Andrei Solodovnikov <VoultBoy@yandex.ru> * Ref(02_alu/board):Уд-ие переносов внутри абзаца * Style(02_alu):Доб-ие блейма * Fix(pic/02_alu):Поворот SE * Ref(pic/02_alu):Вырав-ие разярдностей и их цвета * Fix(02_alu/nexys):Испр-ие блейма * Ref(labs/02_alu/board):Переписывание bin2bcd * Fix(02_Alu):Apply suggestions from code review Co-authored-by: Andrei Solodovnikov <VoultBoy@yandex.ru> * Ref(pic/02_alu/alu_struct):Испр-ие шрифтов * Ref(pic/02_alu):Экспорт в svg * Ref(pic/02_alu/board):Обн-ие экспозиции nexys_alu * Ref(02_alu):Переделка маппинга свитчей в список * Ref(pic/02_alu/board):Подвижка боксов A,B,Sum * Ref(pic/02_alu/board):Замен цветов * Style(01_adder/board):Склеивание строк в абзацах * Ref(pic/02_alu/board):Испр-ие nexys_alu_struct * Fix(02_alu/board):Apply suggestions from code review Co-authored-by: Andrei Solodovnikov <VoultBoy@yandex.ru> * Repo(02_alu/board):Доб-ие шапки создателя --------- Co-authored-by: Andrei Solodovnikov <VoultBoy@yandex.ru>
This commit is contained in:
@@ -1,94 +1,181 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Project Name : Architectures of Processor Systems (APS) lab work
|
||||
* File : nexys_alu.sv
|
||||
* Organization : National Research University of Electronic Technology (MIET)
|
||||
* Department : Institute of Microdevices and Control Systems
|
||||
* Author(s) : Alexander Kharlamov
|
||||
* Email(s) : sasha_xarlamov@org.miet.ru
|
||||
|
||||
See LICENSE file for licensing details.
|
||||
* ------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
module nexys_alu(
|
||||
input CLK100,
|
||||
input resetn,
|
||||
input [15:0] SW,
|
||||
output [15:0] LED,
|
||||
output CA, CB, CC, CD, CE, CF, CG,
|
||||
output [7:0] AN
|
||||
);
|
||||
import alu_opcodes_pkg::*;
|
||||
wire [4:0] operator_i;
|
||||
wire [31:0] operand_a_i;
|
||||
wire [31:0] operand_b_i;
|
||||
|
||||
wire [31:0] result_o;
|
||||
wire comparison_result_o;
|
||||
|
||||
localparam pwm = 1000;
|
||||
reg [9:0] counter;
|
||||
reg [3:0] semseg;
|
||||
reg [7:0] ANreg;
|
||||
reg CAr, CBr, CCr, CDr, CEr, CFr, CGr;
|
||||
reg [15:0] LEDr;
|
||||
reg minus;
|
||||
|
||||
alu_riscv DUT
|
||||
(
|
||||
.alu_op_i (operator_i),
|
||||
.a_i (operand_a_i),
|
||||
.b_i (operand_b_i),
|
||||
|
||||
.result_o (result_o),
|
||||
.flag_o (comparison_result_o)
|
||||
input logic clk_i,
|
||||
input logic arstn_i,
|
||||
input logic [15:0] sw_i,
|
||||
output logic [15:0] led_o,
|
||||
output logic ca_o,
|
||||
output logic cb_o,
|
||||
output logic cc_o,
|
||||
output logic cd_o,
|
||||
output logic ce_o,
|
||||
output logic cf_o,
|
||||
output logic cg_o,
|
||||
output logic dp_o,
|
||||
output logic [ 7:0] an_o
|
||||
);
|
||||
logic sign_on;
|
||||
assign sign_on = sw_i[5];
|
||||
|
||||
assign operator_i = SW[4:0];
|
||||
assign operand_b_i = {{28{SW[10]}},SW[9:6]};
|
||||
assign operand_a_i = {{28{SW[15]}},SW[14:11]};
|
||||
logic sext_operand_a;
|
||||
assign sext_operand_a = sign_on;
|
||||
logic sext_operand_b;
|
||||
assign sext_operand_b = sign_on;
|
||||
|
||||
assign LED[15:0] = LEDr[15:0];
|
||||
import alu_opcodes_pkg::*;
|
||||
|
||||
assign AN[7:0] = ANreg[7:0];
|
||||
assign {CA, CB, CC, CD, CE, CF, CG} = {CAr, CBr, CCr, CDr, CEr, CFr, CGr};
|
||||
logic [4:0] operator;
|
||||
assign operator = sw_i[4:0];
|
||||
|
||||
initial ANreg[7:0] = 8'b11111110;
|
||||
logic [31:0] operand_b;
|
||||
assign operand_b = {(sext_operand_b ? {27{sw_i[10]}} : 27'b0), sw_i[10: 6]};
|
||||
|
||||
always @(posedge CLK100) begin
|
||||
if (!resetn) begin
|
||||
LEDr[15:0] <= 'b0;
|
||||
counter <= 'b0;
|
||||
ANreg[7:0] <= 8'b11111111;
|
||||
{CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b1111111;
|
||||
end
|
||||
else begin
|
||||
LEDr[14:0] <= result_o[14:0];
|
||||
LEDr[15] <= comparison_result_o;
|
||||
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] <= !(SW[5] && (ANreg[6:0] == 7'b1111111));
|
||||
end
|
||||
case (1'b0)
|
||||
ANreg[0]: semseg <= result_o[31] ? ( ~result_o + 1 ) % 4'd10: (result_o ) % 4'd10;
|
||||
ANreg[1]: semseg <= result_o[31] ? ((~result_o + 1) / 'd10 ) % 4'd10: (result_o / 'd10 ) % 4'd10;
|
||||
ANreg[2]: semseg <= result_o[31] ? ((~result_o + 1) / 'd100 ) % 4'd10: (result_o / 'd100 ) % 4'd10;
|
||||
ANreg[3]: semseg <= result_o[31] ? ((~result_o + 1) / 'd1000) % 4'd10: (result_o / 'd1000) % 4'd10;
|
||||
ANreg[4]: semseg <= operand_b_i[31] ? ( ~operand_b_i + 1 ) % 4'd10: (operand_b_i ) % 4'd10;
|
||||
ANreg[5]: semseg <= operand_b_i[31] ? ((~operand_b_i + 1) / 'd10) % 4'd10: (operand_b_i / 'd10) % 4'd10;
|
||||
ANreg[6]: semseg <= operand_a_i[31] ? ( ~operand_a_i + 1 ) % 4'd10: (operand_a_i ) % 4'd10;
|
||||
ANreg[7]: semseg <= operand_a_i[31] ? ((~operand_a_i + 1) / 'd10) % 4'd10: (operand_a_i / 'd10) % 4'd10;
|
||||
endcase
|
||||
minus <= (operator_i == ALU_ADD || operator_i == ALU_SUB || operator_i == ALU_SLTS || operator_i == ALU_SRA || operator_i == ALU_LTS || operator_i == ALU_GES);
|
||||
case (semseg)
|
||||
4'd0: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= (((!ANreg[5] & operand_b_i[31]) || (!ANreg[7] & operand_a_i[31]) || (!ANreg[3] & result_o[31])) && minus) ? 7'b1111110: 7'b0000001;
|
||||
4'd1: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= (((!ANreg[5] & operand_b_i[31]) || (!ANreg[7] & operand_a_i[31]) || (!ANreg[3] & result_o[31])) && minus) ? 7'b1001110: 7'b1001111;
|
||||
4'd2: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b0010010;
|
||||
4'd3: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b0000110;
|
||||
4'd4: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b1001100;
|
||||
4'd5: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b0100100;
|
||||
4'd6: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b0100000;
|
||||
4'd7: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b0001111;
|
||||
4'd8: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b0000000;
|
||||
4'd9: {CAr, CBr, CCr, CDr, CEr, CFr, CGr} <= 7'b0000100;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
logic [31:0] operand_a;
|
||||
assign operand_a = {(sext_operand_a ? {27{sw_i[15]}} : 27'b0), sw_i[15:11]};
|
||||
|
||||
logic [31:0] result;
|
||||
logic flag;
|
||||
|
||||
alu_riscv alu_riscv (
|
||||
.alu_op_i (operator),
|
||||
.a_i (operand_a),
|
||||
.b_i (operand_b),
|
||||
|
||||
.result_o (result),
|
||||
.flag_o (flag)
|
||||
);
|
||||
|
||||
localparam int COUNTER_WIDTH = 10;
|
||||
logic [COUNTER_WIDTH-1:0] counter_next;
|
||||
logic [COUNTER_WIDTH-1:0] counter_ff;
|
||||
assign counter_next = counter_ff + COUNTER_WIDTH'('b1);
|
||||
always_ff @(posedge clk_i or negedge arstn_i) begin
|
||||
if (!arstn_i) counter_ff <= '0;
|
||||
else counter_ff <= counter_next;
|
||||
end
|
||||
|
||||
logic [7:0] an_ff;
|
||||
logic [7:0] an_next;
|
||||
logic an_en;
|
||||
assign an_next = {an_ff[$left(an_ff)-1:0], an_ff[$left(an_ff)]};
|
||||
assign an_en = ~|counter_ff;
|
||||
always_ff @(posedge clk_i or negedge arstn_i) begin
|
||||
if (!arstn_i) an_ff <= ~8'b1;
|
||||
else if (an_en) an_ff <= an_next;
|
||||
end
|
||||
|
||||
function automatic logic [6:0] hex2semseg(input logic [3:0] hex);
|
||||
unique case (hex)
|
||||
4'h0: return 7'b0000001;
|
||||
4'h1: return 7'b1001111;
|
||||
4'h2: return 7'b0010010;
|
||||
4'h3: return 7'b0000110;
|
||||
4'h4: return 7'b1001100;
|
||||
4'h5: return 7'b0100100;
|
||||
4'h6: return 7'b0100000;
|
||||
4'h7: return 7'b0001111;
|
||||
4'h8: return 7'b0000000;
|
||||
4'h9: return 7'b0000100;
|
||||
4'hA: return 7'b0001000;
|
||||
4'hB: return 7'b1100000;
|
||||
4'hC: return 7'b0110001;
|
||||
4'hD: return 7'b1000010;
|
||||
4'hE: return 7'b0110000;
|
||||
4'hF: return 7'b0111000;
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
logic is_result_negative;
|
||||
assign is_result_negative = result[$left(result)] & sign_on;
|
||||
logic is_operand_a_negative;
|
||||
assign is_operand_a_negative = operand_a[$left(operand_a)];
|
||||
logic is_operand_b_negative;
|
||||
assign is_operand_b_negative = operand_b[$left(operand_b)];
|
||||
|
||||
logic [31:0] result_sign_regard;
|
||||
assign result_sign_regard = is_result_negative ? (~result + 32'b1) : result;
|
||||
logic [4:0] operand_a_sign_regard;
|
||||
assign operand_a_sign_regard = is_operand_a_negative ? (~operand_a[4:0] + 5'b1) : (operand_a[4:0]);
|
||||
logic [4:0] operand_b_sign_regard;
|
||||
assign operand_b_sign_regard = is_operand_b_negative ? (~operand_b[4:0] + 5'b1) : (operand_b[4:0]);
|
||||
|
||||
logic [63:0] bcd_result;
|
||||
logic [11:0] bcd_operand_a;
|
||||
logic [11:0] bcd_operand_b;
|
||||
|
||||
bin2bcd #($bits(result_sign_regard)) bin2bcd_result (
|
||||
.bin_i (result_sign_regard),
|
||||
.bcd_o (bcd_result )
|
||||
);
|
||||
|
||||
bin2bcd #($bits(operand_a_sign_regard)) bin2bcd_operand_a (
|
||||
.bin_i (operand_a_sign_regard),
|
||||
.bcd_o (bcd_operand_a )
|
||||
);
|
||||
|
||||
bin2bcd #($bits(operand_b_sign_regard)) bin2bcd_operand_b (
|
||||
.bin_i (operand_b_sign_regard),
|
||||
.bcd_o (bcd_operand_b )
|
||||
);
|
||||
|
||||
localparam bit [6:0] MINUS = 7'b1111110;
|
||||
localparam bit [6:0] BLANK = 7'b1111111;
|
||||
|
||||
logic [ 6:0] semseg;
|
||||
always_comb begin
|
||||
semseg = BLANK;
|
||||
|
||||
unique case (1'b0)
|
||||
an_ff[0]: semseg = hex2semseg(bcd_result[ 3:0]);
|
||||
an_ff[1]: semseg = hex2semseg(bcd_result[ 7:4]);
|
||||
an_ff[2]: semseg = hex2semseg(bcd_result[11:8]);
|
||||
an_ff[3]: semseg = is_result_negative ? MINUS : BLANK;
|
||||
an_ff[4]: semseg = hex2semseg(bcd_operand_b[3:0]);
|
||||
an_ff[5]: semseg = (is_operand_b_negative ? MINUS : BLANK) & (|bcd_operand_b[5:4] ? hex2semseg({2'b0, bcd_operand_b[5:4]}) : BLANK);
|
||||
an_ff[6]: semseg = hex2semseg(bcd_operand_a[3:0]);
|
||||
an_ff[7]: semseg = (is_operand_a_negative ? MINUS : BLANK) & (|bcd_operand_a[5:4] ? hex2semseg({2'b0, bcd_operand_a[5:4]}) : BLANK);
|
||||
endcase
|
||||
end
|
||||
|
||||
assign {ca_o, cb_o, cc_o, cd_o, ce_o, cf_o, cg_o} = semseg;
|
||||
assign dp_o = an_ff[6] ? 1'b1 : 1'b0;
|
||||
|
||||
assign led_o[14:0] = result[14:0];
|
||||
assign led_o[15] = flag;
|
||||
|
||||
assign an_o = an_ff;
|
||||
|
||||
endmodule
|
||||
|
||||
module bin2bcd #(
|
||||
parameter int IN_WIDTH = 32,
|
||||
localparam int OUT_WIDTH_DIGITS = (2 * IN_WIDTH + 3) / 4, // each byte is represented as 2 digits.
|
||||
// And ceiling
|
||||
localparam int OUT_WIDTH = 4 * OUT_WIDTH_DIGITS
|
||||
) (
|
||||
input logic [IN_WIDTH -1:0] bin_i,
|
||||
output logic [OUT_WIDTH-1:0] bcd_o
|
||||
);
|
||||
|
||||
always @(bin_i) begin
|
||||
bcd_o = '0;
|
||||
for (int unsigned bit_number = 0; bit_number < IN_WIDTH; ++bit_number) begin // Iterate once for each bit in input number
|
||||
for (int unsigned digit_num = 0; digit_num < OUT_WIDTH_DIGITS; ++digit_num) begin
|
||||
if (bcd_o[4*digit_num+:4] >= 4'd5) bcd_o[4*digit_num+:4] = bcd_o[4*digit_num+:4] + 4'd3; // If any BCD digit is >= 5, add three
|
||||
end
|
||||
bcd_o = {bcd_o[$left(bcd_o)-1:0], bin_i[$left(bin_i)-bit_number]}; // Shift one bit, and shift in proper bit from input
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
Reference in New Issue
Block a user