1. 一个32组位宽为32的寄存器堆
- 框图
-
代码
- regfile.h
`ifndef __FEGFILE_HEADER__ `define __REGFILE_HEADER__ `define HIGH 1'b1 `define LOW 1'b0 `define ENABLE_ 1'b0 `define DISABLE_ 1'b1 `define DATA_W 32 `define DataBus 31:0 `define DATA_D 32 `define ADDR_W 5 `define AddrBus 4:0 `endif
- regfile.v
`include "regfile2.h" module regfile2 ( input wire clk, input wire reset_, input wire [`AddrBus] addr, input wire [`DataBus] d_in, input wire we_, output wire [`DataBus] d_out ); reg [`DataBus] ff [`DATA_D-1:0]; //寄存器序列 integer i; assign d_out = ff[addr]; always @(posedge clk or negedge reset_) begin if (reset_ == `ENABLE_) begin for (i = 0;i < `DATA_D;i = i + 1) begin ff[i] <= #1{`DATA_W{1'b0}}; end end else begin if (we_ == `ENABLE_) begin ff[addr] <= #1 d_in; end end end endmodule
2. ALU
module alu(
input [2:0] a,b,
input [1:0] sel,
output reg [3:0] out
)
always @(a,b,sel) begin
case(sel)
2'b00: out = a+b;
2'b01: out = ~(a+b);
2'b10: out = a<<1;
2'b11: out = ~a;
default:out = 4'b0000;
endcase
end
endmodule
3. 同步使能,异步复位的D触发器
module Dff (
input clk,
input clr,
input en,
input D,
output reg q,
output qb
);
assign qb = ~q;
always @(posedge clk or posedge clr) begin
if (clr) q <= 0;//异步复位
else if (en) q <= D;//同步使能
end
endmodule
这个Verilog模块实现了一个带有异步复位功能的D触发器。在这个模块中,异步复位由输入信号clr
控制。
异步复位的实现方式是,当clr
信号为高电平(假定高电平表示复位时),触发器的输出q
将被强制置为逻辑0,无论时钟信号clk
和使能信号en
的状态如何。这意味着,无论何时clr
信号变为高电平,都会立即将q
复位为0。
以下是对代码的解释:
-
assign qb = ~q;
行将qb
定义为q
的反相信号,即qb
始终是q
的逻辑反值。 -
always @(posedge clk or posedge clr) begin
声明一个始终块,该块在时钟上升沿(posedge clk
)或异步复位上升沿(posedge clr
)时触发。 -
if (clr) q <= 0;
行检查clr
信号的状态。如果clr
为高电平(即异步复位条件触发),则q
被赋值为0,实现了异步复位。 -
else if (en) q <= D;
行在没有异步复位的情况下,检查使能信号en
。如果en
为高电平,那么q
将被赋值为输入信号D
,实现了同步使能。
这个模块的功能是,当clr
信号为高电平时,无论何时都会将q
置为0,而当clr
信号为低电平且en
信号为高电平时,q
会根据输入信号D
的值来更新。这使得在需要时可以通过异步复位来立即清除触发器的状态。
4. 移位寄存器
module shift_reg (
input clk,
input rst,
input data_in,
output reg [7:0] q
);
always @(posedge clk) begin
if (rst) q <= 0;
else begin
q[7:1] <= q[6:0];
q[0] <= data_in;
end
end
endmodule
5. 使用6个D触发器实现一个6位的寄存器
module DFlipFlop (
input clk,
input clr_n, // 异步复位信号,低电平有效
input D,
output reg Q
);
always @(posedge clk or negedge clr_n) begin
if (!clr_n)
Q <= 1'b0; // 异步复位时,输出清零
else
Q <= D; // 非复位时,将输入数据加载到输出
end
endmodule
module SixBitRegister (
input clk,
input clr_n,
input [5:0] data_input,
output [5:0] data_output
);
reg [5:0] q; // 6位寄存器的输出
integer i;
always @(posedge clk or negedge clr_n) begin
if (!clr_n)
q <= 6'b0; // 异步复位时,全部位清零
else
for (i = 0; i < 6; i = i + 1)
DFlipFlop dff (
.clk(clk),
.clr_n(clr_n),
.D(data_input[i]),
.Q(q[i])
); // 使用循环实例化六个D触发器
end
assign data_output = q;
endmodule
6. 按键产生时钟脉冲,移位寄存器
module shift_reg (
input btn, // 按键输入,用于产生时钟脉冲
output reg clk_pulse, // 时钟脉冲信号
input rst,
input data_in,
output reg [7:0] q
);
reg clk_edge = 0;
always @(posedge btn) begin
clk_edge <= ~clk_edge; // 按键按下时切换时钟边沿
end
always @(posedge clk_edge or posedge rst) begin
if (rst)
q <= 8'b0;
else
begin
q[7:1] <= q[6:0];
q[0] <= data_in;
end
end
// 产生时钟脉冲
always @(posedge clk_edge) begin
clk_pulse <= 1'b1;
end
endmodule
7. 串入并出74SL64芯片
module ShiftRegister_74LS164 (
input clk, // 时钟输入
input srclr, // 异步复位输入
input serial_in, // 串行输入
output [7:0] parallel_out // 并行输出
);
reg [7:0] shift_register; // 移位寄存器存储器件
always @(posedge clk or posedge srclr) begin
if (srclr)
shift_register <= 8'b0; // 异步复位时,寄存器清零
else
shift_register <= {shift_register[6:0], serial_in}; // 数据移位
end
assign parallel_out = shift_register; // 并行输出与寄存器值关联
endmodule
8.同步使能、异步清零的16进制计数器
module counter_16(
input clk,
input clr,
input en,
output reg [3:0] q
);
always @(posedge clk or posedge clr) begin
if (q <= 0) q <= 0;
else if (en) q <= q + 1;
end
endmodule
//激励关键代码
initial fork
ckl = 0;
clr = 0;
en = 0;
forever begin
#10 clk = ~clk;
#25 clr = 1;
#55 clr = 0;
#35 en = 1;
end
join
上面的Verilog代码片段展示了一个 initial
块内的 fork-join
结构,该结构用于并发地控制信号 clk
、clr
和 en
的变化。以下是对这段代码的详细解释:
-
fork
和join
:fork
和join
是一对用于创建并发代码块的关键字。fork
标志着代码分支的开始,允许同时执行多个线程。join
表示所有分支线程都执行完毕后再继续执行后续的代码。在这个例子中,fork
启动了一个并发线程,而join
用于结束这个线程。 -
initial
块:initial
块是Verilog中用于模拟和初始化的代码块。在仿真开始时执行其中的代码。 -
初始化信号:在
initial
块的开头,clk
、clr
、和en
这三个信号都被初始化。它们的初始值分别是 0。 -
forever
循环:forever
关键字用于创建一个无限循环,表示其中的代码将一直执行下去。 -
#10
、#25
、#55
、#35
:这些是时间延迟操作符,用于指定等待的时间。#10
表示等待 10 个时间单位,#25
表示等待 25 个时间单位,以此类推。 -
时钟信号
clk
的翻转:#10 clk = ~clk;
表示在等待 10 个时间单位后,翻转时钟信号clk
的状态,从 0 到 1 或从 1 到 0。这模拟了时钟的周期性振荡。 -
异步复位信号
clr
的设置和清除:#25 clr = 1;
表示在等待 25 个时间单位后,将异步复位信号clr
设置为 1,表示触发异步复位。然后#55 clr = 0;
表示在等待 55 个时间单位后,将clr
再次设置为 0,表示清除异步复位。 -
使能信号
en
的设置和清除:#35 en = 1;
表示在等待 35 个时间单位后,将使能信号en
设置为 1,表示启用某些操作。请注意,en
之后没有清除,因此在整个仿真期间都会保持为 1。
9. 偶数分频
采用加法计数的方法,知识要对时钟的上升沿进行计数,因为输出波形的改变仅仅发生在时钟上升沿。
module divf_even (
input clk,
output reg clk_N
);
parameter N = 6;
integer p;
always @(posedge clk) begin
if (p == N/2-1) begin
p = 0;
clk_N = ~clk_N;
end
else p = p + 1;
end
endmodule
10. 奇数分频
奇数分频——错位异或法。对于实现占空比为50%的N倍奇数分频,首先进行上升沿出发的模N计数计数到一选定值时进行输出时钟翻转,得到一个占空比为50%的N分频时钟clk1;然后在下降沿,经过与上面选定时刻相差(N-1)/2时刻,反转另一个时钟,这样得到另一个占空比为50%的N分频时钟clk2.将clk1和clk2两个时钟进行异或运算,就得到了占空比为50%的奇数分频时钟。利用了相位差
module divf_oddn(
input clk,
output clk_N
);
parameter N = 3;
integer p = 0;
reg clk_p = 0,clk_q = 0;
always @(posedge clk) begin
if (p == N-1) p <= 0;
else p <= p + 1;
end
always @(posedge clk) begin
if (p == N - 1) clk_p <= ~clk_p;
end
always @(negedge clk) begin
if (p == (N-1)/2) clk_q <= ~clk_q;
end
assign clk_N = clk_p ^ clk_q;
endmodule
11. 2 n 2^n 2n 分频
module divf_2pown (
input clk,
input rst,
output clk2,
output clk4,
output clk8,
output clk16
);
reg [3:0] count;
always @(posedge clk) begin
if (rst) begin
count <= 0;
end else begin
count <= count + 1;
end
end
assign clk2 = count[0];
assign clk4 = count[1];
assign clk8 = count[2];
assign clk16 = count[3];
endmodule
12. 秒计数器
- 1s实现加1计数,计到59后再从零计数
- 同步清零,用拨码开关控制同步清零,led灯显示
top 模块
module second_top (
clk,bmkg0,led
);
input clk;
input bmkg0;
output [7:0] led;
wire [7:0] sec;
wire clk_1HZ;
second_divf U1(.clk_50MHZ(clk),
.clk_1HZ(clk_1HZ));
second U2(.clk_1HZ(clk_1HZ),
.clr(bmkg0),
sec(sec));
second_disp U3(.sec(sec),
.q(led));
endmodule
分频模块 50MHz–> 1Hz
module second_divf (
clk_50MHZ,clk_1HZ
);
input clk_50MHZ;
output reg clk_1HZ;
reg [25:0] cnt;
always @(posedge clk_50MHZ) begin
if (cnt == 25000000-1) begin
clk_1HZ = ~clk_1HZ;
cnt <= 0;
end else begin
cnt = cnt + 1;
end
end
endmodule
计数模块
module second(
clk_1HZ,clr,sec
);
input clk_1HZ;
input clr;
output reg [7:0] sec;
always @(posedge clk_1HZ or posedge clr) begin
if (clr) begin
sec <= 0;
end else if (sec == 59) sec <= 0;
else sec <= sec + 1;
end
endmodule
显示模块
module second_disp (
sec,q
);
input [7:0] sec;
output [7:0] q;
assign q = sec;
endmodule
13. 序列检测器
再连续信号中,检测是否包含“110”序列,当包含该序列时,指示灯就亮,否则指示灯灭。
顶层模块
module SerialTect_top (
clk,key,led
);
input clk;
input [1:0] key;
output led;
wire pulse;
wire [1:0] key_debounce;
IP_smg_divf U1(.clk_50MHz(clk),
.clk_190Hz(clk_190Hz));
IP_key_debounce U2(.key_debounce(key_debounce[0]),
.clk_190Hz(clk_190Hz),
.key0(key[1]));
IP_pulse_gen U4(.clk(clk),
.key(|key_bounce),
.pulse(pulse));
Serial_compare U5(.clk(pulse),
.serialData(key_debounce[1]),
.result(led));
endmodule
分频模块
按键消抖模块
脉冲信号模块
序列检测模块
module Serial_compare (
clk,serialData,result
);
input clk;
input serialData;
output result;
parameter s0 = 2'b00,s1 = 2'b01,s2 = 2'b10,s3 = 2'b11;
reg [1:0] next_st = s0;
always @(posedge clk) begin
case (next_st)
s0: if (serialData == 1'b1) next_st = s1;
else next_st = s0;
s1: if (serialData == 1'b1) next_st = s2;
else next_st = s0;
s2: if (serialData == 1'b1) next_st = s2;
else next_st = s3;
s3: if (serialData == 1'b1) next_st = s1;
else next_st = s0;
default: next_st = s0;
endcase
end
assign result = (next_st == s3)?1:0;
endmodule
14. 简易处理器设计
1. 设计要求
- 完成处理器指令集的设计
- 完成处理器的设计,要求能够识别处理指令集中的任何指令
- 设计一段程序,要求该段程序用到指令集中的所有指令,并通过处理器运行这段程序得到结果
2. 设计
- 处理器的组成结构
- 简易处理器的功能
完成 2*(0+1+2+…+10)=?
- 指令系统的设计
- 寄存器传输指令
- 装在指令
- 算术运算指令:完成加减运算
- 逻辑移位指令:完成左移操作
- 存储指令
- 分支指令
所有的指令都包含4位操作码和12位操作数
汇编语言描述
机器码描述
3. 设计实现
3.1 顶层设计
- CPU顶层测试模块
module cpu_mem_test (
clk,rst,key,duan,wei
);
input clk,rst;
input [1:0] key;
output [7:0] duan;
output [3:0] wei;
wire [39:0] rf_data;
wire start;
wire [7:0] PC;
wire [15:0] IR;
cpu_mem cpu_mem(
.clk(clk),
.rst(rst),
.start(start),
.rf_data(rf_data),
.PC(PC),
.IR(IF)
);
fpag_step_ctrl step_ctrl(
.clk(clk),
.rst(rst),
.key(key),
.start(start),
.duan(duan),
.wei(wei),
.PC(PC),
.IR(IR),
.rf_data(rf_data)
) ;
endmodule
- 含ROM和RAM的CPU设计
module cpu_mem (
clk,rst,start,rf_data,PC,IR
);
input clk,rst;
input start;
output [39:0] rf_data;
output [7:0] PC;
output [15:0] IR;
wire ROM_en;
wire [15:0] IR;
wire wr_ram,cs_ram;
wire [7:0] addr_ram;
wire [7:0] alu_out;
wire clk_n;
assign clk_n = ~clk;
cpu cpu(
.clk(clk),
.rst(rst),
.start(start),
.ROM_en(ROM_en),
.IR(IR),
.PC(PC),
.rf_data(rf_data),
.wr_ram(wr_ram),
.cs_ram(cs_ram),
.addr_ram(addr_ram),
.alu_out(alu_out)
);
rom rom_instruction(
.clk(clk_n),
.rst(rst),
.rd(ROM_en),
.rom_data(IR),
.rom_addr(PC)
);
ram ram_data(
.clk(clk_n),
.wr(wr_ram),
.cs(cs_ram),
.addr(addr_ram),
.datain(alu_out)
);
endmodule
- 将CPU进一步规划成datapath和controller
- cpu 内部模块划分——包括数据路径和控制器
module cpu (
clk,rst,start,ROM_en,IR,
PC,rf_data,wr_ram,cs_ram,addr_ram,
alu_out
);
input clk,rst;
input start;
input [15:0] IR;
output [7:0] PC;
output ROM_en;
output wr_ram,cs_ram;
output [7:0] addr_ram;
output [7:0] alu_oout;
output [39:0] rf_data;
wire [7:0] imm;
wire [3:0] sel_rf;
wire [2:0] sel_alu;
wire sel_mux;
wire r_wf,en_rf,en_reg,en_alu,en_imm,alu_zero;
wire clk_n;
assign clk_n = ~clk;
dp datapath(
.rst(rst),
.clk(clk_n),
.r_wf(r_wf),
.en_rf(en_rf),
.en_reg(en_reg),
.en_alu(en_alu),
.en_imm(en_imm),
.sel_rf(sel_rf),
.sel_alu(sel_alu),
.sel_mux(sel_mux),
.imm(imm),
.alu_zero(alu_zero),
.alu_out(alu_out),
.rf_data(rf_data)
);
ctrl controller(
.rst(rst),
.start(start),
.clk(clk),
.alu_zero(alu_zero),
.r_wf(r_wf),
.en_rf(en_rf),
.en_reg(en_reg),
.en_alu(en_alu),
.en_imm(en_imm),
.sel_rf(sel_rf),
.sel_alu(sel_alu),
.sel_mux(sel_mux),
.imm(imm),
.PC(PC),
.IR(IR),
.ROM_en(ROM_en),
.wr_ram(wr_ram),
.cs_ram(cs_ram),
.addr_ram(addr_ram)
);
endmodule
- 数据路径部分细分框图
- 数据路径顶层文件
module dp(
rst,clk,r_wf,en_rf,en_reg,en_alu,en_imm,sel_rf,
sel_alu,sel_mux,imm,alu_zero,alu_out,rf_data
);
input rst,clk,r_wf,en_rf,en_reg,en_alu,en_imm;
input [7:0] imm;
input [2:0] sel_alu;
input [3:0] sel_rf;
input sel_mux;
output alu_zero;
output [39:0] rf_data;
output [7:0] alu_out;
wire [7:0] op1,op2,out_imm,out_rf;
register register0(
.clk(clk),
.en(en_reg),
.in(op1),
.out(op2)
) ;
register register1(
.clk(clk),
.en(en_imm),
.in(imm),
.out(out_imm)
);
mux21 mux0(
.sel(sel_mux),
.in1(out_imm),
.in2(out_rf),
.out(op1)
);
alu alu0(
.clk(clk),
.en(en_alu),
.sel(sel_alu),
.in1(op1),
.in2(op2),
.out(alu_out),
.alu_zero(alu_zero)
);
rf rf0(
.rst(rst),
.clk(clk),
.r_w(r_wf),
.enb(en_rf),
.in(alu_out),
.sel(sel_rf),
.out(out_rf),
.rf_data(rf_data)
);
endmodule
3.2 基本部件设计
- ALU
module alu (
clk,en,sel,in1,in2,out,alu_zero;
);
input en,clk;
input [2:0] sel;
input [7:0] in1,in2;
output reg[7:0]out;
output reg alu_zero;
always @(posedge clk) begin
if (en)
case(sel)
3'b000: out = in1;
3'b001: if (in1 == 0) alu_zero = 1;else alu_zero = 0;
3'b010: out = in1 + in2;
3'b011: out = in1 - in2;
3'b100: out = in1<<in2;
default: ;
endcase
end
endmodule
- 异步使能寄存器
module register (
clk,en,in,out
);
input clk,en;
input [7:0] in;
output reg[7:0] out;
reg [7:0] val;
always @(posedge clk)
val <= in;
always @(en,val) begin
if (en == 1'b1) out <= val;
else ;
end
endmodule
- 通用寄存器
module rf (
rst,clk,r_w,enb,in,sel,out,rf_data
);
input rst,clk,enb,r_w;
input [7:0] in;
input [3:0] sel;
output reg[7:0]out;
output [39:0] rf_data;
reg [7:0] reg_file[0:15];
integer i;
assign rf_data = {reg_file[4],reg_file[3],
reg_file[2],reg_file[1],reg_file[0]};
always @(posedge rst or posedge clk) begin
if (rst) begin
for (i = 0;i < 15;i = i + 1)
reg_file[i] <= 0;
end else if (enb == 1) begin
if (r_w == 0) reg_file[sel] <= in;
else out <= reg_file[sel];
end
end
endmodule
- 二选一多路选择器
module mux21 (
sel,in1,in2,out
);
input sel;
input [7:0] in1,in2;
output[7:0] out;
assign out = (sel)?in2:in1;
endmodule
- 控制器
控制器提供必要的控制信号,使得数据流通过数据路径后达到预期的功能。控制器部分使用状态机计数来实现,这个状态机根据当前的状态和输入的信号值,输出更新后的状态和相应的控制信号。
module ctrl (
rst,start,clk,alu_zero,r_wf,en_rf,en_reg,en_alu,en_imm,
sel_rf,sel_alu,sel_mux,imm,PC,IF,ROM_en,wr_ram,
cs_ram,addr_ram
);
input rst,start,clk;
input alu_zero;
input [15:0] IR;
output reg r_wf,en_rf,en_reg,en_alu,en_imm;
output reg[3:0]sel_rf;
output reg[2:0]sel_alu;
output reg sel_mux;
output reg[7:0]imm,PC;
output reg ROM_en;
output reg wr_ram,cs_ram;
output reg[7:0]addr_ram;
parameter s0 = 6'b000000,s1 = 6'b000001,s2 = 6'b000010,
s3 = 6'b000011,s4 = 6'b000100,s5 = 6'b000101,s5_2 = 6'b000110,s5_3 = 6'b000111,
s6 = 6'b001000,s6_2 = 6'b001001,s6_3 = 6'b001010,
s6_4 = 6'b001000,s6_5 = 6'b001100,
s7 = 6'b001101,s7_2 = 6'b001110,s7_3 = 6'b001111,
s7_4 = 6'b010000,s7_5 = 6'b010001,
s8 = 6'b010010,s8_2 = 6'b010011,s8_3 = 6'b010100,
s9 = 6'b010101,s9_2 = 6'b010110,s9_3 = 6'b010111,
s10 = 6'b100000,s10_2 = 6'b100001,s10_3 = 6'b100010,
s11 = 6'b100011,s11_2 = 6'b100100,s11_3 = 6'b100101,
s11_4 = 6'b100110,s11_5 = 6'b100111,
s12 = 6'b101000,done = 6'b101001;
reg [5:0] state;
parameter loadi = 4'b0011,add = 4'b0100,sub = 4'b0101,
jz = 4'b0110,store = 4'b1000,shiftL = 4'b0111,reg2reg = 4'b0010,
halt = 4'b1111;
reg [3:0] OPCODE;
reg [7:0] address;
reg [3:0] register;
always @(posedge rst or posedge clk) begin
sel_mux <= 1'b1;
en_rf <= 1'b0;
en_reg <= 1'b0;
en_alu <= 1'b0;
en_imm <= 1'b0;
ROM_en <= 1'b0;
wr_ram <= 1'b0;
cs_ram <= 1'b0;
addr_ram <= 0;
if (rst) begin
state <= s0;
PC <= 0;
end else begin
case (state)
s0: begin
PC <= 0;
state <= s1;
end
s1: begin
if (start == 1'b1) begin
ROM_en <= 1;
state <= s2;
end
else state <= s1;
end
s2: begin
OPCODE <= IR[15:12];
register <= IR[11:8];
address <= IR[7:0];
state <= s3;
end
s3: begin
PC <= PC + 8'b1;
state <= s4;
end
s4: begin
case (OPCODE)
loadi: state <= s5;
add: state <= s6;
sub: state <= s7;
jz: state <= s8;
store: state <= s9;
reg2reg:state <= s10;
shiftL: state <= s11;
halt: state <= done;
default:state <= s1;
endcase
end
s5: begin
imm <= address;
en_imm <= 1;
state <= s5_2;
end
s5_2:begin
sel_mux <= 0;
en_alu <= 1;
sel_alu <= 3'b000;
state <= s5_3;
end
s5_3:begin
en_rf <= 1;
r_wf <= 0;
sel_rf <= register;
state <= s12;
end
s6:begin
sel_rf <= IR[7:4];
en_rf <= 1;
r_wf <= 1;
state <= s6_2;
end
s6_2:begin
en_reg <= 1;
state <= s6_3;
end
s6_3:begin
sel_rf <= register;
en_rf <= 1;
r_wf <= 1;
state <= s6_4;
end
s6_4:begin
en_alu <= 1;
sel_alu <= 3'b010;
state <= s6_5;
end
s6_5:begin
sel_rf <= register;
en_rf <= 1;
r_wf <= 0;
state <= s12;
end
s7: begin
sel_rf <= IF[7:4];
en_rf <=1;
r_wf <= 1;
state <= s7_2;
end
s7_2: begin
en_reg <= 1;
state <= s7_3;
end
s7_3: begin
sel_rf <= register;
en_rf <= 1;
r_wf <= 1;
state <= s7_4;
end
s7_5: begin
sel_rf <= register;
en_rf <= 1;
r_wf <= 0;
state <= s12;
end
s8: begin
en_rf <= 1;
r_wf <= 1;
sel_rf <= register;
state <= s8_2;
end
s8_2: begin
en_rf <= 1;
sel_alu <= 3'b001;
state <= s8_3;
end
s8_3: begin
if (alu_zero == 1)
PC <= address;
state <= s12;
end
s9: begin
sel_rf <= register;
en_rf <= 1;
r_wf <= 1;
state <= s9_2;
end
s9_2: begin
en_alu <= 1;
sel_alu <= 3'b000;
state <= s9_3;
end
s9_3: begin
cs_ram <= 1;
wr_ram <= 1;
addr_ram <= address;
state <= s12;
end
s10: begin
sel_rf <= IR[7:4];
en_rf <= 1;
r_wf <= 1;
state <= s10_2;
end
s10_2: begin
en_alu <= 1;
sel_alu <= 3'b000;
state <= s10_3;
end
s10_3:begin
sel_rf <= register;
en_rf <= 1;
r_wf <= 0;
state <= s12;
end
s11: begin
imm <= address;
en_imm <= 1;
state <= s11_2;
end
s11_2: begin
sel_mux <= 0;
en_reg <= 1;
state <= s11_3;
end
s11_3: begin
sel_rf <= register;
en_rf <= 1;
r_wf <= 1;
state <= s11_4;
end
s11_4: begin
en_alu <= 1;
sel_alu <= 3'b100;
state <= s11_5;
end
s11_5: begin
sel_rf <= register;
en_rf <= 1;
r_wf <= 0;
state <= s12;
end
s12: state <= s1;
done: state <= done;
default:;
endcase
end
end
endmodule
- 程序存储器
module rom (
clk,rst,rd,rom_data,rom_addr
);
parameter M = 16,N = 8;
input clk,rst,rd;
input [N-1:0] rom_addr;
output reg[M-1:0] rom_data;
reg [M-1:0] memory[0:2**N-1];
always @(posedge clk or posedge rst) begin
if (rst) begin:init
integer i;
memory[0]=16'b0011_0000 00000000;
//MOV RO,#0;
memory[1]=16'b0011_0001 00001010;
//MOV R1,#10;
memory[2]=16'b0011_0010_00000001;
//MOV R2,#1;
memory[3]=16'b0011 0011 00000000;
//MOV R3,#0;
memory[4]=16'b0110_0001 00001000;
//JZ R1,NEXT;
memory[5]=16'b0100_0000_00010000;
//ADD R0,R1;
memory[6]=16'b0101 0001 00100000;
//SUB R1,R2;
memory[7]=16'b0110_0011 00000100;
//JZ R3,Lo0p
memory[8]=16'b0010_0100_00000000;
//MOV R4,R0
memory[9]=16'b0111_0100_00000001;
//RLR4,#1
memory[10]=16'b1000_0100_00001010;//MOV 10H,R4memory[11J=16'b11110000 00001011;
//halt
for(i=12;i<(2**N);i=i+1)
//存储器其余地址存放0
memory[i] = 0;
end else begin:read
if (rf) rom_data = memory[rom_addr];
end
end
endmodule
- 数据存储器
module ram (
clk,rd,wf,cs,addr,datain,dataout
);
parameter M = 8,N = 8;
input rd,wr,cs,clk;
input [N-1:0]addr;
input [M-1:0]datain;
output reg[M-1:0] dataout;
reg [M-1:0] memory [0:2**N-1];
always @(posedge clk)
begin:p0
if(cs)
if (rd) dataout <= memory[addr];
else if (wr) memory[addr] <= datain;
else dataout <= 'bz;
end
endmodule