Exam Solutions Verilog 2024-04-16
Worked out solutions to the Verilog based questions on the Computer Architecture final exam of 2024-04-16.
Now Including the UART Parity checker, 2C.
2b: Binarization Custom Instruction
ctrl.v Download!
Expand Hide// Copyright (c) 2023 Technische Universiteit Eindhoven
`timescale 1ps/1ps
module ctrl (
input [31:0] instruction,
output reg [4:0] rs1,
output reg [4:0] rs2,
output reg [4:0] rd,
output reg [1:0] ALUOp,
output reg Jump,
output reg [3:0] ALUCtl,
output reg ALUSrc1,
output reg ALUSrc2,
output reg Branch,
output reg MemRead,
output reg MemWrite,
output reg [2:0] MemSize,
output reg RegWrite,
output reg MemToReg,
output reg valid
);
wire [6:0] opcode_value = instruction[6:0];
wire [4:0] rs1_value = instruction[19:15];
wire [4:0] rs2_value = instruction[24:20];
wire [4:0] rd_value = instruction[11:7];
wire [2:0] funct3_value = instruction[14:12];
wire [6:0] funct7_value = instruction[31:25];
wire [3:0] ALUCtl_value = {funct7_value[5], funct3_value};
always @(*) begin
rs1 = 5'd0;
rs2 = 5'd0;
rd = 5'd0;
Jump = 1'b0;
ALUCtl = 4'd0;
ALUSrc1 = 1'b0;
ALUSrc2 = 1'b0;
Branch = 1'b0;
MemRead = 1'b0;
MemWrite = 1'b0;
RegWrite =1'b0;
MemToReg = 1'b0;
ALUOp = 2'b0;
MemSize = 3'b0;
valid = 1'b0;
case (opcode_value)
7'b0001011: begin
rs1 = rs1_value;
rd = rd_value;
ALUCtl = ALUCtl_value;
RegWrite = 1'b1;
ALUOp = 2'b10;
valid = 1'b1;
end
7'd55: begin // 0110111 LUI
valid = 1'b1;
rd = rd_value;
RegWrite = 1'b1;
ALUSrc2 = 1'b1;
end
7'd23: begin // 0010111 AUIPC
valid = 1'b1;
rd = rd_value;
RegWrite = 1'b1;
ALUSrc1 = 1'b1;
ALUSrc2 = 1'b1;
end
7'd111: begin // 1101111 JAL
valid = 1'b1;
rd = rd_value;
Jump = 1'b1;
RegWrite = 1'b1;
ALUSrc1 = 1'b1;
end
7'd103: begin // 1100111 JALR
valid = ~|funct3_value;
rs1 = rs1_value;
rd = rd_value;
Jump = 1'b1;
RegWrite = 1'b1;
end
7'd99: begin // 1100011 BEQ, BNE, BLT, BGE, BLTU, BGEU
rs1 = rs1_value;
rs2 = rs2_value;
Branch = 1'b1;
ALUCtl = 4'd8;
ALUOp = 2'b01;
RegWrite = 1'b1;
case (funct3_value)
3'd0, // BEQ
3'd1, // BNE
3'd4, // BLT
3'd5, // BGE
3'd6, // BLTU
3'd7: // BGEU
valid = 1'b1;
default: ;
endcase
end
7'd3: begin // 0000011 LB, LH, LW, LBU, LHU
rs1 = rs1_value;
rd = rd_value;
ALUSrc2 = 1'b1;
MemRead = 1'b1;
RegWrite = 1'b1;
MemToReg = 1'b1;
MemSize = funct3_value;
case (funct3_value)
3'd0, // LB
3'd1, // LH
3'd2, // LW
3'd4, // LBU
3'd5: // LHU
valid = 1'b1;
default: ;
endcase
end
7'd35: begin // 0100011 SB, SH, SW
rs1 = rs1_value;
rs2 = rs2_value;
ALUSrc2 = 1'b1;
MemWrite = 1'b1;
MemSize = funct3_value;
case (funct3_value)
3'd0, // SB
3'd1, // SH
3'd2: // SW
valid = 1'b1;
default: ;
endcase
end
7'd19: begin // 0010011 ADDI, SLTI, SLTIU, XORI, ORI, ANDI, SLLI, SRLI, SRAI
rs1 = rs1_value;
rd = rd_value;
if (funct3_value[1:0] == 2'b1) begin
ALUCtl = ALUCtl_value;
end else begin
ALUCtl = {1'b0, funct3_value};
end
RegWrite = 1'b1;
ALUSrc2 = 1'b1;
ALUOp = 2'b11;
case (funct3_value)
3'd0, // ADDI
3'd2, // SLTI
3'd3, // SLTIU
3'd4, // XORI
3'd6, // ORI
3'd7: // ANDI
valid = 1'b1;
3'd1: // SLLI
valid = ~|funct7_value;
3'd5:
case (funct7_value)
7'd0, // SRLI
7'd32: // SRAI
valid = 1'b1;
default: ;
endcase
default: ;
endcase
end
7'd51: begin // 0110011 ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND
rs1 = rs1_value;
rs2 = rs2_value;
rd = rd_value;
ALUCtl = ALUCtl_value;
RegWrite = 1'b1;
ALUOp = 2'b10;
case (funct7_value)
7'd0: valid = 1'b1;
7'd32:
case (funct3_value)
3'd0, // SUB
3'd5: // SRA
valid = 1'b1;
default: ;
endcase
default: ;
endcase
end
7'd15: begin // 0001111 FENCE
valid = ~|funct3_value;
//rs1 = rs1_value;
//rd = rd_value;
end
default: ;
endcase
end
endmodule
alu.v Download!
Expand Hide// Copyright (c) 2023 Technische Universiteit Eindhoven
`timescale 1ps/1ps
module alu (
input [4:0] ALUctl,
input [31:0] A,
input [31:0] B,
output Zero,
output reg [31:0] ALUOut
);
always @(*) begin
case (ALUctl[3:0])
4'd0: ALUOut = A + B;
4'd1,4'd9: ALUOut = A << B[4:0];
4'd2: ALUOut = {31'd0, $signed(A) < $signed(B)};
4'd3: ALUOut = {31'd0, A < B};
4'd4: ALUOut = A ^ B;
4'd5: ALUOut = A >> B[4:0];
4'd6: ALUOut = A | B;
4'd7: ALUOut = A & B;
4'd8: ALUOut = A - B;
4'd13: ALUOut = $signed(A) >>> B[4:0];
4'd15: ALUOut = ($signed(A) >= 127) ? 255 : 0;
default: ALUOut = 32'd0;
endcase
end
wire eq_zero = (ALUOut == 32'd0);
assign Zero = (ALUctl[4] ? ~eq_zero : eq_zero);
endmodule
2c: UART Parity Detector
uart_parity_even.v Download!
Expand Hidemodule uart_parity_even(
input reset,
input signal,
input clk,
output reg valid,
output reg error
);
localparam BREAK = 0,
IDLE = 1,
START = 2,
B1E = 3,
B1O = 4,
B2E = 5,
B2O = 6,
B3E = 7,
B3O = 8,
B4E = 9,
B4O = 10,
PO = 11,
PE = 12,
SO = 13,
SE = 14;
reg [3:0] state;
reg [3:0] state_next;
always @(posedge clk) begin
if (reset) begin
state <= BREAK;
valid <= 0;
error <= 0;
end else begin
error <= 0;
valid <= 0;
case (state_next)
SO: error <= 1;
SE: valid <= 1;
endcase
state <= state_next;
end
end
always @(*) begin
case (state)
BREAK: begin
case (signal)
1: state_next = IDLE;
default: state_next = BREAK;
endcase
end
IDLE: begin
case (signal)
1: state_next = IDLE;
default: state_next = START;
endcase
end
START: begin
case (signal)
1: state_next = B1O;
default: state_next = B1E;
endcase
end
B1E: begin
case (signal)
1: state_next = B2O;
default: state_next = B2E;
endcase
end
B2E: begin
case (signal)
1: state_next = B3O;
default: state_next = B3E;
endcase
end
B3E: begin
case (signal)
1: state_next = B4O;
default: state_next = B4E;
endcase
end
B4E: begin
case (signal)
1: state_next = PO;
default: state_next = PE;
endcase
end
B1O: begin
case (signal)
1: state_next = B2E;
default: state_next = B2O;
endcase
end
B2O: begin
case (signal)
1: state_next = B3E;
default: state_next = B3O;
endcase
end
B3O: begin
case (signal)
1: state_next = B4E;
default: state_next = B4O;
endcase
end
B4O: begin
case (signal)
1: state_next = PE;
default: state_next = PO;
endcase
end
PO: begin
case (signal)
1: state_next = SO;
default: state_next = BREAK;
endcase
end
PE: begin
case (signal)
1: state_next = SE;
default: state_next = BREAK;
endcase
end
SO: begin
case (signal)
1: state_next = IDLE;
default: state_next = START;
endcase
end
SE: begin
case (signal)
1: state_next = IDLE;
default: state_next = START;
endcase
end
endcase
end
endmodule
2d: Counter with FSM Trigger
counter.v Download!
Expand Hidemodule counter (
input clk,
input reset,
input enable,
input valid,
input [4:0] value,
output trigger,
output reg [4:0] count,
output [1:0] repeats
);
counter_fsm FSM1 (
.clk(clk),
.complete(count == 0),
.enable(enable),
.reset(reset),
.repeats(repeats),
.trigger(trigger)
);
always @(posedge clk) begin
if(reset) begin
count <= 0;
end else if(valid)
count <= value;
else if(count != 0 && enable)
count <= count - 1;
else
count <= count;
end
endmodule
counter_fsm.v Download!
Expand Hidemodule counter_fsm (
input clk,
input complete,
input enable,
input reset,
output reg [1:0] repeats,
output reg trigger
);
localparam IDLE = 0,
COUNTING = 1,
DONE = 2,
PAUSED = 3;
reg [3:0] state, state_nxt;
always @(posedge clk) begin
if(reset) begin
state <= IDLE;
repeats <= 0;
trigger <= 0;
end else begin
state <= state_nxt;
repeats <= state_nxt == IDLE ? 0 : (state_nxt == DONE ? (repeats + 1) : repeats);
trigger <= state_nxt == DONE;
end
end
always @(*) begin
case(state)
//IDLE
default: begin
if(complete)
state_nxt = IDLE;
else
state_nxt = enable ? COUNTING : PAUSED;
end
COUNTING: begin
if(enable) begin
state_nxt = complete ? DONE : COUNTING;
end else
state_nxt = complete ? IDLE : PAUSED;
end
DONE: begin
if(complete) begin
state_nxt = enable ? DONE : IDLE;
end else
state_nxt = enable ? COUNTING : PAUSED;
end
PAUSED: begin
if(enable) begin
state_nxt = complete ? DONE : COUNTING;
end else
state_nxt = complete ? IDLE : PAUSED;
end
endcase
end
endmodule
2e: HTTP Request Transmitter
http.v Download!
Expand Hidemodule http #(
parameter integer repeats_max = 2
)
(
input clk,
input reset,
input ack,
output done,
output[4:0] count,
output [1:0] repeats
);
wire trigger, enable, valid;
http_fsm #(
.repeats_max(repeats_max)
) HT1 (
.clk(clk),
.ack(ack),
.reset(reset),
.repeats(repeats),
.trigger(trigger),
.done(done),
.enable(enable),
.valid(valid)
);
counter CN1 (
.clk(clk),
.enable(enable),
.reset(reset),
.valid(valid),
.value(5'd5),
.count(count),
.repeats(repeats),
.trigger(trigger)
);
endmodule
http_fsm.v Download!
Expand Hidemodule http_fsm #(
parameter integer repeats_max = 2
)
(
input clk,
input reset,
input ack,
input [1:0] repeats,
input trigger,
output reg done,
output reg enable,
output reg valid
);
localparam INIT = 0,
WAITING = 1,
COUNTING = 2,
RESEND = 3,
TIMEOUT = 4,
SENT = 5;
reg [4:0] state, state_nxt;
always @(posedge clk) begin
if(reset) begin
state <= INIT;
end else begin
state <= state_nxt;
end
end
always @(*) begin
enable = 1;
done = 0;
valid = 0;
case(state)
//INIT
default: begin
state_nxt = ack ? SENT : WAITING;
enable = ack ? 0 : 1;
done = ack;
valid = ack ? 0 : 1;
end
WAITING: begin
state_nxt = COUNTING;
end
COUNTING: begin
state_nxt = trigger ? RESEND : COUNTING;
end
RESEND: begin
if(ack) begin
state_nxt = SENT;
done = 1;
enable = 0;
end else if (repeats >= repeats_max[1:0]) begin
state_nxt = TIMEOUT;
done = 0;
enable = 0;
end else begin
state_nxt = WAITING;
valid = 1;
end
end
TIMEOUT: begin
state_nxt = TIMEOUT;
done = 0;
enable = 0;
end
SENT: begin
state_nxt = SENT;
done = 1;
enable = 0;
end
endcase
end
endmodule