自己设计CPU学习之路——基于《Xilinx FPGA应用开发》
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_) beginif (reset_ == `ENABLE_) beginfor (i = 0;i < `DATA_D;i = i + 1) beginff[i] <= #1{`DATA_W{1'b0}};endend else beginif (we_ == `ENABLE_) beginff[addr] <= #1 d_in;endendendendmodule
2. ALU
module alu(input [2:0] a,b,input [1:0] sel,output reg [3:0] out
)always @(a,b,sel) begincase(sel)2'b00: out = a+b;2'b01: out = ~(a+b);2'b10: out = a<<1;2'b11: out = ~a;default:out = 4'b0000;endcaseend
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) beginif (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) beginif (rst) q <= 0;else begin q[7:1] <= q[6:0];q[0] <= data_in;endendendmodule
5. 使用6个D触发器实现一个6位的寄存器
module DFlipFlop (input clk,input clr_n, // 异步复位信号,低电平有效input D,output reg Q
);always @(posedge clk or negedge clr_n) beginif (!clr_n)Q <= 1'b0; // 异步复位时,输出清零elseQ <= D; // 非复位时,将输入数据加载到输出endendmodulemodule 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) beginif (!clr_n)q <= 6'b0; // 异步复位时,全部位清零elsefor (i = 0; i < 6; i = i + 1)DFlipFlop dff (.clk(clk),.clr_n(clr_n),.D(data_input[i]),.Q(q[i])); // 使用循环实例化六个D触发器endassign 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) beginclk_edge <= ~clk_edge; // 按键按下时切换时钟边沿endalways @(posedge clk_edge or posedge rst) beginif (rst)q <= 8'b0;elsebeginq[7:1] <= q[6:0];q[0] <= data_in;endend// 产生时钟脉冲always @(posedge clk_edge) beginclk_pulse <= 1'b1;endendmodule
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) beginif (srclr)shift_register <= 8'b0; // 异步复位时,寄存器清零elseshift_register <= {shift_register[6:0], serial_in}; // 数据移位endassign 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) beginif (q <= 0) q <= 0;else if (en) q <= q + 1;end
endmodule
//激励关键代码
initial forkckl = 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) beginif (p == N/2-1) beginp = 0;clk_N = ~clk_N;endelse 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) beginif (p == N-1) p <= 0;else p <= p + 1;endalways @(posedge clk) beginif (p == N - 1) clk_p <= ~clk_p;endalways @(negedge clk) beginif (p == (N-1)/2) clk_q <= ~clk_q;endassign 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) beginif (rst) begincount <= 0;end else begincount <= count + 1;endendassign 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) beginif (cnt == 25000000-1) beginclk_1HZ = ~clk_1HZ;cnt <= 0;end else begincnt = cnt + 1;endend
endmodule
计数模块
module second(clk_1HZ,clr,sec
);input clk_1HZ;input clr;output reg [7:0] sec;always @(posedge clk_1HZ or posedge clr) beginif (clr) beginsec <= 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) begincase (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;endcaseendassign 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) beginif (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) beginif (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) beginif (rst) beginfor (i = 0;i < 15;i = i + 1)reg_file[i] <= 0; end else if (enb == 1) beginif (r_w == 0) reg_file[sel] <= in;else out <= reg_file[sel];endend
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) beginsel_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) beginstate <= s0;PC <= 0;end else begincase (state)s0: beginPC <= 0;state <= s1;end s1: beginif (start == 1'b1) beginROM_en <= 1;state <= s2;endelse state <= s1;ends2: beginOPCODE <= IR[15:12];register <= IR[11:8];address <= IR[7:0];state <= s3;ends3: beginPC <= PC + 8'b1;state <= s4;ends4: begincase (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;endcaseends5: beginimm <= address;en_imm <= 1;state <= s5_2;ends5_2:beginsel_mux <= 0;en_alu <= 1;sel_alu <= 3'b000;state <= s5_3;ends5_3:beginen_rf <= 1;r_wf <= 0;sel_rf <= register;state <= s12;ends6:beginsel_rf <= IR[7:4];en_rf <= 1;r_wf <= 1;state <= s6_2;ends6_2:beginen_reg <= 1;state <= s6_3;ends6_3:beginsel_rf <= register;en_rf <= 1;r_wf <= 1;state <= s6_4;ends6_4:beginen_alu <= 1;sel_alu <= 3'b010;state <= s6_5;ends6_5:beginsel_rf <= register;en_rf <= 1;r_wf <= 0;state <= s12;ends7: beginsel_rf <= IF[7:4];en_rf <=1;r_wf <= 1;state <= s7_2;ends7_2: beginen_reg <= 1;state <= s7_3;ends7_3: beginsel_rf <= register;en_rf <= 1;r_wf <= 1;state <= s7_4;ends7_5: beginsel_rf <= register;en_rf <= 1;r_wf <= 0;state <= s12;ends8: beginen_rf <= 1;r_wf <= 1;sel_rf <= register;state <= s8_2;ends8_2: beginen_rf <= 1;sel_alu <= 3'b001;state <= s8_3;ends8_3: beginif (alu_zero == 1) PC <= address;state <= s12; ends9: beginsel_rf <= register;en_rf <= 1;r_wf <= 1;state <= s9_2;ends9_2: beginen_alu <= 1;sel_alu <= 3'b000;state <= s9_3;ends9_3: begincs_ram <= 1;wr_ram <= 1;addr_ram <= address;state <= s12;ends10: beginsel_rf <= IR[7:4];en_rf <= 1;r_wf <= 1;state <= s10_2;ends10_2: beginen_alu <= 1;sel_alu <= 3'b000;state <= s10_3;ends10_3:beginsel_rf <= register;en_rf <= 1;r_wf <= 0;state <= s12;ends11: beginimm <= address;en_imm <= 1;state <= s11_2;ends11_2: beginsel_mux <= 0;en_reg <= 1;state <= s11_3;ends11_3: beginsel_rf <= register;en_rf <= 1;r_wf <= 1;state <= s11_4;ends11_4: beginen_alu <= 1;sel_alu <= 3'b100;state <= s11_5;ends11_5: beginsel_rf <= register;en_rf <= 1;r_wf <= 0;state <= s12;ends12: state <= s1;done: state <= done;default:;endcaseendend
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) beginif (rst) begin:initinteger 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,Lo0pmemory[8]=16'b0010_0100_00000000;//MOV R4,R0memory[9]=16'b0111_0100_00000001;//RLR4,#1memory[10]=16'b1000_0100_00001010;//MOV 10H,R4memory[11J=16'b11110000 00001011;//haltfor(i=12;i<(2**N);i=i+1)//存储器其余地址存放0memory[i] = 0;end else begin:readif (rf) rom_data = memory[rom_addr];endend
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:p0if(cs) if (rd) dataout <= memory[addr];else if (wr) memory[addr] <= datain;else dataout <= 'bz;end
endmodule
4. 上Vivado
跑出来了,不知道对不对
相关文章:
自己设计CPU学习之路——基于《Xilinx FPGA应用开发》
1. 一个32组位宽为32的寄存器堆 框图 代码 regfile.h ifndef __FEGFILE_HEADER__define __REGFILE_HEADER__define HIGH 1b1define LOW 1b0define ENABLE_ 1b0define DISABLE_ 1b1define DATA_W 32define DataBus 31:0define DATA_D 32d…...
数据结构与算法:树
目录 树 定义 结构 二叉树 定义 结构 形式 满二叉树 完全二叉树 存储 链式存储结构 数组 孩子节点 父节点 应用 查找 维持相对顺序 遍历 深度优先遍历 前序遍历 中序遍历 后序遍历 广度优先遍历 层序遍历 二叉堆 定义 自我调整 操作 插入加点 删…...
Spark 【Spark SQL(一)DataFrame的创建、保存与基本操作】
前言 今天学习Spark SQL,前面的RDD编程要想熟练还是得通过项目来熟练,所以先把Spark过一遍,后期针对不足的地方再加强,这样效率会更高一些。 简介 在RDD编程中,我们使用的是SparkContext接口,接下来的Spar…...
026-从零搭建微服务-文件服务(二)
写在最前 如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。 源码地址(后端):https://gitee.com/csps/mingyue 源码地址(前端):https://gitee.com/csps…...
Jenkins 页面部分显示Http状态403 被禁止
前言 生产环境Jenkins部署了一段时间了,结果今天在流水线配置中,部分页面显示Jenkins 页面部分显示Http状态403 被禁止,修改配置点击保存之后偶尔也会出现这个。 问题 以下是问题图片 解决 在全局安全配置里面,勾选上启用代…...
ajax day4
1、promise链式调用 /*** 目标:把回调函数嵌套代码,改成Promise链式调用结构* 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中*/let pname axios({url: http://hmajax.itheima.net/api/province,}).t…...
8.Spring EL与ExpressionParser
Spring EL与ExpressionParser 文章目录 Spring EL与ExpressionParser介绍**使用SpEL来计算评估文字字符串表达式**使用SpEL来计算评估 bean 属性 – “item.name” 介绍 Spring表达式语言(SpEL)支持多种功能,并且可以测试这个特殊的“ExpressionParser”接口的表达…...
Go和Java实现迭代器模式
Go和Java实现迭代器模式 1、迭代器模式 迭代器模式是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道 集合对象的底层表示。 迭代器模式属于行为型模式。 意图:提供一种方法顺序访问一个聚合对象中各个…...
如何在 Vue.js 和 Nuxt.js 之间做出选择?
开篇 今天看了一位国外大佬的文章,主要是他对在项目中如何选择 Vue.js 或 Nuxt.js 的看法,欢迎大家在评论区发表看法,以下内容是他关于这个问题看法的整理,由于翻译水平有限,欢迎大家指正。 国外大佬的看法 Vue.js在开…...
(二十三)大数据实战——Flume数据采集之采集数据聚合案例实战
前言 本节内容我们主要介绍一下Flume数据采集过程中,如何把多个数据采集点的数据聚合到一个地方供分析使用。我们使用hadoop101服务器采集nc数据,hadoop102采集文件数据,将hadoop101和hadoop102服务器采集的数据聚合到hadoop103服务器输出到…...
Linux: network: dhcp: mtu 这个里面也有关于网卡的MTU设置;
https://linux.die.net/man/5/dhcp-options 需注意这个DHCP配置选项。 option interface-mtu uint16; This option specifies the MTU to use on this interface. The minimum legal value for the MTU is 68. 假如在网卡的配置文件中设置了dhcp获取IP信息,可能导…...
Android中使用图片水印,并且能够在线下载字体并应用于水印
Android中使用图片水印,并且能够在线下载字体并应用于水印 要在Android中使用图片水印,并且能够在线下载字体并应用于水印,可以按照以下步骤进行: 1.使用Picasso、Glide或其他图片加载库加载图片: ImageView imageV…...
HTTP文件服务
在工作中,往往会需要将文件同时共享给很多台电脑。 本篇介绍HHDESK的HTTP文件服务功能,通过浏览器,将本地资源共享给任意主机。 1 共享文件 首页——资源管理——服务端——“”,在弹出框中选择HTTP文件服务。 填写各项内容。…...
nginx配置获取客户端的真实ip
场景描述: 访问路径: A机器 - > B机器的 ->C虚拟机 : A机器为客户端用户,本地地址为 192.168.0.110 B机器为服务端反向代理服务器 本地地址为192.168.0.128 –>(192.168.56.1) C机器为B主机安…...
1990-2022上市公司董监高学历工资特征信息数据/上市公司高管信息数据
1990-2022上市公司董监高学历工资特征信息数据/上市公司高管信息数据 1、时间:1990-2022年(统计截止日期为 2022年7月) 2、指标:证券代码、统计截止日期、姓名、国籍、籍贯、籍贯所在地区代码、出生地、出生地所在地区代码、性别…...
Java程序连接 Mysql 超时问题 - 数据包过大,导致超时,# 配置网络超时时间 socketTimeout: 1800000
问题 Java程序连接 Mysql 超时问题 解决方法 如果存在 yml 等类似的配置文件,那么可以配置一下 socket 连接超时的参数,例如 # 配置网络超时时间 半小时,计算公式 60秒*1000毫秒*30分钟 socketTimeout: 1800000...
c++分层最短路(洛谷飞行路线)acwing版
分层最短路算法是在SPFA算法的基础上,将每个点分成若干层,从而使得每个点之间的转移只在同一层次或上下两个相邻层次之间进行,减少了每轮的迭代次数,优化了算法的效率。 #include <iostream> #include <cstdio> #inc…...
Python bs4 BeautifulSoup库使用记录
目录 介绍 安装 初始化 解析器 使用方法 优势 Python标准库 lxml HTML lxml XML html5lib 格式化输出 对象 tag Name 多值属性 其他方法 NavigableString BeautifulSoup Comment 遍历 子节点 父节点 兄弟节点 回退和前进 搜索 过滤器 字符串 正则表达…...
Jmeter系列-插件安装(5)
前言 jmeter4.0以上,如现在最新的5.2.1版本是有集成插件的只需要在官网下载 plugins-manager.jar 包,放在jmeter安装路径的lib/ext目录下即可使用:https://jmeter-plugins.org/install/Install/但并不能满足所有需求,仍然需要安装…...
spring aop源码解析
spring知识回顾 spring的两个重要功能:IOC、AOP,在ioc容器的初始化过程中,会触发2种处理器的调用, 前置处理器(BeanFactoryPostProcessor)后置处理器(BeanPostProcessor)。 前置处理器的调用时机是在容器基本创建完成时ÿ…...
使用Unity的Input.GetAxis(““)控制物体移动、旋转
使用Unity的Input.GetAxis("")控制物体移动、旋转 Input.GetAxis("") 是 Unity 引擎中的一个方法,用于获取游戏玩家在键盘或游戏手柄上输入的某个轴(Axis)的值。这里的 "" 是一个字符串参数,表示要…...
【CSS】画个三角形或圆形或环
首先通过调整边框,我们可以发现一些端倪 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><style>.box{width: 150px;height:150px;border: 50px solid black;}</style&g…...
AI项目六:基于YOLOV5的CPU版本部署openvino
若该文为原创文章,转载请注明原文出处。 一、CPU版本DEMO测试 1、创建一个新的虚拟环境 conda create -n course_torch_openvino python3.8 2、激活环境 conda activate course_torch_openvino 3、安装pytorch cpu版本 pip install torch torchvision torchau…...
记录YDLidar驱动包交叉编译时出现的一点问题
由于一不小心把交叉编译的系统根目录破坏了,所以一股脑将交叉编译系统根目录全删了重新安装,安装后,交叉编译发现ydlidar的ros包驱动出现了库无法链接的错误(刚刚还是好好的),但是又想不起来之前是怎么解决的了,所以还…...
嵌入式学习笔记(32)S5PV210的向量中断控制器
6.6.1异常处理的2个阶段 可以将异常处理分为2个阶段来理解。第一个阶段是异常向量表跳转;第二个阶段是进入了真正的异常处理程序irq_handler之后的部分。 6.6.2回顾:中断处理的第一个阶段(异常向量表跳转阶段)处理 (…...
linux下安装qt、qt触摸屏校准tslib
linux下安装qt 在 Linux 系统下安装 Qt,可以通过以下步骤进行操作:1. 下载 Qt 安装包:首先,你需要从 Qt 官方网站(https://www.qt.io/)下载适用于 Linux 的 Qt 安装包。选择与你的系统和需求相匹配的版本&…...
C++之unordered_map,unordered_set模拟实现
unordered_map,unordered_set模拟实现 哈希表源代码哈希表模板参数的控制仿函数增加正向迭代器实现*运算符重载->运算符重载运算符重载! 和 运算符重载begin()与end()实现 unordered_set实现unordered_map实现map/set 与 unordered_map/unordered_set对比哈希表…...
React Router,常用API有哪些?
react-router React Router是一个用于构建单页面应用程序(SPA)的库,它是用于管理React应用中页面导航和路由的工具。SPA是一种Web应用程序类型,它在加载初始页面后,通过JavaScript来动态加载并更新页面内容࿰…...
JVM类加载和双亲委派机制
当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把类加载到JVM,本文主要说明类加载机制和其具体实现双亲委派模式。 一、类加载机制 类加载过程: 类加载的过程是将类的字节码加载到内存中的过程,主要包括…...
P-MVSNet ICCV-2019 学习笔记总结 译文 深度学习三维重建
文章目录 5 P-MVSNet ICCV-20195.0 主要特点5.1 文章概述5.2 研究方法5.2.1 特征提取5.2.2 学习局域匹配置信5.2.3 深度图预测5.2.4 Loss方程MVSNet系列最新顶刊 对比总结5 P-MVSNet ICCV-2019 深度学习三维重建 P-MVSNet-ICCV-2019(原文、译文、批注) 下载 5.0 主要特点 …...
基层政府网站集约化建设报告/成都有实力的seo团队
注意事项: 1、下载前请关闭360、电脑管家等杀毒软件,否则会误报病毒导致无法安装; 2、安装PS/PR/AE插件合集前,请务必先安装好Adobe软件; 3、安装PS/PR/AE插件合集前,请务必关闭Adobe旗下所有软件。 安装步…...
可以做软件的网站有哪些内容吗/seo刷关键词排名软件
流程控制if-else语法:if 条件:语句else:语句例子:a1#使用方式一if a>1:print(大于1)else:print(小于等于1)#使用方式二print(大于1) if a>1 else print(小于等于1)输出:>>小于等于1>>小于等于1if-elif-else语法:if 条件:语句elif 条件:语句else:语句例子a1if…...
专业的网站建设公司/百度不能搜的十大禁词
我在做一个微服务调用的时候出现了被调接口传参失败问题 Feign是通过http协议调用服务的,后来发现是因为Gep和Maping不一致,还有使用feign时要记得给实体类加无参构造注解 同时这些注解都尽量一致,不然微服务调bug很麻烦。 这是调用者 这是…...
python做网站需要什么/美业推广平台
中国的每个公司都想赚钱,但是真正能够成功、能够伟大的公司不是仅仅说我能赚多少钱、能多快赚钱、这个技术能不能赚钱、何时能上市、谁能发财谁买房买车, 最后这可能是一个负效应。 这些伟大的公司主要都是源于创业者有巨大的理想,他的理想是…...
wordpress7比2主题破解版/国内网站排名
1 importjava.util.LinkedList;23 //ArrayList基于数组实现,所以它具备数组的特点,即查询速度较快,但是修改、插入的速度却有点儿慢。4 //下面将要介绍的LinkedList就是来解决这个问题的,LinkedList基于链表,与ArrayLi…...
2017建设厅网站/做seo需要投入的成本
从Frankred的博客上看到他post的几个出现在WinDev上的Brain-teaser,感觉很有意思,似乎有做文字游戏的味道。在WinDev上回答正确这四题中的两题,可是有机会获得ViewSonic V37 Pocket PCs大奖。事实上,奖品最后落到了两个幸运儿身上…...