Compare commits
14 Commits
d094ff3148
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4ffd9dd46 | ||
|
|
6df7024707 | ||
|
|
42811f868b | ||
|
|
b3d11de769 | ||
|
|
cec82dc58f | ||
|
|
5cc4b5adf4 | ||
|
|
9ff7d002c1 | ||
|
|
53925538d6 | ||
|
|
1525373c61 | ||
|
|
8050e9a473 | ||
|
|
eba954854c | ||
|
|
3f0f6f04e3 | ||
|
|
a1a95b50ab | ||
|
|
838ee4c0ae |
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
*.vcd
|
||||||
|
*.vvp
|
||||||
|
*.json
|
||||||
18
counter/counter.v
Normal file
18
counter/counter.v
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
Contador
|
||||||
|
*/
|
||||||
|
|
||||||
|
module counter #(parameter N = 8) (
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
input write,
|
||||||
|
input [N-1:0] write_value,
|
||||||
|
output reg [N-1:0] count
|
||||||
|
);
|
||||||
|
|
||||||
|
always @(posedge clk or posedge rst) begin
|
||||||
|
if (rst) count <= 0;
|
||||||
|
else if (write) count <= write_value;
|
||||||
|
else count <= count + 1;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
44
counter/counter_tb.v
Normal file
44
counter/counter_tb.v
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
`include "./counter/counter.v"
|
||||||
|
|
||||||
|
module counter_tb;
|
||||||
|
reg clk, rst, write_enable;
|
||||||
|
reg [15:0] write_value;
|
||||||
|
wire [15:0] count;
|
||||||
|
|
||||||
|
counter #(.N(16)) cnt(
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.write(write_enable),
|
||||||
|
.write_value(write_value),
|
||||||
|
.count(count)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
always #5 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("./counter/counter.vcd");
|
||||||
|
$dumpvars(0, counter_tb);
|
||||||
|
|
||||||
|
rst = 1; write_enable = 0; write_value = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
rst = 0;
|
||||||
|
|
||||||
|
// Contar 20 ciclos
|
||||||
|
repeat(20) @(posedge clk);
|
||||||
|
#1 $display("despues de 20 ciclos: count=%0d", count);
|
||||||
|
|
||||||
|
// Load a 200
|
||||||
|
write_enable = 1; write_value = 200;
|
||||||
|
@(posedge clk); #1
|
||||||
|
write_enable = 0;
|
||||||
|
$display("tras load 200: count=%0d", count);
|
||||||
|
|
||||||
|
// Contar hasta overflow (56 ciclos llega a 255 y desborda a 0)
|
||||||
|
repeat(60) @(posedge clk);
|
||||||
|
#1 $display("tras 60 ciclos mas: count=%0d", count);
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
30
decoder_encoder/decoder_encoder.v
Normal file
30
decoder_encoder/decoder_encoder.v
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
Decoder / Encoder
|
||||||
|
*/
|
||||||
|
|
||||||
|
module decoder_3bit (
|
||||||
|
input [2:0] in,
|
||||||
|
output [7:0] out
|
||||||
|
);
|
||||||
|
assign out = 1 << in;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module encoder_3bit(
|
||||||
|
input [7:0] in,
|
||||||
|
output reg [2:0] out
|
||||||
|
);
|
||||||
|
always @(*) begin
|
||||||
|
out = 0;
|
||||||
|
|
||||||
|
casez(in)
|
||||||
|
8'b1???????: out = 3'd7;
|
||||||
|
8'b01??????: out = 3'd6;
|
||||||
|
8'b001?????: out = 3'd5;
|
||||||
|
8'b0001????: out = 3'd4;
|
||||||
|
8'b00001???: out = 3'd3;
|
||||||
|
8'b000001??: out = 3'd2;
|
||||||
|
8'b0000001?: out = 3'd1;
|
||||||
|
8'b00000001: out = 3'd0;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
38
decoder_encoder/decoder_encoder_tb.v
Normal file
38
decoder_encoder/decoder_encoder_tb.v
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
`include "./decoder_encoder/decoder_encoder.v"
|
||||||
|
|
||||||
|
module decoder_3bit_tb;
|
||||||
|
reg [2:0] in;
|
||||||
|
wire [7:0] out;
|
||||||
|
wire [2:0] encoded;
|
||||||
|
|
||||||
|
decoder_3bit dec(
|
||||||
|
.in(in),
|
||||||
|
.out(out)
|
||||||
|
);
|
||||||
|
|
||||||
|
encoder_3bit enc(
|
||||||
|
.in(out),
|
||||||
|
.out(encoded)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("./decoder_encoder/decoder_encoder.vcd");
|
||||||
|
$dumpvars(0, decoder_3bit_tb);
|
||||||
|
|
||||||
|
in = 3'b000;
|
||||||
|
#1
|
||||||
|
$display("in=%d, out=%b, enc=%d", in, out, encoded);
|
||||||
|
in = 3'b001;
|
||||||
|
#1
|
||||||
|
$display("in=%d, out=%b, enc=%d", in, out, encoded);
|
||||||
|
in = 3'b010;
|
||||||
|
#1
|
||||||
|
$display("in=%d, out=%b, enc=%d", in, out, encoded);
|
||||||
|
in = 3'b100;
|
||||||
|
#1
|
||||||
|
$display("in=%d, out=%b, enc=%d", in, out, encoded);
|
||||||
|
in = 3'b111;
|
||||||
|
#1
|
||||||
|
$display("in=%d, out=%b, enc=%d", in, out, encoded);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
17
flip_flop/flip_flop.v
Normal file
17
flip_flop/flip_flop.v
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
Flip-Flop D y registro
|
||||||
|
*/
|
||||||
|
|
||||||
|
module register #(parameter N = 8)(
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
input en,
|
||||||
|
input [N-1:0] d,
|
||||||
|
output reg [N-1:0] q
|
||||||
|
);
|
||||||
|
always @(posedge clk or posedge rst) begin
|
||||||
|
if (rst) q <= 0;
|
||||||
|
else if (en) q <= d;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
52
flip_flop/flip_flop_tb.v
Normal file
52
flip_flop/flip_flop_tb.v
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
Flip-Flop D y registro
|
||||||
|
*/
|
||||||
|
`include "./flip_flop/flip_flop.v"
|
||||||
|
|
||||||
|
module register_tb;
|
||||||
|
reg clk, rst, en;
|
||||||
|
reg [7:0] d;
|
||||||
|
wire [7:0] q;
|
||||||
|
|
||||||
|
register #(.N(8)) dut (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.en(en),
|
||||||
|
.d(d),
|
||||||
|
.q(q)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
always #5 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("./flip_flop/flip_flop.vcd");
|
||||||
|
$dumpvars(0, register_tb);
|
||||||
|
|
||||||
|
rst = 1; en = 0; d = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
|
||||||
|
rst = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("rst=0, en=0, d=%0d, q=%0d (q no cambia)", d, q);
|
||||||
|
|
||||||
|
en = 1; d = 8'd42;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("en=1, d=42 → q=%0d", q);
|
||||||
|
|
||||||
|
d = 8'd99;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("en=1, d=99 → q=%0d", q);
|
||||||
|
|
||||||
|
en = 0; d = 8'd7;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("en=0, d=7 → q=%0d (q mantiene 99)", q);
|
||||||
|
|
||||||
|
rst = 1;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("rst=1 → q=%0d (q=0)", q);
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
48
fsm_traffic/fsm_traffic.v
Normal file
48
fsm_traffic/fsm_traffic.v
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
fsm_traffic
|
||||||
|
*/
|
||||||
|
module fsm_traffic (
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
output red_led,
|
||||||
|
output green_led,
|
||||||
|
output yellow_led
|
||||||
|
);
|
||||||
|
localparam RED = 2'b00;
|
||||||
|
localparam GREEN = 2'b01;
|
||||||
|
localparam YELLOW = 2'b10;
|
||||||
|
|
||||||
|
reg[1:0] state, next_state;
|
||||||
|
reg[7:0] timer;
|
||||||
|
|
||||||
|
always @(posedge clk or posedge rst) begin
|
||||||
|
if (rst) begin
|
||||||
|
state <= RED;
|
||||||
|
timer <= 3;
|
||||||
|
end
|
||||||
|
else if (timer == 0) begin
|
||||||
|
state <= next_state;
|
||||||
|
|
||||||
|
case (next_state)
|
||||||
|
RED: timer <= 3;
|
||||||
|
YELLOW: timer <= 1;
|
||||||
|
GREEN: timer <= 2;
|
||||||
|
default: timer <= 3;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
else timer <= timer - 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
case (state)
|
||||||
|
RED: next_state = GREEN;
|
||||||
|
YELLOW: next_state = RED;
|
||||||
|
GREEN: next_state = YELLOW;
|
||||||
|
default: next_state = RED;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign red_led = state == RED;
|
||||||
|
assign green_led = state == GREEN;
|
||||||
|
assign yellow_led = state == YELLOW;
|
||||||
|
endmodule
|
||||||
56
fsm_traffic/fsm_traffic_tb.v
Normal file
56
fsm_traffic/fsm_traffic_tb.v
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
fsm_traffic testbench
|
||||||
|
*/
|
||||||
|
`include "fsm_traffic/fsm_traffic.v"
|
||||||
|
|
||||||
|
module fsm_traffic_tb;
|
||||||
|
reg clk, rst;
|
||||||
|
wire red_led, green_led, yellow_led;
|
||||||
|
|
||||||
|
fsm_traffic dut (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.red_led(red_led),
|
||||||
|
.green_led(green_led),
|
||||||
|
.yellow_led(yellow_led)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
always #5 clk = ~clk;
|
||||||
|
|
||||||
|
task show_state;
|
||||||
|
$display("t=%0t | rst=%b | R=%b G=%b Y=%b",
|
||||||
|
$time, rst, red_led, green_led, yellow_led);
|
||||||
|
endtask
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("fsm_traffic/fsm_traffic.vcd");
|
||||||
|
$dumpvars(0, fsm_traffic_tb);
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
rst = 1;
|
||||||
|
@(posedge clk); #1
|
||||||
|
show_state;
|
||||||
|
|
||||||
|
rst = 0;
|
||||||
|
|
||||||
|
// Dejar correr varios ciclos para ver todos los estados
|
||||||
|
repeat(9) begin
|
||||||
|
@(posedge clk); #1
|
||||||
|
show_state;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Reset a mitad de secuencia — debe volver a RED
|
||||||
|
rst = 1;
|
||||||
|
@(posedge clk); #1
|
||||||
|
show_state;
|
||||||
|
rst = 0;
|
||||||
|
|
||||||
|
repeat(3) begin
|
||||||
|
@(posedge clk); #1
|
||||||
|
show_state;
|
||||||
|
end
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -31,4 +31,95 @@ module demux_1n2 #(parameter N = 8) (
|
|||||||
);
|
);
|
||||||
assign a = sel ? 0 : in;
|
assign a = sel ? 0 : in;
|
||||||
assign b = sel ? in : 0;
|
assign b = sel ? in : 0;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module mux_4n1 #(parameter N = 8) (
|
||||||
|
input [N-1:0] a,
|
||||||
|
input [N-1:0] b,
|
||||||
|
input [N-1:0] c,
|
||||||
|
input [N-1:0] d,
|
||||||
|
input [1:0] sel,
|
||||||
|
output reg [N-1:0] out
|
||||||
|
);
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
case (sel)
|
||||||
|
2'b00: out = a;
|
||||||
|
2'b01: out = b;
|
||||||
|
2'b10: out = c;
|
||||||
|
2'b11: out = d;
|
||||||
|
default: out = a;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module demux_1n4 #(parameter N = 8) (
|
||||||
|
input [N-1:0] in,
|
||||||
|
input [1:0] sel,
|
||||||
|
output reg [N-1:0] a,
|
||||||
|
output reg [N-1:0] b,
|
||||||
|
output reg [N-1:0] c,
|
||||||
|
output reg [N-1:0] d
|
||||||
|
);
|
||||||
|
always @(*) begin
|
||||||
|
a = 0; b = 0; c = 0; d = 0;
|
||||||
|
|
||||||
|
case (sel)
|
||||||
|
2'b00: a = in;
|
||||||
|
2'b01: b = in;
|
||||||
|
2'b10: c = in;
|
||||||
|
2'b11: d = in;
|
||||||
|
default: a = in;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module mux_8n1 #(parameter N = 8) (
|
||||||
|
input [N-1:0] a,
|
||||||
|
input [N-1:0] b,
|
||||||
|
input [N-1:0] c,
|
||||||
|
input [N-1:0] d,
|
||||||
|
input [N-1:0] e,
|
||||||
|
input [N-1:0] f,
|
||||||
|
input [N-1:0] g,
|
||||||
|
input [N-1:0] h,
|
||||||
|
input [2:0] sel,
|
||||||
|
output reg [N-1:0] out
|
||||||
|
);
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
case (sel)
|
||||||
|
3'b000: out = a;
|
||||||
|
3'b001: out = b;
|
||||||
|
3'b010: out = c;
|
||||||
|
3'b011: out = d;
|
||||||
|
3'b100: out = e;
|
||||||
|
3'b101: out = f;
|
||||||
|
3'b110: out = g;
|
||||||
|
3'b111: out = h;
|
||||||
|
default: out = a;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module mux_Nn1 #(
|
||||||
|
parameter DATA_W = 8, // bits por dato
|
||||||
|
parameter SEL_W = 3 // bits de sel -> 2^SEL_W entradas
|
||||||
|
)(
|
||||||
|
input [(1<<SEL_W) * DATA_W - 1 : 0] in,
|
||||||
|
input [SEL_W-1:0] sel,
|
||||||
|
output [DATA_W-1:0] out
|
||||||
|
);
|
||||||
|
localparam INPUTS = 1 << SEL_W; // 2^3 = 8
|
||||||
|
|
||||||
|
wire [DATA_W-1:0] data [0:INPUTS-1];
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
generate
|
||||||
|
for (i=0; i<INPUTS; i = i + 1) begin: unpack
|
||||||
|
assign data[i] = in[i * DATA_W +: DATA_W];
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign out = data[sel];
|
||||||
endmodule
|
endmodule
|
||||||
43
mux_demux/mux_demux_tb.v
Normal file
43
mux_demux/mux_demux_tb.v
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
`include "./mux_demux/mux_demux.v"
|
||||||
|
|
||||||
|
module mux_demux_tb();
|
||||||
|
reg [7:0] a, b;
|
||||||
|
reg sel;
|
||||||
|
|
||||||
|
wire [7:0] out, _a, _b;
|
||||||
|
|
||||||
|
mux_Nn1 #(.DATA_W(8), .SEL_W(1)) mux (
|
||||||
|
.in({b, a}),
|
||||||
|
.sel(sel),
|
||||||
|
.out(out)
|
||||||
|
);
|
||||||
|
|
||||||
|
demux_1n2 demux (
|
||||||
|
.in(out),
|
||||||
|
.sel(sel),
|
||||||
|
.a(_a),
|
||||||
|
.b(_b)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("./mux_demux/mux_demux.vcd");
|
||||||
|
$dumpvars(0, mux_demux_tb);
|
||||||
|
|
||||||
|
a = 20; b = 5; sel = 0;
|
||||||
|
#1
|
||||||
|
$display("a=%d, b=%d, sel=%b out=%d _a=%d, _b=%d", a, b, sel, out, _a, _b);
|
||||||
|
a = 21; b = 5; sel = 0;
|
||||||
|
#1
|
||||||
|
$display("a=%d, b=%d, sel=%b out=%d _a=%d, _b=%d", a, b, sel, out, _a, _b);
|
||||||
|
a = 22; b = 5; sel = 0;
|
||||||
|
#1
|
||||||
|
$display("a=%d, b=%d, sel=%b out=%d _a=%d, _b=%d", a, b, sel, out, _a, _b);
|
||||||
|
a = 22; b = 5; sel = 1;
|
||||||
|
#1
|
||||||
|
$display("a=%d, b=%d, sel=%b out=%d _a=%d, _b=%d", a, b, sel, out, _a, _b);
|
||||||
|
a = 22; b = 15; sel = 1;
|
||||||
|
#1
|
||||||
|
$display("a=%d, b=%d, sel=%b out=%d _a=%d, _b=%d", a, b, sel, out, _a, _b);
|
||||||
|
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
24
ram/ram.v
Normal file
24
ram/ram.v
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
Ram Sincrona
|
||||||
|
*/
|
||||||
|
|
||||||
|
module ram #(
|
||||||
|
parameter DEPTH = 256, // posiciones
|
||||||
|
parameter W = 16 // bits por posicion
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input wr_en,
|
||||||
|
input [$clog2(DEPTH)-1:0] addr,
|
||||||
|
input [W-1:0] wr_data,
|
||||||
|
output reg [W-1:0] rd_data
|
||||||
|
);
|
||||||
|
reg [W-1:0] mem [0:DEPTH-1];
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (wr_en)
|
||||||
|
mem[addr] <= wr_data;
|
||||||
|
else
|
||||||
|
rd_data <= mem[addr];
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
54
ram/ram_tb.v
Normal file
54
ram/ram_tb.v
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
Ram Sincrona testbench
|
||||||
|
*/
|
||||||
|
`include "ram/ram.v"
|
||||||
|
|
||||||
|
module ram_tb;
|
||||||
|
reg clk, wr_en;
|
||||||
|
reg [7:0] addr;
|
||||||
|
reg [15:0] wr_data;
|
||||||
|
wire [15:0] rd_data;
|
||||||
|
|
||||||
|
ram ram1(
|
||||||
|
.clk(clk),
|
||||||
|
.wr_en(wr_en),
|
||||||
|
.addr(addr),
|
||||||
|
.wr_data(wr_data),
|
||||||
|
.rd_data(rd_data)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
always #5 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("ram/ram.vcd");
|
||||||
|
$dumpvars(0, ram_tb);
|
||||||
|
|
||||||
|
wr_en = 0; addr = 0; wr_data = 0;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("wr_en=%b, addr=%d, wr_data=%d, rd_data=%d", wr_en, addr, wr_data, rd_data);
|
||||||
|
|
||||||
|
wr_en = 1; addr = 25; wr_data = 256;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("wr_en=%b, addr=%d, wr_data=%d, rd_data=%d", wr_en, addr, wr_data, rd_data);
|
||||||
|
|
||||||
|
wr_en = 0;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("wr_en=%b, addr=%d, wr_data=%d, rd_data=%d", wr_en, addr, wr_data, rd_data);
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
$display("wr_en=%b, addr=%d, wr_data=%d, rd_data=%d", wr_en, addr, wr_data, rd_data);
|
||||||
|
|
||||||
|
addr = 16;
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
$display("wr_en=%b, addr=%d, wr_data=%d, rd_data=%d", wr_en, addr, wr_data, rd_data);
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
$display("wr_en=%b, addr=%d, wr_data=%d, rd_data=%d", wr_en, addr, wr_data, rd_data);
|
||||||
|
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
38
register_file/register_file.v
Normal file
38
register_file/register_file.v
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
Registros
|
||||||
|
*/
|
||||||
|
|
||||||
|
module register_file #(
|
||||||
|
parameter REGS = 16,
|
||||||
|
parameter W = 16
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
// Puerto escritura
|
||||||
|
input [$clog2(REGS)-1:0] wr_addr,
|
||||||
|
input [W-1:0] wr_data,
|
||||||
|
input wr_en,
|
||||||
|
// Puerto lectura 1
|
||||||
|
input [$clog2(REGS)-1:0] rd_addr1,
|
||||||
|
output [W-1:0] rd_data1,
|
||||||
|
// Puerto lectura 2
|
||||||
|
input [$clog2(REGS)-1:0] rd_addr2,
|
||||||
|
output [W-1:0] rd_data2
|
||||||
|
);
|
||||||
|
reg [W-1:0] regs [0:REGS-1];
|
||||||
|
|
||||||
|
// Lectura combinacional
|
||||||
|
assign rd_data1 = regs[rd_addr1];
|
||||||
|
assign rd_data2 = regs[rd_addr2];
|
||||||
|
|
||||||
|
// Escritura sincrona
|
||||||
|
integer i;
|
||||||
|
always @(posedge clk or posedge rst) begin
|
||||||
|
if (rst) begin
|
||||||
|
for (i = 0; i < REGS; i = i + 1)
|
||||||
|
regs[i] <= 0;
|
||||||
|
end else if (wr_en) begin
|
||||||
|
regs[wr_addr] <= wr_data;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
60
register_file/register_file_tb.v
Normal file
60
register_file/register_file_tb.v
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Registros
|
||||||
|
*/
|
||||||
|
`include "./register_file/register_file.v"
|
||||||
|
module register_file_tb;
|
||||||
|
reg clk, rst, wr_en;
|
||||||
|
reg [3:0] wr_addr;
|
||||||
|
reg [15:0] wr_data;
|
||||||
|
reg [3:0] rd_addr1, rd_addr2;
|
||||||
|
wire [15:0] rd_value1, rd_value2;
|
||||||
|
|
||||||
|
register_file register(
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.wr_addr(wr_addr),
|
||||||
|
.wr_data(wr_data),
|
||||||
|
.wr_en(wr_en),
|
||||||
|
.rd_addr1(rd_addr1),
|
||||||
|
.rd_data1(rd_value1),
|
||||||
|
.rd_addr2(rd_addr2),
|
||||||
|
.rd_data2(rd_value2)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
always #5 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("register_file/register_file.vcd");
|
||||||
|
$dumpvars(0, register_file_tb);
|
||||||
|
|
||||||
|
rst = 1; wr_en = 0; wr_addr = 0; wr_data = 0;
|
||||||
|
rd_addr1 = 0; rd_addr2 = 0;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("rst=%b, wr_en=%b, wr_add=%d, wr_data=%d", rst, wr_en, wr_addr, wr_data);
|
||||||
|
$display("rd_addr1=%d, rd_addr2=%d, rd_value1=%d, rd_value2=%d", rd_addr1, rd_addr2, rd_value1, rd_value2);
|
||||||
|
|
||||||
|
rst = 0;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("rst=%b, wr_en=%b, wr_add=%d, wr_data=%d", rst, wr_en, wr_addr, wr_data);
|
||||||
|
$display("rd_addr1=%d, rd_addr2=%d, rd_value1=%d, rd_value2=%d", rd_addr1, rd_addr2, rd_value1, rd_value2);
|
||||||
|
|
||||||
|
wr_en = 1; wr_addr = 1; wr_data = 16'hBEEF;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("rst=%b, wr_en=%b, wr_add=%d, wr_data=%d", rst, wr_en, wr_addr, wr_data);
|
||||||
|
$display("rd_addr1=%d, rd_addr2=%d, rd_value1=%d, rd_value2=%d", rd_addr1, rd_addr2, rd_value1, rd_value2);
|
||||||
|
|
||||||
|
wr_en = 0;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("rst=%b, wr_en=%b, wr_add=%d, wr_data=%d", rst, wr_en, wr_addr, wr_data);
|
||||||
|
$display("rd_addr1=%d, rd_addr2=%d, rd_value1=%d, rd_value2=%d", rd_addr1, rd_addr2, rd_value1, rd_value2);
|
||||||
|
|
||||||
|
rd_addr1 = 1;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("rst=%b, wr_en=%b, wr_add=%d, wr_data=%d", rst, wr_en, wr_addr, wr_data);
|
||||||
|
$display("rd_addr1=%d, rd_addr2=%d, rd_value1=%d, rd_value2=%d", rd_addr1, rd_addr2, rd_value1, rd_value2);
|
||||||
|
|
||||||
|
repeat(100) @(posedge clk);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
20
roadmap.md
20
roadmap.md
@@ -345,16 +345,16 @@ gtkwave modulo.vcd
|
|||||||
- [x] Fase 1.1 — Full Adder
|
- [x] Fase 1.1 — Full Adder
|
||||||
- [x] Fase 1.2 — Adder N bits
|
- [x] Fase 1.2 — Adder N bits
|
||||||
- [x] Fase 1.3 — ALU basica
|
- [x] Fase 1.3 — ALU basica
|
||||||
- [ ] Fase 1.4 — Mux / Demux
|
- [x] Fase 1.4 — Mux / Demux
|
||||||
- [ ] Fase 1.5 — Decoder / Encoder
|
- [x] Fase 1.5 — Decoder / Encoder
|
||||||
- [ ] Fase 2.1 — Flip-Flop D y registro
|
- [x] Fase 2.1 — Flip-Flop D y registro
|
||||||
- [ ] Fase 2.2 — Contador
|
- [x] Fase 2.2 — Contador
|
||||||
- [ ] Fase 2.3 — Shift Register
|
- [x] Fase 2.3 — Shift Register
|
||||||
- [ ] Fase 2.4 — Register File
|
- [x] Fase 2.4 — Register File
|
||||||
- [ ] Fase 3.1 — RAM sincrona
|
- [x] Fase 3.1 — RAM sincrona
|
||||||
- [ ] Fase 3.2 — ROM
|
- [x] Fase 3.2 — ROM
|
||||||
- [ ] Fase 3.3 — Stack
|
- [x] Fase 3.3 — Stack
|
||||||
- [ ] Fase 4.1 — FSM Semaforo
|
- [x] Fase 4.1 — FSM Semaforo
|
||||||
- [ ] Fase 4.2 — UART TX
|
- [ ] Fase 4.2 — UART TX
|
||||||
- [ ] Fase 5.1 — Fetch Unit
|
- [ ] Fase 5.1 — Fetch Unit
|
||||||
- [ ] Fase 5.2 — Decoder de instrucciones
|
- [ ] Fase 5.2 — Decoder de instrucciones
|
||||||
|
|||||||
5
rom/program.hex
Normal file
5
rom/program.hex
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
BEEF
|
||||||
|
1234
|
||||||
|
ABCD
|
||||||
|
0000
|
||||||
|
FF00
|
||||||
21
rom/rom.v
Normal file
21
rom/rom.v
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
ROM
|
||||||
|
*/
|
||||||
|
|
||||||
|
module rom #(
|
||||||
|
parameter DEPTH = 256,
|
||||||
|
parameter W = 16,
|
||||||
|
parameter FILE = ""
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input [$clog2(DEPTH)-1:0] addr,
|
||||||
|
output reg [W-1:0] rd_data
|
||||||
|
);
|
||||||
|
reg [W-1:0] mem [0:DEPTH-1];
|
||||||
|
|
||||||
|
initial $readmemh(FILE, mem);
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
rd_data <= mem[addr];
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
44
rom/rom_tb.v
Normal file
44
rom/rom_tb.v
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
ROM
|
||||||
|
*/
|
||||||
|
`include "rom/rom.v"
|
||||||
|
|
||||||
|
module rom_tb;
|
||||||
|
reg clk;
|
||||||
|
reg [7:0] addr;
|
||||||
|
wire [15:0] rd_data;
|
||||||
|
|
||||||
|
rom #(.FILE("rom/program.hex")) rom1(
|
||||||
|
.clk(clk),
|
||||||
|
.addr(addr),
|
||||||
|
.rd_data(rd_data)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
always #5 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("rom/rom.vcd");
|
||||||
|
$dumpvars(0, rom_tb);
|
||||||
|
|
||||||
|
addr = 0;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("addr=%d, rd_data=%x", addr, rd_data);
|
||||||
|
@(posedge clk);
|
||||||
|
$display("addr=%d, rd_data=%x", addr, rd_data);
|
||||||
|
|
||||||
|
addr = 1;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("addr=%d, rd_data=%x", addr, rd_data);
|
||||||
|
@(posedge clk);
|
||||||
|
$display("addr=%d, rd_data=%x", addr, rd_data);
|
||||||
|
|
||||||
|
addr = 2;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("addr=%d, rd_data=%x", addr, rd_data);
|
||||||
|
@(posedge clk);
|
||||||
|
$display("addr=%d, rd_data=%x", addr, rd_data);
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
16
run.sh
Executable file
16
run.sh
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: $0 <module>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
module="${1#./}"
|
||||||
|
module="${module#/}"
|
||||||
|
module="${module%/}"
|
||||||
|
|
||||||
|
iverilog -o "./$module/$module.vvp" "./$module/${module}_tb.v" || exit 1
|
||||||
|
|
||||||
|
vvp "./$module/$module.vvp" || exit 1
|
||||||
|
|
||||||
|
surfer "./$module/$module.vcd"
|
||||||
24
shift_register/shift_register.v
Normal file
24
shift_register/shift_register.v
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
module shift_register #(parameter N = 8) (
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
input load,
|
||||||
|
input shift_en,
|
||||||
|
input dir,
|
||||||
|
input serial_in,
|
||||||
|
input [N-1:0] parallel_in,
|
||||||
|
output reg [N-1:0] q,
|
||||||
|
output serial_out
|
||||||
|
);
|
||||||
|
|
||||||
|
assign serial_out = dir ? q[0] : q[N-1];
|
||||||
|
|
||||||
|
always @(posedge clk or posedge rst) begin
|
||||||
|
if (rst) q <= 0;
|
||||||
|
else if (load) q <= parallel_in;
|
||||||
|
else if (shift_en) begin
|
||||||
|
if (dir == 0) q <= {q[N-2:0], serial_in};
|
||||||
|
else q <= {serial_in, q[N-1:1]};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
48
shift_register/shift_register_tb.v
Normal file
48
shift_register/shift_register_tb.v
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
`include "./shift_register/shift_register.v"
|
||||||
|
|
||||||
|
module shift_register_tb;
|
||||||
|
reg clk, rst, load, shift_en, dir, serial_in;
|
||||||
|
reg [7:0] parallel_in;
|
||||||
|
wire [7:0] q;
|
||||||
|
wire serial_out;
|
||||||
|
|
||||||
|
shift_register register(
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.load(load),
|
||||||
|
.shift_en(shift_en),
|
||||||
|
.dir(dir),
|
||||||
|
.serial_in(serial_in),
|
||||||
|
.parallel_in(parallel_in),
|
||||||
|
.q(q),
|
||||||
|
.serial_out(serial_out)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
always #5 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("./shift_register/shift_register.vcd");
|
||||||
|
$dumpvars(0, shift_register_tb);
|
||||||
|
|
||||||
|
rst = 1; load = 0; shift_en = 1; dir = 0; serial_in = 0;
|
||||||
|
@(posedge clk);
|
||||||
|
|
||||||
|
$display("rst=%b, load=%b, shift_en=%b, dir=%b, serial_in=%b, q=%b", rst, load, shift_en, dir, serial_in, q);
|
||||||
|
|
||||||
|
rst = 0; load = 1; parallel_in = 64;
|
||||||
|
@(posedge clk);
|
||||||
|
|
||||||
|
$display("rst=%b, load=%b, shift_en=%b, dir=%b, serial_in=%b, q=%b", rst, load, shift_en, dir, serial_in, q);
|
||||||
|
|
||||||
|
load = 0; serial_in = 1;
|
||||||
|
@(posedge clk);
|
||||||
|
$display("rst=%b, load=%b, shift_en=%b, dir=%b, serial_in=%b, q=%b", rst, load, shift_en, dir, serial_in, q);
|
||||||
|
|
||||||
|
repeat(10) @(posedge clk);
|
||||||
|
$display("rst=%b, load=%b, shift_en=%b, dir=%b, serial_in=%b, q=%b", rst, load, shift_en, dir, serial_in, q);
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
33
stack/stack.v
Normal file
33
stack/stack.v
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
Stack
|
||||||
|
*/
|
||||||
|
|
||||||
|
module stack #(
|
||||||
|
parameter DEPTH = 256,
|
||||||
|
parameter W = 16
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
input push,
|
||||||
|
input pop,
|
||||||
|
input [W-1:0] value,
|
||||||
|
output reg [W-1:0] out
|
||||||
|
);
|
||||||
|
reg [W-1:0] mem [0:DEPTH-1];
|
||||||
|
reg [$clog2(DEPTH):0] sp; // bit extra para detectar overflow
|
||||||
|
|
||||||
|
wire full = (sp == DEPTH);
|
||||||
|
wire empty = (sp == 0);
|
||||||
|
|
||||||
|
always @(posedge clk or posedge rst) begin
|
||||||
|
if (rst) begin
|
||||||
|
sp <= 0;
|
||||||
|
end else if (push && !full) begin
|
||||||
|
mem[sp] <= value;
|
||||||
|
sp <= sp + 1;
|
||||||
|
end else if (pop && !empty) begin
|
||||||
|
out <= mem[sp - 1];
|
||||||
|
sp <= sp - 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
63
stack/stack_tb.v
Normal file
63
stack/stack_tb.v
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
Stack testbench
|
||||||
|
*/
|
||||||
|
|
||||||
|
`include "stack/stack.v"
|
||||||
|
|
||||||
|
module stack_tb;
|
||||||
|
reg clk, rst, push, pop;
|
||||||
|
reg[15:0] in;
|
||||||
|
wire [15:0] out;
|
||||||
|
|
||||||
|
stack stack1(
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.push(push),
|
||||||
|
.pop(pop),
|
||||||
|
.value(in),
|
||||||
|
.out(out)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
always #5 clk = ~clk;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("stack/stack.vcd");
|
||||||
|
$dumpvars(0, stack_tb);
|
||||||
|
|
||||||
|
rst = 1; push = 0; pop = 0; in = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
rst = 0;
|
||||||
|
$display("push=%b, pop=%b, value=%x, out=%x", push, pop, in, out);
|
||||||
|
|
||||||
|
push = 1; pop = 0; in = 69;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("push=%b, pop=%b, value=%x, out=%x", push, pop, in, out);
|
||||||
|
|
||||||
|
push = 1; pop = 0; in = 40;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("push=%b, pop=%b, value=%x, out=%x", push, pop, in, out);
|
||||||
|
|
||||||
|
push = 0; pop = 0; in = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("push=%b, pop=%b, value=%x, out=%x", push, pop, in, out);
|
||||||
|
|
||||||
|
push = 0; pop = 1; in = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("push=%b, pop=%b, value=%x, out=%x", push, pop, in, out);
|
||||||
|
push = 0; pop = 0; in = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("push=%b, pop=%b, value=%x, out=%x", push, pop, in, out);
|
||||||
|
|
||||||
|
|
||||||
|
push = 0; pop = 1; in = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("push=%b, pop=%b, value=%x, out=%x", push, pop, in, out);
|
||||||
|
push = 0; pop = 0; in = 0;
|
||||||
|
@(posedge clk); #1
|
||||||
|
$display("push=%b, pop=%b, value=%x, out=%x", push, pop, in, out);
|
||||||
|
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Reference in New Issue
Block a user