1. 基礎概念問題
1.1 ミーリ状態機械とムーア状態機械の特性と相互関係について説明してください。
ムーア状態機械:出力が現在の状態のみに依存する状態機械。
ミーリ状態機械:出力が現在の状態だけでなく入力にも依存する状態機械。
ミーリ機械とムーア機械は相互に変換可能です。任意のミーリ機械に対して等価なムーア機械が存在し、そのムーア機械の状態数は対応するミーリ機械の状態数と出力数の積を上限とします。
1.2 SRAMの特性と、実際の応用におけるレジスタファイル論理との長所と短所の比較について説明してください。
SRAMの特性:動作速度が高速であり、電源が供給されている限り書き込まれた情報は保持され、リフレッシュ回路が不要です。読み出し時に元の情報が破壊されることがなく、一度書き込むと何度でも読み出せます。しかし、集積度は低く、消費電力は大きいという欠点があります。
レジスタファイル論理:実装がよりシンプルですが、プロセス最適化されたSRAMには性能が及びません。一方、SRAMは性能に優れますが、実装がやや複雑になります。
1.3 ゲーテッドクロックの一般的な回路構造と適用範囲について説明してください。
ゲーテッドクロックの回路構造:
- 制御信号とクロック信号を直接AND演算する方式(グリッチが発生するため、実際にはほとんど使用されません)
- ラッチャベースのクロックゲーティング方式(ASIC設計でよく使用)
- フリップフロップベースのクロックゲーティング方式(FPGA設計でよく使用)
1.4 AHBバスとAPBバスの基本特性と、実際のSoCシステムにおける適用場面について説明してください。
AHB(Advanced High-performance Bus):高速バスで、通常高速周辺機器の接続に使用されます。
APB(Advanced Peripheral Bus):低速バスで、通常低速周辺機器の接続に使用されます。
SoCシステムでは、AHBバスにARMプロセッサ、RAM、DMAコントローラなどのデバイスが接続され、AHB2APBブリッジを介してAPBバスに接続されます。APBバスにはUART、タイマなどの低速デバイスが接続されます。
2. Verilog HDLを用いた論理回路設計
2.1 平方根計算回路
32ビット非負整数の平方根を計算する順序論理回路を設計します。入力xに対して、y = floor(sqrt(x))を計算します。ここでyは、2乗した値がxを超えない最大の非負整数です。
例:
- 入力x = 256、出力y = 16
- 入力x = 255、出力y = 15
- 入力x = 2147483648、出力y = 46340
- 入力x = 4294967295、出力y = 65535
トップモジュール名はsqrt_calculatorとし、入出力機能は以下のように定義します:
| 名前 | 方向 | ビット幅 | 説明 |
|---|---|---|---|
| clk | I | 1 | システムクロック |
| rst_n | I | 1 | システム非同期リセット、Low有効 |
| data_valid | I | 1 | 入力データ有効指示 |
| input_val | I | 32 | 入力値(被開平数) |
| result_valid | O | 1 | 出力データ有効指示 |
| output_val | O | 16 | 出力結果 |
設計要件:
- Verilog実装コードは合成可能であること
- 複数のデータ入力を処理できること
- データ入力から結果出力までの遅延サイクル数をできるだけ少なくすること
設計アプローチ:
初期検討したCORDICアルゴリズムやニュートン法では、32ビット入力に対して収束しない問題があったため、逐次近似法を採用しました。これは逆方向のニュートン法と理解できます。
逐次近似アルゴリズムの流れ:まずデータ入力を受け取り、試行値と確定値を設定し、上位ビットから順に各ビットを1に設定します。試行値の2乗を入力データと比較し、試行値の2乗が入力値より大きい場合はそのビットを0に、そうでない場合は1に設定します。これを最下位ビットまで繰り返します。
コード実装:
module sqrt_calculator (
input clk,
input rst_n,
input data_valid,
input [31:0] input_val,
output reg result_valid,
output reg [15:0] output_val
);
parameter DATA_WIDTH = 32;
parameter RESULT_WIDTH = 16;
reg [DATA_WIDTH-1:0] data_reg [RESULT_WIDTH:1];
reg [RESULT_WIDTH-1:0] trial_val [RESULT_WIDTH:1];
reg [RESULT_WIDTH-1:0] result_val [RESULT_WIDTH:1];
reg valid_flag [RESULT_WIDTH:1];
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
data_reg[RESULT_WIDTH] <= 0;
trial_val[RESULT_WIDTH] <= 0;
result_val[RESULT_WIDTH] <= 0;
valid_flag[RESULT_WIDTH] <= 0;
end
else if(data_valid)
begin
data_reg[RESULT_WIDTH] <= input_val;
trial_val[RESULT_WIDTH] <= {1'b1,{(RESULT_WIDTH-1){1'b0}}};
result_val[RESULT_WIDTH] <= 0;
valid_flag[RESULT_WIDTH] <= 1;
end
else
begin
data_reg[RESULT_WIDTH] <= 0;
trial_val[RESULT_WIDTH] <= 0;
result_val[RESULT_WIDTH] <= 0;
valid_flag[RESULT_WIDTH] <= 0;
end
end
generate
genvar i;
for(i=RESULT_WIDTH-1;i>=1;i=i-1)
begin:SQRT_STAGE
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
data_reg[i] <= 0;
trial_val[i] <= 0;
result_val[i] <= 0;
valid_flag[i] <= 0;
end
else if(valid_flag[i+1])
begin
if(trial_val[i+1]*trial_val[i+1] > data_reg[i+1])
begin
trial_val[i] <= {result_val[i+1][RESULT_WIDTH-1:i],1'b1,{{i-1}{1'b0}}};
result_val[i] <= result_val[i+1];
end
else
begin
trial_val[i] <= {trial_val[i+1][RESULT_WIDTH-1:i],1'b1,{{i-1}{1'b0}}};
result_val[i] <= trial_val[i+1];
end
data_reg[i] <= data_reg[i+1];
valid_flag[i] <= 1;
end
else
begin
valid_flag[i] <= 0;
data_reg[i] <= 0;
result_val[i] <= 0;
trial_val[i] <= 0;
end
end
end
endgenerate
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
output_val <= 0;
result_valid <= 0;
end
else if(valid_flag[1])
begin
if(trial_val[1]*trial_val[1] > data_reg[1])
begin
output_val <= result_val[1];
result_valid <= 1;
end
else
begin
output_val <= {result_val[1][RESULT_WIDTH-1:1],trial_val[1][0]};
result_valid <= 1;
end
end
else
begin
output_val <= 0;
result_valid <= 0;
end
end
endmodule
テストベンチ:
module sqrt_testbench ();
reg clk, rst_n, data_valid;
reg [31:0] input_val;
wire result_valid;
wire [15:0] output_val;
initial begin
clk <= 1'b0;
rst_n <= 1'b0;
data_valid <= 1'b0;
input_val <= 0;
#30
rst_n <= 1'b1;
data_valid <= 1'b1;
input_val <= 256;
#20
input_val <= 255;
#20
input_val <= 2147483648;
#20
input_val <= 4294967295;
end
always #10 clk <= ~clk;
sqrt_calculator u_sqrt(
.clk(clk),
.rst_n(rst_n),
.data_valid(data_valid),
.input_val(input_val),
.result_valid(result_valid),
.output_val(output_val)
);
endmodule
2.2 データソート回路
入力された32個の8ビット符号なし整数を小さい順にソートする順序論理回路を設計します。同じ値のデータが複数ある場合は、それらの順序は問いません。
例:
- 入力32個のデータ:31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 2, 2, 4, 4, 4, 4, 8, 16, 8, 16, 32, 32, 0, 10, 20, 30
- 出力32個のデータ:0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 7, 8, 8, 9, 10, 11, 13, 15, 16, 16, 17, 19, 20, 21, 23, 25, 27, 29, 30, 31, 32, 32
トップモジュール名はdata_sorterとし、入出力機能は以下のように定義します:
| 名前 | 方向 | ビット幅 | 説明 |
|---|---|---|---|
| clk | I | 1 | システムクロック |
| rst_n | I | 1 | システム非同期リセット、Low有効 |
| input_valid | I | 1 | 入力データ有効指示 |
| data_in[0:31] | I | 8 | 入力データ配列 |
| output_valid | O | 1 | 出力データ有効指示 |
| data_out[0:31] | O | 8 | 出力データ配列(ソート済み) |
設計要件:
- Verilog実装コードは合成可能であること
- 論理リソースと遅延のトレードオフを考慮し、データ入力から結果出力までの遅延サイクル数をできるだけ少なくすること
設計アプローチ:
双調ソーティングネットワークを検討しましたが、重複データの扱いに課題がありました。バブルソートはリソース消費は少ないですが、遅延が大きくなるため、状態機械を用いた制御で実装します。
コード実装:
module data_sorter (
input clk,
input rst_n,
input input_valid,
input [7:0] data_in[0:31],
output reg output_valid,
output [7:0] data_out[0:31]
);
parameter IDLE = 2'b00;
parameter LOAD = 2'b01;
parameter SORT = 2'b10;
parameter DONE = 2'b11;
reg [4:0] counter, pass_count;
reg [7:0] sort_buffer[0:31];
reg [1:0] current_state, next_state;
reg reset_signal, load_signal, swap_signal;
integer i;
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
always @(posedge clk) begin
if(reset_signal == 1'b1) begin
for (i = 0; i < 32; i = i + 1) begin
sort_buffer[i] <= 0;
end
pass_count <= 0;
counter <= 0;
end
else if(load_signal == 1'b1) begin
for (i = 0; i < 32; i = i + 1) begin
sort_buffer[i] <= data_in[i];
end
pass_count <= 31;
counter <= 0;
end
else if(swap_signal == 1'b1) begin
if(counter < pass_count) begin
counter <= counter + 1;
if(sort_buffer[counter+1] < sort_buffer[counter]) begin
sort_buffer[counter+1] <= sort_buffer[counter];
sort_buffer[counter] <= sort_buffer[counter+1];
end
end
else begin
counter <= 1;
pass_count <= pass_count - 1;
if(sort_buffer[1] < sort_buffer[0]) begin
sort_buffer[1] <= sort_buffer[0];
sort_buffer[0] <= sort_buffer[1];
end
end
end
end
always @(counter, current_state, pass_count, input_valid) begin
next_state <= IDLE;
case (current_state)
IDLE : begin
reset_signal <= 1'b1;
output_valid <= 1'b0;
next_state <= LOAD;
end
LOAD : begin
reset_signal <= 1'b0;
if(input_valid == 1'b1) begin
load_signal <= 1'b1;
output_valid <= 1'b0;
next_state <= SORT;
end
else begin
next_state <= LOAD;
end
end
SORT : begin
swap_signal <= 1'b1;
load_signal <= 1'b0;
if(pass_count == 1 && counter == 1) begin
next_state <= DONE;
output_valid <= 1'b1;
end
else begin
next_state <= SORT;
end
end
DONE : begin
next_state <= LOAD;
swap_signal <= 1'b0;
end
default : begin
next_state <= IDLE;
end
endcase
end
genvar j;
generate
for(j = 0; j < 32; j = j + 1) begin:OUTPUT_ASSIGN
assign data_out[j] = sort_buffer[j];
end
endgenerate
endmodule
テストベンチ:
module sort_testbench ();
reg clk, rst_n, input_valid;
reg [7:0] data_in[0:31];
wire output_valid;
wire [7:0] data_out[0:31];
integer k;
initial begin
rst_n <= 1'b0;
clk <= 1'b0;
input_valid <= 1'b0;
data_in[0] <= 31;
data_in[1] <= 29;
data_in[2] <= 27;
data_in[3] <= 25;
data_in[4] <= 23;
data_in[5] <= 21;
data_in[6] <= 19;
data_in[7] <= 17;
data_in[8] <= 15;
data_in[9] <= 13;
data_in[10] <= 11;
data_in[11] <= 9;
data_in[12] <= 7;
data_in[13] <= 5;
data_in[14] <= 3;
data_in[15] <= 1;
data_in[16] <= 2;
data_in[17] <= 2;
data_in[18] <= 4;
data_in[19] <= 4;
data_in[20] <= 4;
data_in[21] <= 4;
data_in[22] <= 8;
data_in[23] <= 16;
data_in[24] <= 8;
data_in[25] <= 16;
data_in[26] <= 32;
data_in[27] <= 32;
data_in[28] <= 0;
data_in[29] <= 10;
data_in[30] <= 20;
data_in[31] <= 30;
#30
rst_n <= 1'b1;
input_valid <= 1'b1;
#20
input_valid <= 1'b0;
end
always #10 clk <= ~clk;
data_sorter u_sorter(
.clk(clk),
.rst_n(rst_n),
.input_valid(input_valid),
.data_in(data_in),
.output_valid(output_valid),
.data_out(data_out)
);
endmodule
2.3 ジグザグスキャン回路
8x8の行列ブロックをジグザグパターンでスキャンし、データを再配置する順序論理回路を設計します。入力は行優先方式の64個のデータで、出力はジグザグスキャン順のデータです。
例:
- 入力64個のデータ:1, 2, 3, 4, ..., 61, 62, 63, 64
- 出力64個のデータ:1, 2, 9, 17, 10, 3, ..., 62, 55, 48, 56, 63, 64
トップモジュール名はzigzag_scannerとし、入出力機能は以下のように定義します:
| 名前 | 方向 | ビット幅 | 説明 |
|---|---|---|---|
| clk | I | 1 | システムクロック |
| rst_n | I | 1 | システム非同期リセット、Low有効 |
| input_valid | I | 1 | 入力データ有効指示 |
| data_in | I | 10 | 入力データ |
| output_valid | O | 1 | 出力データ有効指示 |
| data_out | O | 10 | 出力データ |
設計要件:
- Verilog実装コードは合成可能であること
- SRAMを使用して入力データをキャッシュすること
- データ入力から結果出力までの遅延サイクル数をできるだけ少なくすること
設計アプローチ:
SRAMに64個のデータを保存し、入力時はアドレスを順次増加させ、読み出し時は状態機械でジグザグスキャンに対応するアドレス変化を実装します。
コード実装:
module zigzag_scanner (
input clk,
input rst_n,
input input_valid,
input [9:0] data_in,
output reg output_valid,
output [9:0] data_out
);
reg chip_select, write_enable, read_enable;
reg [5:0] address;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
address <= 6'b11_1111;
chip_select <= 1'b1;
write_enable <= 1'b0;
read_enable <= 1'b0;
output_valid <= 1'b0;
end
else if (input_valid) begin
write_enable <= 1'b1;
chip_select <= 1'b0;
address <= address + 1'b1;
end
else begin
output_valid <= 1'b1;
read_enable <= 1'b1;
case (address)
6'b11_1111 : address <= 6'b00_0000;
6'b00_0000 : address <= 6'b00_0001;
6'b00_0001 : address <= 6'b00_1000;
6'b00_1000 : address <= 6'b01_0000;
6'b01_0000 : address <= 6'b00_1001;
6'b00_1001 : address <= 6'b00_0010;
6'b00_0010 : address <= 6'b00_0011;
6'b00_0011 : address <= 6'b00_1010;
6'b00_1010 : address <= 6'b01_0001;
6'b01_0001 : address <= 6'b01_1000;
6'b01_1000 : address <= 6'b10_0000;
6'b10_0000 : address <= 6'b01_1001;
6'b01_1001 : address <= 6'b01_0010;
6'b01_0010 : address <= 6'b00_1011;
6'b00_1011 : address <= 6'b00_0100;
6'b00_0100 : address <= 6'b00_0101;
6'b00_0101 : address <= 6'b00_1100;
6'b00_1100 : address <= 6'b01_0011;
6'b01_0011 : address <= 6'b01_1010;
6'b01_1010 : address <= 6'b10_0001;
6'b10_0001 : address <= 6'b10_1000;
6'b10_1000 : address <= 6'b11_0000;
6'b11_0000 : address <= 6'b10_1001;
6'b10_1001 : address <= 6'b10_0010;
6'b10_0010 : address <= 6'b01_1011;
6'b01_1011 : address <= 6'b01_0100;
6'b01_0100 : address <= 6'b00_1101;
6'b00_1101 : address <= 6'b00_0110;
6'b00_0110 : address <= 6'b00_0111;
6'b00_0111 : address <= 6'b00_1110;
6'b00_1110 : address <= 6'b01_0101;
6'b01_0101 : address <= 6'b01_1100;
6'b01_1100 : address <= 6'b10_0011;
6'b10_0011 : address <= 6'b10_1010;
6'b10_1010 : address <= 6'b11_0001;
6'b11_0001 : address <= 6'b11_1000;
6'b11_1000 : address <= 6'b11_1001;
6'b11_1001 : address <= 6'b11_0010;
6'b11_0010 : address <= 6'b10_1011;
6'b10_1011 : address <= 6'b10_0100;
6'b10_0100 : address <= 6'b01_1101;
6'b01_1101 : address <= 6'b01_0110;
6'b01_0110 : address <= 6'b00_1111;
6'b00_1111 : address <= 6'b01_0111;
6'b01_0111 : address <= 6'b01_1110;
6'b01_1110 : address <= 6'b10_0101;
6'b10_0101 : address <= 6'b10_1100;
6'b10_1100 : address <= 6'b11_0011;
6'b11_0011 : address <= 6'b11_1010;
6'b11_1010 : address <= 6'b11_1011;
6'b11_1011 : address <= 6'b11_0100;
6'b11_0100 : address <= 6'b10_1101;
6'b10_1101 : address <= 6'b10_0110;
6'b10_0110 : address <= 6'b01_1111;
6'b01_1111 : address <= 6'b10_0111;
6'b10_0111 : address <= 6'b10_1110;
6'b10_1110 : address <= 6'b11_0101;
6'b11_0101 : address <= 6'b11_1100;
6'b11_1100 : address <= 6'b11_1101;
6'b11_1101 : address <= 6'b11_0110;
6'b11_0110 : address <= 6'b10_1111;
6'b10_1111 : address <= 6'b11_0111;
6'b11_0111 : address <= 6'b11_1110;
6'b11_1110 : address <= 6'b11_1111;
endcase
end
end
memory_block #(
.ADDR_WIDTH(6),
.DATA_WIDTH(10),
.MEMORY_SIZE(64)
) u_memory (
.clk(clk),
.rst_n(rst_n),
.cs_n(chip_select),
.we_n(write_enable),
.re_n(read_enable),
.addr(address),
.data_in(data_in),
.data_out(data_out)
);
endmodule
メモリブロック:
module memory_block #(
parameter ADDR_WIDTH = 4,
parameter DATA_WIDTH = 8,
parameter MEMORY_SIZE = 16
)(
input clk,
input rst_n,
input cs_n,
input we_n,
input re_n,
input [ADDR_WIDTH-1:0] addr,
input [DATA_WIDTH-1:0] data_in,
output reg [DATA_WIDTH-1:0] data_out
);
reg [DATA_WIDTH-1:0] memory [MEMORY_SIZE-1:0];
integer i;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
for (i = 0; i < MEMORY_SIZE; i=i+1) begin
memory[i] <= 0;
end
end
else if (we_n == 1'b1 && cs_n == 1'b0) begin
memory[addr] <= data_in;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
data_out <= 0;
end
else if (re_n == 1'b1 && cs_n == 1'b0) begin
data_out <= memory[addr];
end
else begin
data_out <= data_out;
end
end
endmodule
2.4 AHB-SRAMコントローラ
AHBスレーブインターフェースに基づくシングルポートSRAMコントローラを設計し、SRAMメモリとAHBバス間のデータ交換を実現します。AHBバス上の読み書き操作を標準SRAM読み書き操作に変換します。
SRAMサイズは4096x32ビット、AHBインターフェースデータサイズは固定32ビット、AHBインターフェースアドレス範囲は0x00000000~0x00003FFCです。シングルまたはバーストモードのデータ読み書き操作を実現します。
トップモジュール名はahb_sram_controllerとし、入出力機能は以下のように定義します:
| 名前 | 方向 | ビット幅 | 説明 |
|---|---|---|---|
| hclk | I | 1 | システムクロック |
| hresetn | I | 1 | システム非同期リセット、Low有効 |
| hwrite | I | 1 | 書き込み有効 |
| htrans | I | 2 | 現在の転送タイプ |
| hsize | I | 3 | 現在の転送サイズ |
| haddr | I | 32 | 読み書きアドレス |
| hburst | I | 3 | 現在のバーストタイプ |
| hwdata | I | 32 | 書き込みデータ |
| hready | O | 1 | 転送完了指示 |
| hresp | O | 2 | 転送応答 |
| hrdata | O | 32 | 読み出しデータ |
| sram_csn | O | 1 | SRAMチップ選択、Low有効 |
| sram_wen | O | 1 | SRAM書き込みイネーブル、Low有効 |
| sram_addr | O | 12 | SRAM読み書きアドレス |
| sram_din | O | 32 | SRAM書き込みデータ |
| sram_dout | I | 32 | SRAM読み出しデータ |
設計要件:
- Verilog実装コードは合成可能であること
- シミュレーションでは、様々な典型的な状況下でのデータ読み書きインターフェース信号波形を示すこと
設計アプローチ:
CPUのメモリアクセスはバイト(8ビット)単位で行われるため、メモリのデータ幅とバス幅が32ビットで揃っている場合、アクセスアドレスのシフトを考慮する必要があります。32ビットアクセスの場合はhaddrを2ビット左シフトし、16ビットアクセスの場合は1ビット左シフトし、8ビットアクセスの場合はシフト不要です。
コード実装:
module ahb_sram_controller (
input hclk,
input hresetn,
input hwrite,
input [1:0] htrans,
input [2:0] hsize,
input [31:0] haddr,
input [2:0] hburst,
input [31:0] hwdata,
output reg hready,
output reg [1:0] hresp,
output reg [31:0] hrdata,
output reg sram_csn,
output reg sram_wen,
output reg [11:0] sram_addr,
output reg [31:0] sram_din,
input [31:0] sram_dout
);
reg [31:0] write_mask;
always @(posedge hclk or negedge hresetn) begin
if(hresetn == 1'b0) begin
write_mask <= 0;
hready <= 1'b1;
hresp <= 2'b0;
hrdata <= 0;
sram_csn <= 1'b0;
sram_wen <= 1'b0;
sram_addr <= 0;
sram_din <= 0;
end
else begin
sram_wen <= hwrite & htrans[1];
sram_addr <= haddr[13:2];
end
end
always @(posedge hclk or negedge hresetn) begin
if(hresetn == 1'b0) begin
hrdata <= 0;
sram_din <= 0;
end
else begin
case (hsize[1:0])
2'b10: write_mask <= 32'hFFFFFFFF; // ワード書き込み
2'b01: write_mask <= (32'h0000FFFF << (16 * haddr[1])); // ハーフワード書き込み
2'b00: write_mask <= (32'h000000FF << (8 * haddr[1:0])); // バイト書き込み
default: write_mask <= 32'hFFFFFFFF;
endcase
sram_din <= (hwdata & write_mask) | (hrdata & ~write_mask);
hrdata <= sram_dout;
end
end
endmodule
SRAMモデル:
module sram_model #(
parameter ADDR_WIDTH = 12,
parameter DATA_WIDTH = 32,
parameter MEMORY_SIZE = 4096
)(
input clk,
input rst_n,
input cs_n,
input we_n,
input [ADDR_WIDTH-1:0] addr,
input [DATA_WIDTH-1:0] din,
output reg [DATA_WIDTH-1:0] dout
);
reg [DATA_WIDTH-1:0] memory [MEMORY_SIZE-1:0];
integer i;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
for (i = 0; i < MEMORY_SIZE; i=i+1) begin
memory[i] <= 0;
end
end
else if (we_n == 1'b1 && cs_n == 1'b0) begin
memory[addr] <= din;
end
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
dout <= 0;
end
else if (cs_n == 1'b0) begin
dout <= memory[addr];
end
end
endmodule
テストベンチ:
module ahb_sram_testbench ();
reg hclk;
reg hresetn;
reg hwrite;
reg [1:0] htrans;
reg [2:0] hsize;
reg [31:0] haddr;
reg [2:0] hburst;
reg [31:0] hwdata;
wire hready;
wire [1:0] hresp;
wire [31:0] hrdata;
wire sram_csn;
wire sram_wen;
wire [11:0] sram_addr;
wire [31:0] sram_din;
wire [31:0] sram_dout;
initial begin
hclk <= 1'b0;
hresetn <= 1'b0;
hwrite <= 1'b0;
htrans <= 2'b00;
hsize <= 3'b000;
haddr <= 32'h00000000;
hburst <= 3'b000;
hwdata <= 32'h00000000;
#20
hresetn <= 1'b1;
hwrite <= 1'b1;
htrans <= 2'b10;
hsize <= 3'b010;
#20
haddr <= 32'hfffffffc;
hwdata <= 32'h20211212;
#20
hsize <= 3'b001;
haddr <= 32'hfffffffE;
hwdata <= 32'habcd0000;
#20
hsize <= 3'b000;
haddr <= 32'hffffffff;
hwdata <= 32'h59000000;
#20
hwrite <= 1'b0;
end
always #10 hclk <= ~hclk;
ahb_sram_controller u_ahb_sram_ctrl(
.hclk(hclk),
.hresetn(hresetn),
.hwrite(hwrite),
.htrans(htrans),
.hsize(hsize),
.haddr(haddr),
.hburst(hburst),
.hwdata(hwdata),
.hready(hready),
.hresp(hresp),
.hrdata(hrdata),
.sram_csn(sram_csn),
.sram_wen(sram_wen),
.sram_addr(sram_addr),
.sram_din(sram_din),
.sram_dout(sram_dout)
);
sram_model #(
.ADDR_WIDTH(12),
.DATA_WIDTH(32),
.MEMORY_SIZE(4096)
) u_sram (
.clk(hclk),
.rst_n(hresetn),
.cs_n(sram_csn),
.we_n(sram_wen),
.addr(sram_addr),
.din(sram_din),
.dout(sram_dout)
);
endmodule