你觉得这篇文章怎么样? 帮助我们为您提供更好的内容。
Thank you! Your feedback has been received.
There was a problem submitting your feedback, please try again later.
你觉得这篇文章怎么样?
学习Verilog语言基础,在Chip Hack EDSAC Challenge上驱动纸带穿孔机
Chip Hack EDSAC Challenge成为2017年 Wuthering Bytes节日 的一部分。该活动由BCS Open Source Specialist Group (BCS OSSG)和 Computer Conservation Society (CCS)主办,由Embecosm提供,旨在向世界推广FPGAs 和硬件描述语言(HDL),本案例中介绍Verilog。
类似的活动以前也举办过,在今年合并推出了一些关键的事物,虽然这些事物不是最有趣的,但是包含了过去的见解。其中有趣的一点是,整个活动都是围绕FPGA工具链。
EDSAC
在上一篇文章中,我们讨论了EDSAC的背景。在早期的计算机时代,EDSAC是早期非常卓越的计算机。CCS和 The National Museum of Computing正在制作一个全尺寸的EDSAC复制品,其所用硬件和原来的机器一样。这已经接近完成状态,并且在短时间内,您不仅可以访问它,还可以在它上面运行代码。
硬件描述语言
HDL不这是一个术语,它影响着我们的日常生活。你的智能手机,电脑,手表,甚至是牙刷(如果你有电动牙刷的话),它们里面的设备都是用HDL设计的。世界上几乎所有的IC都含有某种形式的HDL。
HDL主要有两种VHDL和Verilog。这并不是说没有其他语言,但就像软件一样,有些语言相比而言更普遍。在某些方面,有些语言比其他语言功能更强大。虽然Verilog更倾向于芯片设计,VHDL更适用于FPGA,但这并不是相互排斥的,这两种语言都可用于这两个领域,就像Java和c++一样。
在Chip Hack活动中选择了Verilog语言,它比VHDL更像c语言,所以对于那些以前没有使用过HDL的人来说这是更好的选择。
硅的设计超出了范围
虽然HDL可以快速编码,但将其转换为物理硬件的过程相当复杂。因此,世界上只有屈指可数的几个硅铸造厂或 “fabs” 。生产晶片与最终形成芯片的过程是非常昂贵的——即使是运用旧的技术。大多数晶圆厂都是建立在很高的产量上,每天/周生产数以百万计的晶片与芯片。那么我们如何测试我们写的Verilog呢?
介绍现场可编程门阵列(FPGA)。自80年代中期以来,FPGA这个相对较老的技术,在某些应用之外的吸引力有限。一些原因造成了其局限性,但其中很主要的一个因素是成本。直到最近,它们都很昂贵——与ASIC不成比例,以至于不能成为商业电子产品。
它在改变,而且更倾向于节约成本,并且有一些设备选择FPGA在他们的设计中起主要的作用。HTC Vive VR耳机就是一个例子,使用 FPGAs来完成传统ASICs不能完成的设计。第二个例子是移动市场使用FPGA实现DSP功能,虽然一些软件可以做同样的工作,但它们完成同样的任务时,需要的功率比FPGA更大,示例包括语音识别。FPGA行业的大多数主要生产商已经开始生产“小型”的FPGA来填补这些功能所需。事实证明,所谓的“小”一点也不小,EDSAC能够很容易适配这些设备中最小的部分。
MyStorm — iCE40
myStorm是Alan Wood和Ken Boak最近创建的,一个基于FPGA设计的 Lattice iCE40。这个设计的催化剂是 Clifford Wolf的IceStorm项目,它提供了第一个完全开放的FPGA流程。myStorm项目诞生于市场上出现的FPGA流程与节约成本型FPGA之间。
开始
运行一种新语言可能会让人望而生畏,然而大多数软件语言都遵循同样的主题;软件通常以线性方式运行,并发代码不是标准。即使我们使用线程来并发代码,这样做也是相当明确的。当我们最终运行并发代码线程时,在CPU中,这些线程是逐个运行的,而不是并行运行的。当我们进入多核系统时,这种情况正在改变,大多数软件真正的并行计算是抽象的,我们不必担心。
这不是HDL的案例,Verilog看起来像C语言,然而我们所描述的是数字电路,它们不是一个一个运行的,它们是并行运行的。实际上,让系统按顺序运行时,需要特别注意,因为这不是硬件的标准。
在某种程度上,第一天的大部分时间都花在了最简单的设计上,以便有效地使用硬件。
我们都必须从某个地方着手,因此例1让一个LED灯发光是一个好的开始。人类可读的名称供给芯片配置,留下了单个Verilog文件:
module led (output led);
assign led =1;
endmodule
这很简单
从“led =”按钮迅速升级到闪烁的led灯。
module blink(input clk, output led);
reg [24:0] count;
assign led = count[24];
always @(posedge clk)
count <= count + 1;
endmodule
在这点上,我们已经从组合逻辑转换到顺序逻辑,从阻塞到非阻塞的分配。这是我们需要详细了解的一个关键的区别。
组合逻辑
当我们想象一个逻辑电路时,我们通常会想到组合逻辑。下面的电路就是一个很好的示例。与门将立即反映出异或与非门输入的变化,即并行任务。
顺序逻辑
为了使电路在顺序逻辑之上,我们需要对信号进行控制。通过在输出上使用D型触发器,我们可以极大地改变电路的性能。在这个示例中,我们将锁定输出并将其与内部时钟同步。
如上图所示,如果我们使用顺序逻辑,我们可能会错过输出“X”。然而,通过使用顺序逻辑
,我们保留了X的状态,直到我们准备就绪(状态“Y”)。
阻塞VS非阻塞
虽然解释起来有点困难,但是我们会使用代码呈现。输出n,输入我们希望存储的n - 1(n1)然后时钟输出y。
always @(posedge clk)
begin
n1 = n;
y = n1;
end
随着n的变化n1也在改变。因此,实际上在任何情况下n = n1。当n1最终取n时(这可能是一个复杂的组合逻辑块),我们也无法控制其结果。最终结果是y = n。
让我们将其更改为非阻塞:
always @(posedge clk)
begin
n1 <= n;
y <= n1;
end
在时钟的上升沿,n将被赋值为n1。y也会取n1的状态,但这一次是在时钟的边沿上,所以y = n- 1而不是n !
原创作品
随着活动的进展,我们很快掌握了获取EDSAC示例所需的(主要)技能。尽管取得了惊人的成就,但使用提供的代码与创建原创作品是不一样的。因此,在这一点上,我们被放开,以创造我们希望的任何东西。不想浪费花在 PSoC powered tape punch上的努力,我们决定为该活动创建一个清晰的标题来纪念。如果你读过上一篇文章,你可能已经注意到在里面拍摄的标题。
在最初尝试创建一个三重嵌套的状态机设计时,我们遇到了瓶颈,我们(非常感谢Embecosm的想法)认为创建数据流并直接从单个寄存器中轮转数据可能更简单。
我们使用含有时钟,由5位数据配置的punch,使用电子表格来创建清晰的模式变得非常简单。
从这里开始,构建一个465位长(93字符长)的数据流,并以465b为前缀,告诉Verilog如何存储数据:
465'b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111110101100010000011111100010111000000110011010110011000001111110100111110000011111100011000100000000000000011111100011000100000111110010011111000001000111111100010000011111101001110000000000000000011111001001111100000111111010011111000001111110001100010000011111001101101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
如果我们有下面的代码,我们就可以加载“out”,数据从移位寄存器移出分配给正确的引脚。
out <= data[464:460]; // output the top 5 bits of data
data <= data << 5; // shift the data for next time
下一步,我们需要一个状态机来控制操作状态:
- 无所事事/不做事/重新装车
- 穿孔维护数据
- 离开维护数据并穿孔
这相当于一个4状态的状态机:
// The state machine
// 0 - initial state
// action: get the next 5-bits
// goto state 1
// 1 - assert punch
// goto state 2
// 2 - deassert punch and initiate punching until done
// if not done goto state 0
// if done goto state 3
// 3 - idle state
// goto state 3
reg [1:0] state = 3;
经过大量的编码和少量的实验,我们最终得到了下面的代码,它曾经加载到FPGA上,让我们的核心内容有了清晰的标题:
module punch(input clk, input reset ,input but0, output led,output led2,output led3, output led4, output D8, output D7, output D6, output D5, output D4, output pclk);
reg slowclk;
reg [4:0] out; // register to hold output
// reg punch; // punch control not used
reg [7:0] charcount; // Number of 5-bit char blocks. Enough for up to 256 chars (this would include lead in and out)
// The state machine
// 0 - initial state
// action: get the next 5-bits
// goto state 1
// 1 - assert punch
// goto state 2
// 2 – de assert punch
// goto state 0
// 3 - idle state
// goto state 3
reg [1:0] state = 3;
// The data to punch
reg [464:0] data;
assign {D8,D7,D6,D5,D4} = {out}; // map the output pins to the data
reg [21:0] count; // register to hold clock counter
assign slowclk = count[21]; // create a much slower 100Mhz/65536 around 1.5khz
// increment the counter when we get a clock
always @(posedge clk)
count <= count + 1;
// State machine code
always @(posedge slowclk) begin
if (reset == 1'b0) begin
pclk <= 1'b0; // pclock is the Punch out clock
state <= 3; // Idle state
led4 <= 1'b0; // status leds
end
else begin
case (state)
0: begin
// Initial state
out <= data[464:460]; // out takes the top 5 bits of data
data <= data << 5; // shift data for next time
state <= 1; // on the next clock start state 1
led <=1'b0; // status leds
led2 <=1'b1; // status leds
led3 <=1'b1; // status leds
led4 <=1'b1; // status leds
end
1: begin
// Assert punch
pclk <= 1'b1; // punch (neg edge triggered) clock high
charcount <= charcount - 1; // Do here, so ready by next state;
state <= 2; // on the next clock start state 2
led2 <= 1'b0; // status leds
end
2: begin
// Deassert punch, which will trigger the action (negedge)
pclk <= 1'b0; // punch (neg edge triggered) clock low so clock in and punch
led3 <=1'b0; // status leds
state <= (charcount == 4'b0) ? 3 : 0; // if statement equivalent of if(charcount = 0000) then state=3 else state =0 e.g. wait for all chars to be punched before idling
end
3: begin
// If we get here, wait for buttun0 or reset.
led <=1'b1; // status leds
// this is the data to punch
data <= 465'b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111110101100010000011111100010111000000110011010110011000001111110100111110000011111100011000100000000000000011111100011000100000111110010011111000001000111111100010000011111101001110000000000000000011111001001111100000111111010011111000001111110001100010000011111001101101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
charcount <= 93; // load the char count
state <= (but0 == 1'b0) ? 0 : 3;// if statement equivalent of if(but = 0) then state=0 else state =3... e.g. wait for button before punching
end
endcase
end
end
endmodule
总结
我们在Chip Hack EDSAC Challenge中玩得很开心。如果您想要自己尝试EDSAC和编码,甚至运行自己的Chip Hack,那么所有的notes和workshop材料都可以在chiphack.org上找到。
Verilog是一款非常强大的工具,虽然很难掌握,但我们期待在将来能够更频繁地使用到它。
Karl Woodward