mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-05-05 07:25:00 -04:00
Make initial public release
This commit is contained in:
commit
715de60f4a
251 changed files with 881225 additions and 0 deletions
5
hw/application_fpga/core/timer/README.md
Normal file
5
hw/application_fpga/core/timer/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# timer
|
||||
A simple timer with prescaler written in Verilog.
|
||||
|
||||
## Introduction
|
||||
This core implements a simple timer with a prescaler. The purpose of the prescaler is to more easily time durations rather than cycles. If for example setting the timer to the clock frequency, the timer can cound seconds.
|
194
hw/application_fpga/core/timer/rtl/timer.v
Normal file
194
hw/application_fpga/core/timer/rtl/timer.v
Normal file
|
@ -0,0 +1,194 @@
|
|||
//======================================================================
|
||||
//
|
||||
// timer.v
|
||||
// --------
|
||||
// Top level wrapper for the timer core.
|
||||
//
|
||||
//
|
||||
// Author: Joachim Strombergson
|
||||
// Copyright (C) 2022 - Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module timer(
|
||||
input wire clk,
|
||||
input wire reset_n,
|
||||
|
||||
input wire cs,
|
||||
input wire we,
|
||||
|
||||
input wire [7 : 0] address,
|
||||
input wire [31 : 0] write_data,
|
||||
output wire [31 : 0] read_data,
|
||||
output wire ready
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Internal constant and parameter definitions.
|
||||
//----------------------------------------------------------------
|
||||
localparam ADDR_NAME0 = 8'h00;
|
||||
localparam ADDR_NAME1 = 8'h01;
|
||||
localparam ADDR_VERSION = 8'h02;
|
||||
|
||||
localparam ADDR_CTRL = 8'h08;
|
||||
localparam CTRL_START_BIT = 0;
|
||||
localparam CTRL_STOP_BIT = 1;
|
||||
|
||||
localparam ADDR_STATUS = 8'h09;
|
||||
localparam STATUS_READY_BIT = 0;
|
||||
|
||||
localparam ADDR_PRESCALER = 8'h0a;
|
||||
localparam ADDR_TIMER = 8'h0b;
|
||||
|
||||
localparam CORE_NAME0 = 32'h74696d65; // "time"
|
||||
localparam CORE_NAME1 = 32'h72202020; // "r "
|
||||
localparam CORE_VERSION = 32'h00000003;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Registers including update variables and write enable.
|
||||
//----------------------------------------------------------------
|
||||
reg [31 : 0] prescaler_reg;
|
||||
reg prescaler_we;
|
||||
|
||||
reg [31 : 0] timer_reg;
|
||||
reg timer_we;
|
||||
|
||||
reg start_reg;
|
||||
reg start_new;
|
||||
|
||||
reg stop_reg;
|
||||
reg stop_new;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Wires.
|
||||
//----------------------------------------------------------------
|
||||
reg [31 : 0] tmp_read_data;
|
||||
reg tmp_ready;
|
||||
|
||||
wire core_ready;
|
||||
wire [31 : 0] core_curr_prescaler;
|
||||
wire [31 : 0] core_curr_timer;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Concurrent connectivity for ports etc.
|
||||
//----------------------------------------------------------------
|
||||
assign read_data = tmp_read_data;
|
||||
assign ready = tmp_ready;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// core instantiation.
|
||||
//----------------------------------------------------------------
|
||||
timer_core core(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
.prescaler_value(prescaler_reg),
|
||||
.timer_value(timer_reg),
|
||||
.start(start_reg),
|
||||
.stop(stop_reg),
|
||||
.curr_prescaler(core_curr_prescaler),
|
||||
.curr_timer(core_curr_timer),
|
||||
.ready(core_ready)
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// reg_update
|
||||
//----------------------------------------------------------------
|
||||
always @ (posedge clk)
|
||||
begin : reg_update
|
||||
if (!reset_n) begin
|
||||
start_reg <= 1'h0;
|
||||
stop_reg <= 1'h0;
|
||||
prescaler_reg <= 32'h0;
|
||||
timer_reg <= 32'h0;
|
||||
end
|
||||
|
||||
else begin
|
||||
start_reg <= start_new;
|
||||
stop_reg <= stop_new;
|
||||
|
||||
if (prescaler_we) begin
|
||||
prescaler_reg <= write_data;
|
||||
end
|
||||
|
||||
if (timer_we) begin
|
||||
timer_reg <= write_data;
|
||||
end
|
||||
end
|
||||
end // reg_update
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// api
|
||||
//
|
||||
// The interface command decoding logic.
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : api
|
||||
start_new = 1'h0;
|
||||
stop_new = 1'h0;
|
||||
prescaler_we = 1'h0;
|
||||
timer_we = 1'h0;
|
||||
tmp_read_data = 32'h0;
|
||||
tmp_ready = 1'h0;
|
||||
|
||||
if (cs) begin
|
||||
tmp_ready = 1'h1;
|
||||
|
||||
if (we) begin
|
||||
if (address == ADDR_CTRL) begin
|
||||
start_new = write_data[CTRL_START_BIT];
|
||||
stop_new = write_data[CTRL_STOP_BIT];
|
||||
end
|
||||
|
||||
if (core_ready) begin
|
||||
if (address == ADDR_PRESCALER) begin
|
||||
prescaler_we = 1'h1;
|
||||
end
|
||||
|
||||
if (address == ADDR_TIMER) begin
|
||||
timer_we = 1'h1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else begin
|
||||
if (address == ADDR_NAME0) begin
|
||||
tmp_read_data = CORE_NAME0;
|
||||
end
|
||||
|
||||
if (address == ADDR_NAME1) begin
|
||||
tmp_read_data = CORE_NAME1;
|
||||
end
|
||||
|
||||
if (address == ADDR_VERSION) begin
|
||||
tmp_read_data = CORE_VERSION;
|
||||
end
|
||||
|
||||
if (address == ADDR_STATUS) begin
|
||||
tmp_read_data = {31'h0, core_ready};
|
||||
end
|
||||
|
||||
if (address == ADDR_PRESCALER) begin
|
||||
tmp_read_data = core_curr_prescaler;
|
||||
end
|
||||
|
||||
if (address == ADDR_TIMER) begin
|
||||
tmp_read_data = core_curr_timer;
|
||||
end
|
||||
end
|
||||
end
|
||||
end // addr_decoder
|
||||
endmodule // timer
|
||||
|
||||
//======================================================================
|
||||
// EOF timer.v
|
||||
//======================================================================
|
225
hw/application_fpga/core/timer/rtl/timer_core.v
Normal file
225
hw/application_fpga/core/timer/rtl/timer_core.v
Normal file
|
@ -0,0 +1,225 @@
|
|||
//======================================================================
|
||||
//
|
||||
// timer_core.v
|
||||
// ------------
|
||||
// timer core.
|
||||
//
|
||||
//
|
||||
// Author: Joachim Strombergson
|
||||
// Copyright (C) 2022 - Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module timer_core(
|
||||
input wire clk,
|
||||
input wire reset_n,
|
||||
|
||||
input wire [31 : 0] prescaler_value,
|
||||
input wire [31 : 0] timer_value,
|
||||
input wire start,
|
||||
input wire stop,
|
||||
|
||||
output wire [31 : 0] curr_prescaler,
|
||||
output wire [31 : 0] curr_timer,
|
||||
|
||||
output wire ready
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Internal constant and parameter definitions.
|
||||
//----------------------------------------------------------------
|
||||
localparam CTRL_IDLE = 2'h0;
|
||||
localparam CTRL_PRESCALER = 2'h1;
|
||||
localparam CTRL_TIMER = 2'h2;
|
||||
localparam CTRL_DONE = 2'h3;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Registers including update variables and write enable.
|
||||
//----------------------------------------------------------------
|
||||
reg ready_reg;
|
||||
reg ready_new;
|
||||
reg ready_we;
|
||||
|
||||
reg [31 : 0] prescaler_reg;
|
||||
reg [31 : 0] prescaler_new;
|
||||
reg prescaler_we;
|
||||
reg prescaler_set;
|
||||
reg prescaler_dec;
|
||||
|
||||
reg [31 : 0] timer_reg;
|
||||
reg [31 : 0] timer_new;
|
||||
reg timer_we;
|
||||
reg timer_set;
|
||||
reg timer_dec;
|
||||
|
||||
reg [1 : 0] core_ctrl_reg;
|
||||
reg [1 : 0] core_ctrl_new;
|
||||
reg core_ctrl_we;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Concurrent connectivity for ports etc.
|
||||
//----------------------------------------------------------------
|
||||
assign curr_prescaler = prescaler_reg;
|
||||
assign curr_timer = timer_reg;
|
||||
assign ready = ready_reg;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// reg_update
|
||||
//----------------------------------------------------------------
|
||||
always @ (posedge clk)
|
||||
begin: reg_update
|
||||
if (!reset_n)
|
||||
begin
|
||||
ready_reg <= 1'h1;
|
||||
prescaler_reg <= 32'h0;
|
||||
timer_reg <= 32'h0;
|
||||
core_ctrl_reg <= CTRL_IDLE;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (ready_we) begin
|
||||
ready_reg <= ready_new;
|
||||
end
|
||||
|
||||
if (prescaler_we) begin
|
||||
prescaler_reg <= prescaler_new;
|
||||
end
|
||||
|
||||
if (timer_we) begin
|
||||
timer_reg <= timer_new;
|
||||
end
|
||||
|
||||
if (core_ctrl_we) begin
|
||||
core_ctrl_reg <= core_ctrl_new;
|
||||
end
|
||||
end
|
||||
end // reg_update
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// prescaler_ctr
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : prescaler_ctr
|
||||
prescaler_new = 32'h0;
|
||||
prescaler_we = 1'h0;
|
||||
|
||||
if (prescaler_set) begin
|
||||
prescaler_new = prescaler_value;
|
||||
prescaler_we = 1'h1;
|
||||
end
|
||||
else if (prescaler_dec) begin
|
||||
prescaler_new = prescaler_reg - 1'h1;
|
||||
prescaler_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// timer_ctr
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : timer_ctr
|
||||
timer_new = 32'h0;
|
||||
timer_we = 1'h0;
|
||||
|
||||
if (timer_set) begin
|
||||
timer_new = timer_value;
|
||||
timer_we = 1'h1;
|
||||
end
|
||||
else if (timer_dec) begin
|
||||
timer_new = timer_reg - 1'h1;
|
||||
timer_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Core control FSM.
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : core_ctrl
|
||||
ready_new = 1'h0;
|
||||
ready_we = 1'h0;
|
||||
prescaler_set = 1'h0;
|
||||
prescaler_dec = 1'h0;
|
||||
timer_set = 1'h0;
|
||||
timer_dec = 1'h0;
|
||||
core_ctrl_new = CTRL_IDLE;
|
||||
core_ctrl_we = 1'h0;
|
||||
|
||||
case (core_ctrl_reg)
|
||||
CTRL_IDLE: begin
|
||||
if (start)
|
||||
begin
|
||||
ready_new = 1'h0;
|
||||
ready_we = 1'h1;
|
||||
prescaler_set = 1'h1;
|
||||
timer_set = 1'h1;
|
||||
core_ctrl_new = CTRL_PRESCALER;
|
||||
core_ctrl_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
CTRL_PRESCALER: begin
|
||||
if (stop) begin
|
||||
core_ctrl_new = CTRL_DONE;
|
||||
core_ctrl_we = 1'h1;
|
||||
end
|
||||
else begin
|
||||
if (prescaler_reg == 0) begin
|
||||
core_ctrl_new = CTRL_TIMER;
|
||||
core_ctrl_we = 1'h1;
|
||||
end
|
||||
else begin
|
||||
prescaler_dec = 1'h1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
CTRL_TIMER: begin
|
||||
if (stop) begin
|
||||
core_ctrl_new = CTRL_DONE;
|
||||
core_ctrl_we = 1'h1;
|
||||
end
|
||||
else begin
|
||||
if (timer_reg == 0) begin
|
||||
core_ctrl_new = CTRL_DONE;
|
||||
core_ctrl_we = 1'h1;
|
||||
end
|
||||
else begin
|
||||
prescaler_set = 1'h1;
|
||||
timer_dec = 1'h1;
|
||||
core_ctrl_new = CTRL_PRESCALER;
|
||||
core_ctrl_we = 1'h1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
CTRL_DONE: begin
|
||||
ready_new = 1'h1;
|
||||
ready_we = 1'h1;
|
||||
core_ctrl_new = CTRL_IDLE;
|
||||
core_ctrl_we = 1'h1;
|
||||
end
|
||||
|
||||
default: begin
|
||||
end
|
||||
endcase // case (core_ctrl_reg)
|
||||
end // core_ctrl
|
||||
|
||||
endmodule // timer_core
|
||||
|
||||
//======================================================================
|
||||
// EOF timer_core.v
|
||||
//======================================================================
|
293
hw/application_fpga/core/timer/tb/tb_timer.v
Normal file
293
hw/application_fpga/core/timer/tb/tb_timer.v
Normal file
|
@ -0,0 +1,293 @@
|
|||
//======================================================================
|
||||
//
|
||||
// tb_timer.v
|
||||
// -----------
|
||||
// Testbench for the timer top level wrapper.
|
||||
//
|
||||
//
|
||||
// Author: Joachim Strombergson
|
||||
// Copyright (C) 2022 - Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module tb_timer();
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Internal constant and parameter definitions.
|
||||
//----------------------------------------------------------------
|
||||
parameter DEBUG = 0;
|
||||
parameter DUMP_WAIT = 0;
|
||||
|
||||
parameter CLK_HALF_PERIOD = 1;
|
||||
parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
|
||||
|
||||
localparam ADDR_NAME0 = 8'h00;
|
||||
localparam ADDR_NAME1 = 8'h01;
|
||||
localparam ADDR_VERSION = 8'h02;
|
||||
|
||||
localparam ADDR_CTRL = 8'h08;
|
||||
localparam CTRL_NEXT_BIT = 0;
|
||||
|
||||
localparam ADDR_STATUS = 8'h09;
|
||||
localparam STATUS_READY_BIT = 0;
|
||||
|
||||
localparam ADDR_CONFIG = 8'h0a;
|
||||
localparam CONFIG_ENCDEC_BIT = 0;
|
||||
|
||||
localparam ADDR_KEY0 = 8'h10;
|
||||
localparam ADDR_KEY1 = 8'h11;
|
||||
localparam ADDR_KEY2 = 8'h12;
|
||||
localparam ADDR_KEY3 = 8'h13;
|
||||
|
||||
localparam ADDR_BLOCK0 = 8'h20;
|
||||
localparam ADDR_BLOCK1 = 8'h21;
|
||||
|
||||
localparam ADDR_RESULT0 = 8'h30;
|
||||
localparam ADDR_RESULT1 = 8'h31;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Register and Wire declarations.
|
||||
//----------------------------------------------------------------
|
||||
reg [31 : 0] cycle_ctr;
|
||||
reg [31 : 0] error_ctr;
|
||||
reg [31 : 0] tc_ctr;
|
||||
reg tb_monitor;
|
||||
|
||||
reg tb_clk;
|
||||
reg tb_reset_n;
|
||||
reg tb_cs;
|
||||
reg tb_we;
|
||||
reg [7 : 0] tb_address;
|
||||
reg [31 : 0] tb_write_data;
|
||||
wire [31 : 0] tb_read_data;
|
||||
|
||||
reg [31 : 0] read_data;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Device Under Test.
|
||||
//----------------------------------------------------------------
|
||||
timer dut(
|
||||
.clk(tb_clk),
|
||||
.reset_n(tb_reset_n),
|
||||
|
||||
.cs(tb_cs),
|
||||
.we(tb_we),
|
||||
|
||||
.address(tb_address),
|
||||
.write_data(tb_write_data),
|
||||
.read_data(tb_read_data)
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// clk_gen
|
||||
//
|
||||
// Always running clock generator process.
|
||||
//----------------------------------------------------------------
|
||||
always
|
||||
begin : clk_gen
|
||||
#CLK_HALF_PERIOD;
|
||||
tb_clk = !tb_clk;
|
||||
end // clk_gen
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// sys_monitor()
|
||||
//
|
||||
// An always running process that creates a cycle counter and
|
||||
// conditionally displays information about the DUT.
|
||||
//----------------------------------------------------------------
|
||||
always
|
||||
begin : sys_monitor
|
||||
cycle_ctr = cycle_ctr + 1;
|
||||
#(CLK_PERIOD);
|
||||
if (tb_monitor)
|
||||
begin
|
||||
dump_dut_state();
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// dump_dut_state()
|
||||
//
|
||||
// Dump the state of the dump when needed.
|
||||
//----------------------------------------------------------------
|
||||
task dump_dut_state;
|
||||
begin
|
||||
$display("State of DUT");
|
||||
$display("------------");
|
||||
$display("Cycle: %08d", cycle_ctr);
|
||||
$display("");
|
||||
end
|
||||
endtask // dump_dut_state
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// reset_dut()
|
||||
//
|
||||
// Toggle reset to put the DUT into a well known state.
|
||||
//----------------------------------------------------------------
|
||||
task reset_dut;
|
||||
begin
|
||||
$display("--- Toggle reset.");
|
||||
tb_reset_n = 0;
|
||||
#(2 * CLK_PERIOD);
|
||||
tb_reset_n = 1;
|
||||
end
|
||||
endtask // reset_dut
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// display_test_result()
|
||||
//
|
||||
// Display the accumulated test results.
|
||||
//----------------------------------------------------------------
|
||||
task display_test_result;
|
||||
begin
|
||||
if (error_ctr == 0)
|
||||
begin
|
||||
$display("--- All %02d test cases completed successfully", tc_ctr);
|
||||
end
|
||||
else
|
||||
begin
|
||||
$display("--- %02d tests completed - %02d test cases did not complete successfully.",
|
||||
tc_ctr, error_ctr);
|
||||
end
|
||||
end
|
||||
endtask // display_test_result
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// init_sim()
|
||||
//
|
||||
// Initialize all counters and testbed functionality as well
|
||||
// as setting the DUT inputs to defined values.
|
||||
//----------------------------------------------------------------
|
||||
task init_sim;
|
||||
begin
|
||||
cycle_ctr = 0;
|
||||
error_ctr = 0;
|
||||
tc_ctr = 0;
|
||||
tb_monitor = 0;
|
||||
|
||||
tb_clk = 1'h0;
|
||||
tb_reset_n = 1'h1;
|
||||
tb_cs = 1'h0;
|
||||
tb_we = 1'h0;
|
||||
tb_address = 8'h0;
|
||||
tb_write_data = 32'h0;
|
||||
end
|
||||
endtask // init_sim
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// write_word()
|
||||
//
|
||||
// Write the given word to the DUT using the DUT interface.
|
||||
//----------------------------------------------------------------
|
||||
task write_word(input [11 : 0] address,
|
||||
input [31 : 0] word);
|
||||
begin
|
||||
if (DEBUG)
|
||||
begin
|
||||
$display("--- Writing 0x%08x to 0x%02x.", word, address);
|
||||
$display("");
|
||||
end
|
||||
|
||||
tb_address = address;
|
||||
tb_write_data = word;
|
||||
tb_cs = 1;
|
||||
tb_we = 1;
|
||||
#(2 * CLK_PERIOD);
|
||||
tb_cs = 0;
|
||||
tb_we = 0;
|
||||
end
|
||||
endtask // write_word
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// read_word()
|
||||
//
|
||||
// Read a data word from the given address in the DUT.
|
||||
// the word read will be available in the global variable
|
||||
// read_data.
|
||||
//----------------------------------------------------------------
|
||||
task read_word(input [11 : 0] address);
|
||||
begin
|
||||
tb_address = address;
|
||||
tb_cs = 1;
|
||||
tb_we = 0;
|
||||
#(CLK_PERIOD);
|
||||
read_data = tb_read_data;
|
||||
tb_cs = 0;
|
||||
|
||||
if (DEBUG)
|
||||
begin
|
||||
$display("--- Reading 0x%08x from 0x%02x.", read_data, address);
|
||||
$display("");
|
||||
end
|
||||
end
|
||||
endtask // read_word
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// wait_ready()
|
||||
//
|
||||
// Wait for the ready flag to be set in dut.
|
||||
//----------------------------------------------------------------
|
||||
task wait_ready;
|
||||
begin : wready
|
||||
read_word(ADDR_STATUS);
|
||||
while (read_data == 0)
|
||||
read_word(ADDR_STATUS);
|
||||
end
|
||||
endtask // wait_ready
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// test1()
|
||||
//----------------------------------------------------------------
|
||||
task test1;
|
||||
begin
|
||||
tc_ctr = tc_ctr + 1;
|
||||
|
||||
$display("");
|
||||
$display("--- test1: started.");
|
||||
|
||||
$display("--- test1: completed.");
|
||||
$display("");
|
||||
end
|
||||
endtask // tes1
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// timer_test
|
||||
//----------------------------------------------------------------
|
||||
initial
|
||||
begin : timer_test
|
||||
$display("");
|
||||
$display(" -= Testbench for timer started =-");
|
||||
$display(" =============================");
|
||||
$display("");
|
||||
|
||||
init_sim();
|
||||
reset_dut();
|
||||
test1();
|
||||
|
||||
display_test_result();
|
||||
$display("");
|
||||
$display(" -= Testbench for timer started =-");
|
||||
$display(" =============================");
|
||||
$display("");
|
||||
$finish;
|
||||
end // timer_test
|
||||
endmodule // tb_timer
|
||||
|
||||
//======================================================================
|
||||
// EOF tb_timer.v
|
||||
//======================================================================
|
247
hw/application_fpga/core/timer/tb/tb_timer_core.v
Normal file
247
hw/application_fpga/core/timer/tb/tb_timer_core.v
Normal file
|
@ -0,0 +1,247 @@
|
|||
//======================================================================
|
||||
//
|
||||
// tb_timer_core.v
|
||||
// --------------
|
||||
// Testbench for the timer core.
|
||||
//
|
||||
//
|
||||
// Author: Joachim Strombergson
|
||||
// Copyright (C) 2022 - Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module tb_timer_core();
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Internal constant and parameter definitions.
|
||||
//----------------------------------------------------------------
|
||||
parameter DEBUG = 0;
|
||||
parameter DUMP_WAIT = 0;
|
||||
|
||||
parameter CLK_HALF_PERIOD = 1;
|
||||
parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Register and Wire declarations.
|
||||
//----------------------------------------------------------------
|
||||
reg [31 : 0] cycle_ctr;
|
||||
reg [31 : 0] error_ctr;
|
||||
reg [31 : 0] tc_ctr;
|
||||
reg tb_monitor;
|
||||
|
||||
reg tb_clk;
|
||||
reg tb_reset_n;
|
||||
reg tb_start;
|
||||
reg tb_stop;
|
||||
reg [31 : 0] tb_prescaler;
|
||||
reg [31 : 0] tb_timer;
|
||||
wire [31 : 0] tb_curr_prescaler;
|
||||
wire [31 : 0] tb_curr_timer;
|
||||
wire tb_ready;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Device Under Test.
|
||||
//----------------------------------------------------------------
|
||||
timer_core dut(
|
||||
.clk(tb_clk),
|
||||
.reset_n(tb_reset_n),
|
||||
.prescaler_value(tb_prescaler),
|
||||
.timer_value(tb_timer),
|
||||
.start(tb_start),
|
||||
.stop(tb_stop),
|
||||
.curr_prescaler(tb_curr_prescaler),
|
||||
.curr_timer(tb_curr_timer),
|
||||
.ready(tb_ready)
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// clk_gen
|
||||
//
|
||||
// Always running clock generator process.
|
||||
//----------------------------------------------------------------
|
||||
always
|
||||
begin : clk_gen
|
||||
#CLK_HALF_PERIOD;
|
||||
tb_clk = !tb_clk;
|
||||
end // clk_gen
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// sys_monitor()
|
||||
//
|
||||
// An always running process that creates a cycle counter and
|
||||
// conditionally displays information about the DUT.
|
||||
//----------------------------------------------------------------
|
||||
always
|
||||
begin : sys_monitor
|
||||
cycle_ctr = cycle_ctr + 1;
|
||||
#(CLK_PERIOD);
|
||||
if (tb_monitor)
|
||||
begin
|
||||
dump_dut_state();
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// dump_dut_state()
|
||||
//
|
||||
// Dump the state of the dump when needed.
|
||||
//----------------------------------------------------------------
|
||||
task dump_dut_state;
|
||||
begin
|
||||
$display("State of DUT");
|
||||
$display("------------");
|
||||
$display("Cycle: %08d", cycle_ctr);
|
||||
$display("");
|
||||
$display("Inputs and outputs:");
|
||||
$display("start: 0x%1x, stop: 0x%1x, ready: 0x%1x",
|
||||
dut.start, dut.stop, dut.ready);
|
||||
$display("prescaler_value: 0x%08x, timer_value: 0x%08x",
|
||||
dut.prescaler_value, dut.timer_value);
|
||||
$display("");
|
||||
$display("Internal state:");
|
||||
$display("prescaler_reg: 0x%08x, prescaler_new: 0x%08x",
|
||||
dut.prescaler_reg, dut.prescaler_new);
|
||||
$display("prescaler_set: 0x%1x, prescaler_dec: 0x%1x",
|
||||
dut.prescaler_set, dut.prescaler_dec);
|
||||
$display("");
|
||||
$display("timer_reg: 0x%08x, timer_new: 0x%08x",
|
||||
dut.timer_reg, dut.timer_new);
|
||||
$display("timer_set: 0x%1x, timer_dec: 0x%1x",
|
||||
dut.timer_set, dut.timer_dec);
|
||||
$display("");
|
||||
$display("core_ctrl_reg: 0x%02x, core_ctrl_new: 0x%02x, core_ctrl_we: 0x%1x",
|
||||
dut.core_ctrl_reg, dut.core_ctrl_new, dut.core_ctrl_we);
|
||||
$display("");
|
||||
$display("");
|
||||
end
|
||||
endtask // dump_dut_state
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// reset_dut()
|
||||
//
|
||||
// Toggle reset to put the DUT into a well known state.
|
||||
//----------------------------------------------------------------
|
||||
task reset_dut;
|
||||
begin
|
||||
$display("--- DUT before reset:");
|
||||
dump_dut_state();
|
||||
$display("--- Toggling reset.");
|
||||
tb_reset_n = 0;
|
||||
#(2 * CLK_PERIOD);
|
||||
tb_reset_n = 1;
|
||||
$display("--- DUT after reset:");
|
||||
dump_dut_state();
|
||||
end
|
||||
endtask // reset_dut
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// wait_ready()
|
||||
//
|
||||
// Wait for the ready flag in the dut to be set.
|
||||
//
|
||||
// Note: It is the callers responsibility to call the function
|
||||
// when the dut is actively processing and will in fact at some
|
||||
// point set the flag.
|
||||
//----------------------------------------------------------------
|
||||
task wait_ready;
|
||||
begin
|
||||
#(2 * CLK_PERIOD);
|
||||
while (!tb_ready)
|
||||
begin
|
||||
#(CLK_PERIOD);
|
||||
if (DUMP_WAIT)
|
||||
begin
|
||||
dump_dut_state();
|
||||
end
|
||||
end
|
||||
end
|
||||
endtask // wait_ready
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// init_sim()
|
||||
//
|
||||
// Initialize all counters and testbed functionality as well
|
||||
// as setting the DUT inputs to defined values.
|
||||
//----------------------------------------------------------------
|
||||
task init_sim;
|
||||
begin
|
||||
cycle_ctr = 0;
|
||||
error_ctr = 0;
|
||||
tc_ctr = 0;
|
||||
tb_monitor = 0;
|
||||
|
||||
tb_clk = 0;
|
||||
tb_reset_n = 1;
|
||||
|
||||
tb_start = 1'h0;
|
||||
tb_stop = 1'h0;
|
||||
tb_prescaler = 32'h0;
|
||||
tb_timer = 32'h0;
|
||||
end
|
||||
endtask // init_sim
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// test()
|
||||
// Runs an encipher, decipher test with given key and plaintext
|
||||
// The generated ciphertext is verified with the given ciphertet.
|
||||
// The generated plaintxt is also verified against the
|
||||
// given plaintext.
|
||||
//----------------------------------------------------------------
|
||||
task test1;
|
||||
begin
|
||||
tc_ctr = tc_ctr + 1;
|
||||
tb_monitor = 1;
|
||||
|
||||
$display("--- test1 started.");
|
||||
dump_dut_state();
|
||||
tb_prescaler = 32'h6;
|
||||
tb_timer = 32'h9;
|
||||
#(CLK_PERIOD);
|
||||
tb_start = 1'h1;
|
||||
#(CLK_PERIOD);
|
||||
tb_start = 1'h0;
|
||||
wait_ready();
|
||||
#(CLK_PERIOD);
|
||||
tb_monitor = 0;
|
||||
$display("--- test1 completed.");
|
||||
$display("");
|
||||
end
|
||||
endtask // test1
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// timer_core_test
|
||||
//
|
||||
// Test vectors from:
|
||||
//----------------------------------------------------------------
|
||||
initial
|
||||
begin : timer_core_test
|
||||
$display("--- Simulation of TIMER core started.");
|
||||
$display("");
|
||||
|
||||
init_sim();
|
||||
reset_dut();
|
||||
|
||||
test1();
|
||||
|
||||
$display("");
|
||||
$display("--- Simulation of timer core completed.");
|
||||
$finish;
|
||||
end // timer_core_test
|
||||
endmodule // tb_timer_core
|
||||
|
||||
//======================================================================
|
||||
// EOF tb_timer_core.v
|
||||
//======================================================================
|
75
hw/application_fpga/core/timer/toolruns/Makefile
Executable file
75
hw/application_fpga/core/timer/toolruns/Makefile
Executable file
|
@ -0,0 +1,75 @@
|
|||
#===================================================================
|
||||
#
|
||||
# Makefile
|
||||
# --------
|
||||
# Makefile for building the timer core and top simulations.
|
||||
#
|
||||
#
|
||||
# Author: Joachim Strombergson
|
||||
# Copyright (C) 2022 - Tillitis AB
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
#===================================================================
|
||||
|
||||
CORE_SRC=../rtl/timer_core.v
|
||||
TB_CORE_SRC =../tb/tb_timer_core.v
|
||||
|
||||
TOP_SRC=../rtl/timer.v $(CORE_SRC)
|
||||
TB_TOP_SRC =../tb/tb_timer.v
|
||||
|
||||
CC = iverilog
|
||||
CC_FLAGS = -Wall
|
||||
|
||||
LINT = verilator
|
||||
LINT_FLAGS = +1364-2001ext+ --lint-only -Wall -Wno-fatal -Wno-DECLFILENAME
|
||||
|
||||
|
||||
all: top.sim core.sim
|
||||
|
||||
|
||||
top.sim: $(TB_TOP_SRC) $(TOP_SRC)
|
||||
$(CC) $(CC_FLAGS) -o top.sim $(TB_TOP_SRC) $(TOP_SRC)
|
||||
|
||||
|
||||
core.sim: $(TB_CORE_SRC) $(CORE_SRC)
|
||||
$(CC) $(CC_FLAGS) -o core.sim $(TB_CORE_SRC) $(CORE_SRC)
|
||||
|
||||
|
||||
sim-top: top.sim
|
||||
./top.sim
|
||||
|
||||
|
||||
sim-core: core.sim
|
||||
./core.sim
|
||||
|
||||
|
||||
lint-core: $(CORE_SRC)
|
||||
$(LINT) $(LINT_FLAGS) $(CORE_SRC)
|
||||
|
||||
|
||||
lint-top: $(TOP_SRC)
|
||||
$(LINT) $(LINT_FLAGS) $(TOP_SRC)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f top.sim
|
||||
rm -f core.sim
|
||||
|
||||
|
||||
help:
|
||||
@echo "Build system for simulation of Prince core"
|
||||
@echo ""
|
||||
@echo "Supported targets:"
|
||||
@echo "------------------"
|
||||
@echo "all: Build all simulation targets."
|
||||
@echo "top.sim: Build top level simulation target."
|
||||
@echo "core.sim: Build core level simulation target."
|
||||
@echo "sim-top: Run top level simulation."
|
||||
@echo "sim-core: Run core level simulation."
|
||||
@echo "lint-core: Lint core rtl source files."
|
||||
@echo "lint-core: Lint top rtl source files."
|
||||
@echo "clean: Delete all built files."
|
||||
|
||||
#===================================================================
|
||||
# EOF Makefile
|
||||
#===================================================================
|
Loading…
Add table
Add a link
Reference in a new issue